一个微博用户日均发送两条消息,后台统计显示当前日活跃用户仅50万,但消息队列系统却经常在高发时段崩溃。新来的架构师梳理后发现,问题根源在于业务子系统之间严重耦合,一个模块出问题就会牵连整个链条,引入消息队列系统成为破局关键。
复杂度分析先行
架构设计的本质目的是解决软件系统的复杂性,因此在动手设计前必须先搞清楚复杂在哪里。架构师采用排查法,从高性能、高可用、扩展性三个维度入手分析当前消息队列的痛点。
实际数据显示,高峰期每秒处理约350条消息写入,读取量是写入量的10倍左右。考虑到后续业务增长,设计目标按峰值的4倍设定,最终性能要求TPS达到1380,QPS达到13800。
四大核心复杂度
综合分析下来,消息队列的复杂性主要集中在四个方面:高性能消息读取、高可用消息写入、高可用消息存储、高可用消息读取。这四点决定了系统能否在突发流量下稳定运行。
高可用写入要求消息只要写入集群中一台服务器就算成功,而高可用存储则要确保单台服务器宕机时已写入的消息不丢失。高可用读取则关注在服务器故障时,已存储的消息仍能被正常消费。
备选方案设计
高性能消息读取属于计算高可用范畴,团队技术栈是Java,虽然C/C++在性能上有优势,但为了语言特性让整个团队切换并不划算。最终确定基于Netty网络库用Java开发。
高可用写入与高性能读取类似,可以采用集群方式满足。采用轮询算法分配,客户端将消息依次写入不同服务器,正常情况下消息写入一台就算成功,保证写入效率。
存储方案权衡
高可用存储和高可用读取是整个系统最复杂的部分。架构师第一时间想到MySQL主备复制方案,利用成熟的关系型数据库保证数据不丢,同时通过主备架构满足读取可用性。
但MySQL的关系模型并不契合消息队列的数据特点,于是又考虑自研文件存储方案。参考Kafka的做法,自行实现一套文件存储和复制机制,完全掌控底层细节。
360度环评对比
架构师列出三个备选方案的质量属性对比表,从性能、可用性、开发成本、运维难度、团队适应性等多个维度进行综合评估。备选方案1引入成熟Kafka,备选方案2是自研存储,备选方案3是MySQL主备。
最终选择备选方案2,主要原因有三点:团队能完全掌控技术细节避免黑盒问题,与现有技术体系融合度更高,长期维护成本可控。虽然开发周期稍长,但避免了外部依赖带来的不确定性。
方案细化落地
备选方案确定后需要进一步细化才能指导开发。主备决策采用ZooKeeper实现,主服务器路径规则为/MQ/分区编号/,备机为/MQ/分区编号/slave,节点类型为临时节点便于故障检测。
传输协议选用TCP保证可靠性,数据格式采用自定义二进制协议提升解析效率。还需要细化分区策略、消费进度记录、日志文件格式等具体设计点,形成完整的技术方案文档。
架构师的技术储备越丰富,备选方案就会越多,最终选择也会更贴合实际。你所在的项目遇到过因技术选型失误导致的线上故障吗?欢迎在评论区分享你的经历,点赞转发让更多同行看到真实案例。


