共计 1941 个字符,预计需要花费 5 分钟才能阅读完成。
业务场景与核心痛点
在金融级短信验证码、电商订单号等场景中,Claude 号码系统需要满足两个核心需求:全局唯一性和递增有序性。传统方案在高并发场景下暴露三大问题:

- 号码重复 :数据库自增 ID 在分库分表时出现冲突
- 序列化竞争 :多线程获取序列时产生锁竞争,TPS 从 2000 骤降到 300
- 数据库压力 :每秒万级请求导致主库 CPU 长期维持在 90% 以上
ID 生成方案横评
通过对比业界主流方案,我们得到如下性能基准(测试环境:4C8G 云服务器):
| 方案 | 吞吐量 (QPS) | 时延 (ms) | 是否有序 | 缺陷 |
|---|---|---|---|---|
| UUIDv4 | 50,000 | 0.2 | × | 无序导致索引分裂 |
| 数据库序列 | 1,200 | 15 | √ | 单点故障风险高 |
| Redis INCR | 8,000 | 5 | √ | 持久化时性能下降 50% |
| 雪花算法 | 25,000 | 0.5 | √ | 时钟回拨需处理 |
| 美团 Leaf | 35,000 | 0.8 | √ | 依赖 ZooKeeper |
分布式解决方案
混合架构设计
[客户端] → [API 网关] → [ID 生成集群] ←→ [Redis Cluster]
↑ ↖
└── [ZooKeeper] ←─┘
- 分段缓冲层 :采用双 Buffer 模式,每个 Worker 预分配 1000 个 ID 段
- 状态协调器 :通过 ZooKeeper 的 EPHEMERAL 节点检测存活状态
- 故障转移 :Redis 节点宕机时自动切换到本地缓存模式
核心代码实现(Java)
public class HybridIDGenerator {
private volatile Segment currentSegment;
private volatile Segment nextSegment;
// 双 Buffer 切换逻辑
public synchronized long nextId() throws IDGenException {if (currentSegment == null || !currentSegment.isAvailable()) {if (nextSegment != null && nextSegment.isAvailable()) {
currentSegment = nextSegment;
nextSegment = null;
// 异步加载下一个段
executor.submit(this::loadNextSegment);
} else {throw new IDGenException("Segment not ready");
}
}
return currentSegment.getAndIncrement();}
// Redis 分段获取实现
private Segment fetchSegmentFromRedis() {try (Jedis jedis = pool.getResource()) {Long start = jedis.incrBy("id_segment", 1000);
return new Segment(start, start + 999);
} catch (JedisException e) {logger.warn("Redis failed, fallback to DB", e);
return fetchSegmentFromDB(); // 降级逻辑}
}
}
Redis 集群关键配置
# redis-cluster-prod.yml
cluster:
nodes: 10.0.1.101:7001,10.0.1.102:7002,10.0.1.103:7003
max-redirects: 3
timeout: 2000ms
pool:
max-active: 500
max-wait: 100ms
min-idle: 50
# 必须配置的优化参数
notify-keyspace-events Ex
hash-max-ziplist-entries 512
性能验证
基准测试
在 8 节点集群上使用 JMeter 压测(持续 30 分钟):
| 并发线程数 | 传统方案 (QPS) | 本方案 (QPS) | P99 延迟 |
|---|---|---|---|
| 500 | 1,200 | 28,000 | 9ms |
| 2000 | 800 | 35,000 | 15ms |
| 5000 | 宕机 | 32,000 | 45ms |
故障注入测试
- 随机 kill 一个 Redis 节点:200ms 内完成流量切换
- 模拟网络分区:ZooKeeper 在 3 秒内触发重新选主
- 强制时钟回拨:采用历史最大 ID+ 1 的保守策略
生产环境避坑指南
- 时钟同步必须使用 NTP+chrony 双保险 :雪花算法对时钟敏感,曾因虚拟机时钟漂移导致重复 ID
- Redis 持久化选择 AOF+RDB 混合 :纯 RDB 在崩溃时可能丢失最近 1 秒分配的 ID 段
- 预加载阈值动态调整 :根据历史 QPS 曲线设置缓冲大小,例如大促期间从 1000 调整为 5000
- 禁用 THP 透明大页 :实测发现会导致 Redis 延迟波动达 300ms
开放性问题
当前方案在跨机房场景下仍存在挑战:
– 如何实现 ID 生成服务的异地多活?
– 当遇到区域性 Redis 故障时,降级到本地生成如何避免冲突?
– 在 Serverless 架构中如何保持 ID 生成的性能一致性?
正文完
