高可用设计
号段模式需要考虑高可用性,确保服务始终可用。
号段模式的 ID 全部来自一个中心化的发号服务。业务应用有十个副本还是一百个副本都不要紧,只要发号服务背后的数据库抖一下,所有发号请求就会一起卡住。双 Buffer 解决的是”取号慢”,解决不了”取不到号”——所以这一章要谈的是故障边界:哪些故障会让发号暂停,降级方案按什么顺序切换,以及故障恢复之后怎么保证不发出重复的 ID。
存储层要做的是主从复制和故障转移:主库写入号段,从库同步,主库故障时把从库提升为新主库。这里有一条硬约束——号段表的水位不能在切换之后回退,否则会重新发出已经用过的 ID。缓存层要缓存当前号段,让数据库不可用时应用还能继续发号,代价是必须处理缓存与数据库两份状态的一致性。服务层则是多节点部署同一个发号服务,前面挂负载均衡,单节点故障时由其他节点接管。
监控上要盯住 QPS、延迟、错误率、Buffer 使用率、数据库连接数和 Redis 连接数,并按等级设置告警阈值:QPS 低于阈值报 P3,延迟 P99 超过阈值报 P2,错误率超过阈值报 P1。
读完这一章,你应该能画出号段模式的高可用拓扑,写出数据库故障和 Redis 故障两种场景下的降级顺序,并解释为什么降级链路的末端是雪花算法和 UUID,以及切换之前需要满足什么前提。
1. 多节点部署
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 节点 A │ │ 节点 B │ │ 节点 C │
│号段模式 │ │号段模式 │ │号段模式 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└────────────┼────────────┘
│
负载均衡器
2. 数据库高可用
主从复制:
DB 主库:写入
DB 从库:读取
故障转移:
主库故障 → 从库提升为主库
服务切换到新主库
3. Redis 缓存
缓存号段: 把发号表里的当前号段同步一份到 Redis,应用侧从 Redis 取号段并缓存在本地内存,数据库退居为号段水位的权威来源,只负责异步推进 max_id。
好处是数据库短时不可用时,应用还能从 Redis 继续发号,可用的窗口被拉长;代价是引入了缓存和数据库两份状态。Redis 重启或持久化策略不当都可能导致序列回退,所以缓存号段必须配合持久化,并在恢复之后校验序列水位。
1. 数据库故障
降级方案: 数据库不可用时,先看 Redis 里还有没有剩余号段:有就继续从缓存发号,直到缓存耗尽;缓存也耗尽后,先切到已经预分配好机器 ID 的雪花算法继续发号,再不行才退到 UUID 这种牺牲有序性但保证不重复的方案。
这里有一个前提容易被忽略:降级到雪花算法之前,机器 ID 必须已经分配完成并保证不冲突,否则降级反而会制造出重复 ID。无论走到哪一级降级,都不应该退回本地单点发号。
2. Redis 故障
降级方案: Redis 不可用时,如果号段表还在数据库里,直接回退到数据库取号,用一部分性能换可用性;数据库也不可用时,再按前面的顺序切到雪花算法和 UUID。
需要注意 Redis 的一个固有特性:重启后序列可能回退。所以不能假设 Redis 恢复之后序列还在原处,恢复时应该先检查序列水位,确认没有回退再重新投入发号。
监控指标
QPS
延迟
错误率
Buffer 使用率
数据库连接数
Redis 连接数
告警规则
QPS < 阈值 → P3 告警
延迟 P99 > 阈值 → P2 告警
错误率 > 阈值 → P1 告警
1. 多级降级
主方案:号段模式
降级方案1:雪花算法
降级方案2:UUID
2. 完善监控
实时监控
告警机制
日志追踪
号段模式通过多级降级和完善的监控,可以实现高可用性。
了解了号段模式的高可用设计后,我们学习系统架构设计。
👉 下一章:系统架构设计
发现内容有问题?
告诉我们哪里需要改进。
