这是 Beta 探索课程,内容结构、实验步骤和示例可能会继续调整。
设计原则
设计一个生产级的分布式 ID 系统,需要遵循一些核心设计原则。
1. 唯一性优先 ⭐⭐⭐⭐⭐
原则: 唯一性是最高优先级,所有其他特性都要为此让路。
实践:
2. 性能优先 ⭐⭐⭐⭐⭐
原则: 在不牺牲唯一性的前提下,追求最高性能。
实践:
✅ 本地生成,避免网络
✅ 批量获取,减少访问
✅ 无锁设计,提升并发
✅ 缓存优化,减少计算
3. 可用性优先 ⭐⭐⭐⭐⭐
原则: 服务必须保持高可用,不能成为单点故障。
实践:
✅ 多节点部署
✅ 无单点故障
✅ 快速故障转移
✅ 有降级方案
4. 简单性 ⭐⭐⭐⭐
原则: 在满足核心需求的前提下,保持系统简单。
实践:
✅ 避免过度设计
✅ 选择成熟方案
✅ 减少依赖组件
✅ 简化运维复杂度
1. 唯一性 vs 性能
权衡:
全局协调保证唯一 → 性能差
本地生成保证性能 → 唯一性难保证
选择:
小型系统:选择性能,接受短暂不一致
大型系统:选择唯一性,通过优化提升性能
2. 有序性 vs 性能
权衡:
严格有序 → 需要全局协调,性能差
趋势递增 → 性能好,满足大部分需求
选择:
大部分场景:选择趋势递增
特殊场景:需要严格有序时单独处理
3. 可用性 vs 一致性
权衡:
强一致性 → 可用性差
最终一致性 → 可用性好
选择:
ID 生成器:优先可用性
数据一致性:通过其他机制保证
1. 分层架构
┌─────────────────────────────────┐
│ 应用层 │
│ 业务调用 ID 生成服务 │
└────────────┬────────────────────┘
│
┌────────────▼────────────────────┐
│ 服务层 │
│ ID 生成逻辑、缓存、降级 │
└────────────┬────────────────────┘
│
┌────────────▼────────────────────┐
│ 数据层 │
│ 数据库、Redis、持久化 │
└─────────────────────────────────┘
2. 服务化
原则: ID 生成器应该是一个独立的服务。
优势:
✅ 统一管理
✅ 独立扩展
✅ 独立部署
✅ 独立监控
1. 多级降级
主方案:号段模式
↓
降级方案1:雪花算法
↓
降级方案2:UUID
↓
降级方案3:时间戳 + 随机数
2. 降级触发
降级不能靠人点按钮,必须由明确的触发条件自动切换。判断依据只有一个:主方案还能不能保证唯一性。
| 触发条件 | 判断方式 | 降级动作 | 恢复方式 |
|---|---|---|---|
| 号段服务超时 | 单次取号超过 200ms | 切到下一个降级方案 | 连续 10 次取号成功后退回主方案 |
| 号段服务不可用 | 连接失败,或 5xx 比例超过 1% | 切到下一个降级方案 | 探测到恢复后退回主方案 |
| 本地号段耗尽且取不到新号段 | 本地剩余量为 0 且取号失败 | 切到雪花算法 | 取到号段后退回主方案 |
| 数据库不可用 | 主库和从库都连不上 | 切到 UUID | 数据库恢复后退回主方案 |
两条硬规则:
- 只能逐级降级,不能跳级。降级方案本身也分好几级,跳级会让有序性直接掉到底,而且事后说不清是哪一级出的问题。
- 降级要快,恢复要慢。降级在故障发生的当下就生效,恢复则要连续观察一段时间(比如连续 10 次成功)再退回去,避免在临界点上反复横跳。
降级状态必须可观测:每次切换都要打点(切换前后的方案名、时间、原因),并作为指标暴露出来。一个悄悄降级着的系统,比一个直接报错的系统更难排查。
1. 核心指标
QPS
延迟(P50, P99, P999)
错误率
可用性
资源使用(CPU, 内存, 网络)
2. 告警策略
P0:系统完全不可用 → 立即处理
P1:部分故障 → 1小时内处理
P2:性能下降 → 24小时内处理
P3:资源预警 → 持续观察
1. 选择合适方案
小型系统:数据库自增 / Redis
中型系统:雪花算法
大型系统:号段模式
超大系统:号段模式 + 双 Buffer
2. 多方案组合
核心业务:号段模式
一般业务:雪花算法
临时业务:UUID
追踪业务:UUID
设计原则总结
| 原则 | 重要性 | 说明 |
|---|---|---|
| 唯一性 | ⭐⭐⭐⭐⭐ | 最高优先级 |
| 性能 | ⭐⭐⭐⭐⭐ | 极重要 |
| 可用性 | ⭐⭐⭐⭐⭐ | 极重要 |
| 简单性 | ⭐⭐⭐⭐ | 重要 |
| 可扩展性 | ⭐⭐⭐⭐ | 重要 |
| 可维护性 | ⭐⭐⭐⭐ | 重要 |
了解了设计原则后,我们学习完整的系统架构。
👉 下一节:完整架构
发现内容有问题?
告诉我们哪里需要改进。
