点击蓝色 "乔志勇笔记" 关注我哟
加个 "星标", 第一时间获取推送的文章哦
(1)架构设计的关键思维是判断和取舍, 程序设计的关键思维是逻辑和实现
(2)架构设计的主要目的是为了解决软件系统复杂度带来的问题.
一, 高性能
1, 单机软件系统
多线程, 多进程, 进程间通信, 多线程并发
2, 集群
任务分配 , 任务分解
二, 高可用
1, 计算高可用
2, 存储高可用
3, 高可用状态决策
(1)独裁式 (2)协商式 (3)民主式
三, 扩展性
1, 预测变化
2, 应对变化
四, 低成本
引入新技术 , 创造新技术
五, 安全
功能安全, 架构安全
六, 规模
功能, 数据
七, 伸缩性
(4)架构设计原则
1, 合适原则
2, 简单原则
3, 演化原则
(5)架构设计流程
一, 识别复杂度
示例: 前浪微博消息队列的复杂性
1, 高性能的消息读取
2, 高可用的消息写入
3, 高可用的消息储存
4, 高可用的消息读取
二, 设计备选方案
常见误区: 1, 设计最优秀的方案
2, 只做一个方案
3, 备选方案过于详细
示例: 前浪微博消息队列的备选方案
1, 开源的消息队列 kafka \ rocketmq
2,netty 集群 + MySQL 储存
3,netty 集群 + 自研储存系统
三, 评估和选择备选方案
1,360 环评: 列出我们需要关注的质量属性点, 然后分别从这些质量属性的维度去评估每个方案, 再综合挑选适合当时情况的最优方案
2, 按优先级选择: 即架构师综合当前的业务发展情况, 团队人员规模和技能, 业务发展预测等因素, 将质量属性按照优先级排序, 首先挑选满足第一优先级的, 如果方案都满足, 那就再看第二优先级...... 以此类推
示例:
架构师经过思考后, 给出了最终选择备选方案 2, 原因有:
排除备选方案 1 的主要原因是可运维性, 因为再成熟的系统, 上线后都可能出问题, 如果出问题无法快速解决, 则无法满足业务的需求; 并且 Kafka 的主要设计目标是高性能日志传输, 而我们的消息队列设计的主要目标是业务消息的可靠传输.
排除备选方案 3 的主要原因是复杂度, 目前团队技术实力和人员规模 (总共 6 人, 还有其他中间件系统需要开发和维护) 无法支撑自研存储系统(参考架构设计原则 2: 简单原则).
备选方案 2 的优点就是复杂度不高, 也可以很好地融入现有运维体系, 可靠性也有保障.
针对备选方案 2 的缺点, 架构师解释是:
备选方案 2 的第一个缺点是性能, 业务目前需要的性能并不是非常高, 方案 2 能够满足, 即使后面性能需求增加, 方案 2 的数据分组方案也能够平行扩展进行支撑(参考架构设计原则 3: 演化原则).
备选方案 2 的第二个缺点是成本, 一个分组就需要 4 台机器, 支撑目前的业务需求可能需要 12 台服务器, 但实际上备机 (包括服务器和数据库) 主要用作备份, 可以和其他系统并行部署在同一台机器上.
备选方案 2 的第三个缺点是技术上看起来并不很优越, 但我们的设计目的不是为了证明自己(参考架构设计原则 1: 合适原则), 而是更快更好地满足业务需求.
四, 详细方案设计
示例:
细化设计点 1: 数据库表如何设计?
数据库设计两类表, 一类是日志表, 用于消息写入时快速存储到 MySQL 中; 另一类是消息表, 每个消息队列一张表.
业务系统发布消息时, 首先写入到日志表, 日志表写入成功就代表消息写入成功; 后台线程再从日志表中读取消息写入记录, 将消息内容写入到消息表中.
业务系统读取消息时, 从消息表中读取.
日志表表名为 MQ_LOG, 包含的字段: 日志 ID, 发布者信息, 发布时间, 队列名称, 消息内容.
消息表表名就是队列名称, 包含的字段: 消息 ID(递增生成), 消息内容, 消息发布时间, 消息发布者.
日志表需要及时清除已经写入消息表的日志数据, 消息表最多保存 30 天的消息数据.
细化设计点 2: 数据如何复制?
直接采用 MySQL 主从复制即可, 只复制消息存储表, 不复制日志表.
细化设计点 3: 主备服务器如何倒换?
采用 ZooKeeper 来做主备决策, 主备服务器都连接到 ZooKeeper 建立自己的节点, 主服务器的路径规则为 "/MQ/server/ 分区编号 /master", 备机为 "/MQ/server/ 分区编号 /slave", 节点类型为 EPHEMERAL.
备机监听主机的节点消息, 当发现主服务器节点断连后, 备服务器修改自己的状态, 对外提供消息读取服务.
细化设计点 4: 业务服务器如何写入消息?
消息队列系统设计两个角色: 生产者和消费者, 每个角色都有唯一的名称.
消息队列系统提供 SDK 供各业务系统调用, SDK 从配置中读取所有消息队列系统的服务器信息, SDK 采取轮询算法发起消息写入请求给主服务器. 如果某个主服务器无响应或者返回错误, SDK 将发起请求发送到下一台服务器.
细化设计点 5: 业务服务器如何读取消息?
消息队列系统提供 SDK 供各业务系统调用, SDK 从配置中读取所有消息队列系统的服务器信息, 轮流向所有服务器发起消息读取请求.
消息队列服务器需要记录每个消费者的消费状态, 即当前消费者已经读取到了哪条消息, 当收到消息读取请求时, 返回下一条未被读取的消息给消费者.
细化设计点 6: 业务服务器和消息队列服务器之间的通信协议如何设计?
考虑到消息队列系统后续可能会对接多种不同编程语言编写的系统, 为了提升兼容性, 传输协议用 TCP, 数据格式为 ProtocolBuffer.
参考: 李运华的从 0 开始学架构
近期文章:
微服务架构 ---- 基本组件
微服务实战问题
微服务架构进阶
秒杀系统设计
分布式数据一致性理解
5 种分布式锁实现的对比?
Java 并发编程学习体系
java8 Stream 史上最全总结
Java 网络编程 "初探"
Redis 知识点总结
java 核心技术学习总结 (一)
spring 中 "投机取巧" 地限制 用户同时登陆
如果你喜欢本文
请长按二维码, 关注 乔志勇笔记
来源: http://www.tuicool.com/articles/au6nEfn