分布式ID计划方案详解:从理论到实践

打印 上一主题 下一主题

主题 963|帖子 963|积分 2889

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
一、为什么需要分布式ID?

在分布式体系中,唯一ID的生成面对两大核心挑衅:

  • 全局唯一性:制止跨节点、跨数据中央的ID冲突。
  • 有序性:确保ID按时间或业务规则递增,提升数据库写入性能(如InnoDB的B+树索引)。
    传统单机自增ID(如MySQL AUTO_INCREMENT)无法满足分库分表、高并发等场景需求,因此需引入分布式ID方案。

二、主流分布式ID方案对比

方案优点缺点实用场景UUID简单、无中央化依赖无序、存储空间大、查询性能差临时标识、低并发场景数据库自增ID递增、易实现性能瓶颈、单点故障风险高中小规模、非高并发体系Redis生成ID高性能、原子操纵依赖Redis可用性、需维护集群中等并发、可容忍短时Redis不可用Snowflake算法高性能、趋势递增、去中央化依赖机器时钟、时钟回拨问题高并发、分布式服务Leaf(美团)高可用、支持多种模式部署复杂度高、依赖第三方组件大型互联网公司、高并发业务
三、方案详解与实现

1. UUID

原理:通过算法生成128位的全局唯一标识符,如 550e8400-e29b-41d4-a716-446655440000。
实现
  1. UUID uuid = UUID.randomUUID();
  2. String id = uuid.toString();
复制代码
缺点


  • 无序性:导致数据库索引频繁分裂,写入性能下降。
  • 存储成本:32位字符串占用空间大,作为主键时影响存储和查询服从。

2. 数据库自增ID

原理:使用数据库的自增字段,通过 REPLACE INTO 或 步长隔离 实现多节点ID分配。
实现(步长隔离)
  1. -- 节点1配置
  2. CREATE TABLE id_generator (
  3.   id INT AUTO_INCREMENT PRIMARY KEY
  4. ) AUTO_INCREMENT=1, STEP=2;
  5. -- 节点2配置
  6. CREATE TABLE id_generator (
  7.   id INT AUTO_INCREMENT PRIMARY KEY
  8. ) AUTO_INCREMENT=2, STEP=2;
复制代码
缺点


  • 扩展性差:新增节点需重新规划步长,汗青数据迁移困难。
  • 单点瓶颈:高并发下数据库压力大,需分库分表支持。

3. Redis生成ID

原理:使用Redis的 INCR 或 INCRBY 下令的原子性,生成递增ID。
实现
  1. // 初始化序列
  2. redisTemplate.opsForValue().set("order_id", 1000);
  3. // 获取ID
  4. Long id = redisTemplate.opsForValue().increment("order_id");
复制代码
优化方案


  • 批量获取:每次获取一个区间(如1~1000),淘汰Redis访问频率。
  • 集群部署:通过Lua脚本保证原子性,制止集群间数据不同等。

4. Snowflake算法

原理:生成64位Long型ID,结构为:时间戳(41位) + 机器ID(10位) + 序列号(12位)。
Snowflake ID结构
实现
  1. public class SnowflakeIdWorker {
  2.     private long workerId;      // 机器ID
  3.     private long sequence = 0L; // 序列号
  4.     private long lastTimestamp = -1L;
  5.     public synchronized long nextId() {
  6.         long timestamp = System.currentTimeMillis();
  7.         if (timestamp < lastTimestamp) {
  8.             throw new RuntimeException("时钟回拨异常");
  9.         }
  10.         if (timestamp == lastTimestamp) {
  11.             sequence = (sequence + 1) & SEQUENCE_MASK;
  12.             if (sequence == 0) { // 当前毫秒序列号用尽,等待下一毫秒
  13.                 timestamp = tilNextMillis(lastTimestamp);
  14.             }
  15.         } else {
  16.             sequence = 0L;
  17.         }
  18.         lastTimestamp = timestamp;
  19.         return ((timestamp - EPOCH) << TIMESTAMP_SHIFT)
  20.                 | (workerId << WORKER_ID_SHIFT)
  21.                 | sequence;
  22.     }
  23. }
复制代码
缺点


  • 时钟回拨:若机器时钟回调,可能导致ID重复。
  • 机器ID管理:需手动分配或依赖ZooKeeper等和谐服务。
优化变种


  • 美团Leaf-Snowflake:通过ZooKeeper管理机器ID,办理时钟回拨问题。
  • 百度UidGenerator:引入RingBuffer预生成ID,提升性能。

5. Leaf(美团)

原理:Leaf提供两种模式:


  • 号段模式:从数据库批量获取ID区间,淘汰数据库访问压力。
  • Snowflake模式:优化时钟回拨问题,支持容器化部署。
号段模式实现
  1. CREATE TABLE id_leaf (
  2.   biz_tag VARCHAR(128) PRIMARY KEY,  -- 业务标识
  3.   max_id BIGINT NOT NULL,            -- 当前最大ID
  4.   step INT NOT NULL                  -- 号段步长
  5. );
复制代码
  1. // 从数据库获取号段
  2. UPDATE id_leaf SET max_id = max_id + step WHERE biz_tag = 'order';
  3. SELECT max_id FROM id_leaf WHERE biz_tag = 'order';
复制代码
优势


  • 高可用:号段模式支持数据库故障时降级到本地缓存。
  • 高性能:Snowflake模式单机QPS可达数十万。

四、选型建议与最佳实践

1. 选型维度



  • 并发量:低并发(<1k QPS)选数据库/Redis,高并发选Snowflake/Leaf。
  • 有序性要求:分库分表需趋势递增,日志类数据可担当无序。
  • 运维成本:Snowflake需办理时钟问题,Leaf需维护中间件。
2. 最佳实践



  • 业务隔离:不同业务线使用独立的ID生成器(如订单ID与用户ID分离)。
  • 监控告警:实时监控ID生成器的QPS、时钟状态、号段斲丧速度。
  • 压测验证:上线前模拟高并发场景,验证ID生成性能和唯一性。

五、总结

方案核心优势核心挑衅UUID简单、无中央化无序、存储性能差数据库自增易实现、递增扩展性差、单点风险Redis高性能、原子操纵依赖外部存储Snowflake高性能、趋势递增时钟回拨、机器ID管理Leaf高可用、支持多模式部署复杂度高 终极建议


  • 中小型项目:优先考虑数据库自增或Redis。
  • 大型互联网应用:选择Leaf或定制化Snowflake变种。
  • 特别需求:需严酷单调递增时,可结合数据库与Snowflake(如Twitter的分布式自增ID)。
通过合理选择分布式ID方案,可显著提升体系的扩展性和稳定性,为业务增长奠定坚固基础! 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

曹旭辉

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表