知识卡片

高可用设计:要写清楚"哪里会丢",而非假装100%可靠

普通读书笔记卡

内容

消息队列案例的高可用详细设计分三层,每一层都没有回避自己的极限失败场景,而是明确写出”在什么条件下会丢消息、丢了之后怎么办”。消息发送可靠性:业务服务器嵌入消息队列SDK,SDK支持轮询发送,当某个分组的主服务器无法发送时,SDK挑选下一个分组主服务器重发,依次尝试所有主服务器直到发送成功;如果全部主服务器都无法发送,SDK可以缓存消息也可以直接丢弃,具体策略由启动时的配置指定——但如果SDK缓存了未发送的消息、此时业务服务器又重启,缓存消息将永久丢失,这种情况SDK不做处理,业务方需要针对非常关键的消息自己实现永久存储功能。消息存储可靠性:消息存储在MySQL中,每个分组一主一备两台服务器,之间通过复制来保证存储高可用;但如果主备间出现复制延迟,恰好此时主服务器宕机导致数据无法恢复,部分消息会永久丢失,这种情况同样不做针对性设计,而是要求DBA监控主备复制延迟,超过30秒就及时告警处理。消息读取可靠性:每个分组一主一备,主服务器同时支持发送和读取,备服务器只支持读取;正常情况下备服务器不对外提供服务,只有备服务器判断主服务器故障时才对外提供读取服务;主备角色和分组信息通过配置指定,具体通过ZooKeeper做状态判断和决策——主备服务器启动时分别连接ZooKeeper,在/MQ/Server/[group]目录下建立EPHEMERAL临时节点(例如分组group1对应/MQ/Server/group1/master/MQ/Server/group1/slave),节点超时时间可配置,默认10秒。这三段设计共同体现了一个写文档的重要原则:高可用设计不是宣称”绝对不丢数据”,而是老老实实分析出系统在哪些具体条件下会丢数据、丢多少、由谁(SDK自动处理还是业务方自己兜底、还是靠DBA人工监控)来兜底这个风险,把”不可能100%可靠”这件事说清楚,比空喊一个不可能兑现的可用性指标更有工程价值。

参考来源

- 位置:《从零开始学架构》第50讲《架构实战:架构设计文档模板》"详细设计"之"高可用设计"(源文件:_epub-src/OEBPS/text00003.html) - 结论依据:原文说明"如果 SDK 缓存了一些消息未发送,此时恰好业务服务器又重启,则所有缓存的消息将永久丢失,这种情况 SDK 不做处理,业务方需要针对某些非常关键的消息自己实现永久存储的功能""如果主备间出现复制延迟,恰好此时 MySQL 主服务器宕机导致数据无法恢复,则部分消息会永久丢失,这种情况不做针对性设计,DBA 需要对主备间的复制延迟进行监控",直接支撑本卡关于"明确写出失败边界"的结论。 - 原始内容:如果 SDK 缓存了一些消息未发送,此时恰好业务服务器又重启,则所有缓存的消息将永久丢失,这种情况 SDK 不做处理……如果主备间出现复制延迟,恰好此时 MySQL 主服务器宕机导致数据无法恢复,则部分消息会永久丢失,这种情况不做针对性设计,DBA 需要对主备间的复制延迟进行监控,当复制延迟超过 30 秒的时候需要及时告警并进行处理