以“前浪微博”场景为例,谈谈架构设计流程四步曲(二)-英拿科技
作者|李运华编辑|何潇(接上篇文章)4架构设计第 3 步:评估和选择备选方案
在完成备选方案设计后,如何挑选出最终的方案也是一个很大的挑战小山回家。有时候我们要挑选最简单的方案,有时候要挑选最优秀的方案,有时候要挑选最熟悉的方案河铉雨,甚至有时候真的要领导拍板。因此关键问题是:这里的“有时候”到底应该怎么判断?
我的答案就是 “360 度环评”! 具体的操作方式为:列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。
针对上期提出的 3 个备选方案临漳天气预报,架构师组织了备选方案评审会议,参加的人有研发、测试、运维、还有几个核心业务的主管相府闺秀。1. 备选方案 1:采用开源 Kafka 方案
业务主管倾向于采用 Kafka 方案,因为 Kafka 已经比较成熟,各个业务团队或多或少都了解过 Kafka。
中间件团队部分研发人员也支持使用 Kafka,因为使用 Kafka 能节省大量的开发投入;但部分人员认为 Kafka 可能并不适合我们的业务场景,因为 Kafka 的设计目的是为了支撑大容量的日志消息传输,而我们的消息队列是为了业务数据的可靠传输。
运维代表提出了强烈的反对意见:首先,Kafka 是 Scala 语言编写的,运维团队没有维护 Scala 语言开发的系统的经验,出问题后很难快速处理;其次,目前运维团队已经有一套成熟的运维体系,包括部署、监控、应急等,使用 Kafka 无法融入这套体系,需要单独投入运维人力。
测试代表也倾向于引入 Kafka,因为 Kafka 比较成熟,无须太多测试投入。2. 备选方案 2:集群 + MySQL 存储
中间件团队的研发人员认为这个方案比较简单,但部分研发人员对于这个方案的性能持怀疑态度,毕竟使用 MySQL 来存储消息数据,性能肯定不如使用文件系统;并且有的研发人员担心做这样的方案是否会影响中间件团队的技术声誉,毕竟用 MySQL 来做消息队列,看起来比较“土”、比较另类。
运维代表赞同这个方案鸮人,因为这个方案可以融入到现有的运维体系中金陵塔碑文,而且使用 MySQL 存储数据,可靠性有保证,运维团队也有丰富的 MySQL 运维经验;但运维团队认为这个方案的成本比较高灵异便利店 ,一个数据分组就需要 4 台机器(2 台服务器 + 2 台数据库)。
测试代表认为这个方案测试人力投入较大,包括功能测试、性能测试、可靠性测试等都需要大量地投入人力。
业务主管对这个方案既不肯定也不否定,因为反正都不是业务团队来投入人力来开发,系统维护也是中间件团队负责,对业务团队来说,只要保证消息队列系统稳定和可靠即可。3. 备选方案 3:集群 + 自研存储系统
中间件团队部分研发人员认为这是一个很好的方案,既能够展现中间件团队的技术实力,性能上相比 MySQL 也要高;但另外的研发人员认为这个方案复杂度太高,按照目前的团队人力和技术实力,要做到稳定可靠的存储系统第七个读者,需要耗时较长的迭代,这个过程中消息队列系统可能因为存储出现严重问题,例如文件损坏导致丢失大量数据。
运维代表不太赞成这个方案,因为运维之前遇到过几次类似的存储系统故障导致数据丢失的问题,损失惨重。例如,MongoDB 丢数据、Tokyo Tyrant 丢数据无法恢复等。运维团队并不相信目前的中间件团队的技术实力足以支撑自己研发一个存储系统(这让中间件团队的人员感觉有点不爽)。
测试代表赞同运维代表的意见,并且自研存储系统的测试难度也很高,投入也很大。
业务主管对自研存储系统也持保留意见,因为从历史经验来看,新系统上线肯定有 bug,而存储系统出 bug 是最严重的,一旦出 bug 导致大量消息丢失,对系统的影响会严重。
针对 3 个备选方案的讨论初步完成后,架构师列出了 3 个方案的 360 度环评表:

列出这个表格后,无法一眼看出具体哪个方案更合适,于是大家都把目光投向架构师,决策的压力现在集中在架构师身上了。
架构师经过思考后,给出了最终选择备选方案 2,原因有:
排除备选方案 1 的主要原因是可运维性,因为再成熟的系统,上线后都可能出问题,如果出问题无法快速解决,则无法满足业务的需求;并且 Kafka 的主要设计目标是高性能日志传输,而我们的消息队列设计的主要目标是业务消息的可靠传输。
排除备选方案 3 的主要原因是复杂度,目前团队技术实力和人员规模(总共 6 人,还有其他中间件系统需要开发和维护)无法支撑自研存储系统(参考架构设计原则 2:简单原则)。
备选方案 2 的优点就是复杂度不高,也可以很好地融入现有运维体系,可靠性也有保障爱你长久。
针对备选方案 2 的缺点,架构师解释是:
备选方案 2 的第一个缺点是性能,业务目前需要的性能并不是非常高,方案 2 能够满足,即使后面性能需求增加,方案 2 的数据分组方案也能够平行扩展进行支撑(参考架构设计原则 3:演化原则)。
备选方案 2 的第二个缺点是成本,一个分组就需要 4 台机器,支撑目前的业务需求可能需要 12 台服务器,但实际上备机(包括服务器和数据库)主要用作备份,可以和其他系统并行部署在同一台机器上。
备选方案 2 的第三个缺点是技术上看起来并不很优越,但我们的设计目的不是为了证明自己(参考架构设计原则 1:合适原则),而是更快更好地满足业务需求。
最后,大家针对一些细节再次讨论后,李建群确定了选择备选方案 2。
通过“前浪微博”这个案例我们可以看出,备选方案的选择和很多因素相关,卞之琳断章并不单单考虑性能高低、技术是否优越这些纯技术因素无讼案例。业务的需求特点、运维团队的经验、已有的技术体系、团队人员的技术水平都会影响备选方案的选择。因此,同样是上述 3 个备选方案,有的团队会选择引入 Kafka黑白龙狼传,有的会选择自研存储系统。5架构设计第 4 步:详细方案设计
完成备选方案的设计和选择后邵家有女 ,我们终于可以长出一口气,因为整个架构设计最难的一步已经完成了,但整体方案尚未完成,架构师还需继续努力。接下来我们需要再接再励,将最终确定的备选方案进行细化,使得备选方案变成一个可以落地的设计方案沁县吧。
虽然我们在“前浪微博”消息队列的架构设计挑选了备选方案 2 作为最终方案,但备选方案设计阶段的方案粒度还比较粗,无法真正指导开发人员进行后续的设计和开发,因此需要在备选方案的基础上进一步细化。
下面我列出一些备选方案 2 典型的需要细化的点供参考,有兴趣的同学可以自己尝试细化更多的设计点。1. 细化设计点 1:数据库表如何设计?
数据库设计两类表,一类是日志表,用于消息写入时快速存储到 MySQL 中;另一类是消息表,每个消息队列一张表。
业务系统发布消息时,首先写入到日志表西点揭秘,日志表写入成功就代表消息写入成功;后台线程再从日志表中读取消息写入记录,将消息内容写入到消息表中。
业务系统读取消息时,从消息表中读取。
日志表表名为 MQ_LOG,包含的字段:日志 ID、发布者信息、发布时间、队列名称、消息内容。
消息表表名就是队列名称,包含的字段:消息 ID(递增生成)、消息内容、消息发布时间、消息发布者马兰矿贴吧。
日志表需要及时清除已经写入消息表的日志数据,消息表最多保存 30 天的消息数据。2. 细化设计点 2:数据如何复制?
直接采用 MySQL 主从复制即可,只复制消息存储表,不复制日志表。3. 细化设计点 3:主备服务器如何倒换?
采用 ZooKeeper 来做主备决策,主备服务器都连接到 ZooKeeper 建立自己的节点,主服务器的路径规则为“/MQ/server/ 分区编号 /master”,备机为“/MQ/server/ 分区编号 /slave”,节点类型为 EPHEMERAL急冻奇侠。
备机监听主机的节点消息,当发现主服务器节点断连后,备服务器修改自己的状态程序员鼓励师,对外提供消息读取服务。4. 细化设计点 4:业务服务器如何写入消息?
消息队列系统设计两个角色:生产者和消费者,每个角色都有唯一的名称。
消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,SDK 采取轮询算法发起消息写入请求给主服务器。如果某个主服务器无响应或者返回错误,SDK 将发起请求发送到下一台服务器僵尸流。5. 细化设计点 5:业务服务器如何读取消息?
消息队列系统提供 SDK 供各业务系统调用,SDK 从配置中读取所有消息队列系统的服务器信息,轮流向所有服务器发起消息读取请求。
消息队列服务器需要记录每个消费者的消费状态,即当前消费者已经读取到了哪条消息九龙剑宗,当收到消息读取请求时,返回下一条未被读取的消息给消费者。6. 细化设计点 6:业务服务器和消息队列服务器之间的通信协议如何设计?
考虑到消息队列系统后续可能会对接多种不同编程语言编写的系统,为了提升兼容性,传输协议用 TCP,数据格式为 ProtocolBuffer。
当然还有更多设计细节就不再一一列举,因此这还不是一个完整的设计方案柒牌男装官网,我希望可以通过这些具体实例来说明细化方案具体如何去做。