高可用设计

号段模式需要考虑高可用性,确保服务始终可用。

号段模式的 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. 完善监控

实时监控
告警机制
日志追踪

总结

号段模式通过多级降级和完善的监控,可以实现高可用性。


下一步

了解了号段模式的高可用设计后,我们学习系统架构设计。

👉 下一章:系统架构设计

发现内容有问题?

告诉我们哪里需要改进。