如何开始架构设计

点击蓝色“ 乔志勇笔记 ”关注我哟

加个“ 星标 ”,第一时间获取推送的文章哦

(1)架构设计的关键思维是判断和取舍,程序设计的关键思维是逻辑和实现

(2)架构设计的主要目的是为了解决软件系统复杂度带来的问题。

(3)软件系统复杂度的来源:

一、高性能

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. 细化设计点 1:数据库表如何设计?

  • 数据库设计两类表,一类是日志表,用于消息写入时快速存储到 MySQL 中;另一类是消息表,每个消息队列一张表。

  • 业务系统发布消息时,首先写入到日志表,日志表写入成功就代表消息写入成功;后台线程再从日志表中读取消息写入记录,将消息内容写入到消息表中。

  • 业务系统读取消息时,从消息表中读取。

  • 日志表表名为 MQ_LOG,包含的字段:日志 ID、发布者信息、发布时间、队列名称、消息内容。

  • 消息表表名就是队列名称,包含的字段:消息 ID(递增生成)、消息内容、消息发布时间、消息发布者。

  • 日志表需要及时清除已经写入消息表的日志数据,消息表最多保存 30 天的消息数据。

  1. 细化设计点 2:数据如何复制?

直接采用 MySQL 主从复制即可,只复制消息存储表,不复制日志表。

  1. 细化设计点 3:主备服务器如何倒换?

采用 ZooKeeper 来做主备决策,主备服务器都连接到 ZooKeeper 建立自己的节点,主服务器的路径规则为“/MQ/server/ 分区编号 /master”,备机为“/MQ/server/ 分区编号 /slave”,节点类型为 EPHEMERAL。

备机监听主机的节点消息,当发现主服务器节点断连后,备服务器修改自己的状态,对外提供消息读取服务。

  1. 细化设计点 4:业务服务器如何写入消息?

  • 消息队列系统设计两个角色:生产者和消费者,每个角色都有唯一的名称。

  • 消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,SDK 采取轮询算法发起消息写入请求给主服务器。如果某个主服务器无响应或者返回错误,SDK 将发起请求发送到下一台服务器。

  1. 细化设计点 5:业务服务器如何读取消息?

  • 消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,轮流向所有服务器发起消息读取请求。

  • 消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息,当收到消息读取请求时,返回下一条未被读取的消息给消费者。

  1. 细化设计点 6:业务服务器和消息队列服务器之间的通信协议如何设计?

考虑到消息队列系统后续可能会对接多种不同编程语言编写的系统,为了提升兼容性,传输协议用 TCP,数据格式为 ProtocolBuffer。

参考:李运华的从0开始学架构

近期文章:

微服务架构————基本组件

微服务实战问题

微服务架构进阶

秒杀系统设计

分布式数据一致性理解

5种分布式锁实现的对比?

Java并发编程学习体系

java8 Stream 史上最全总结

Java 网络编程”初探”

redis 知识点总结

java 核心技术学习总结 (一)

spring中”投机取巧”地限制 用户同时登陆

如果你喜欢本文

请长按二维码,关注 乔志勇笔记