简单总结一下流行的分布式 id 的实现方法
雪花算法
snowflake 是 Twitter 开源的分布式 ID 生成算法.
核心思想是: 分布式 ID 固定是一个 long 型的数字, 一个 long 型占 8 个字节, 也就是 64 个 bit, 原始 snowflake 算法中对于 bit 的分配如下图:
第一个 bit 位是标识部分, 在 java 中由于 long 的最高位是符号位, 正数是 0, 负数是 1, 一般生成的 ID 为正数, 所以固定为 0
时间戳部分占 41bit, 这个是毫秒级的时间, 一般实现上不会存储当前的时间戳, 而是时间戳的差值 (当前时间 - 固定的开始时间)
这样可以使产生的 ID 从更小值开始; 41 位的时间戳可以使用 69 年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69 年
工作机器 id 占 10bit, 这里比较灵活, 比如, 可以使用前 5 位作为数据中心机房标识, 后 5 位作为单机房机器标识, 可以部署 1024 个节点
序列号部分占 12bit, 支持同一毫秒内同一个节点可以生成 4096 个 ID
snowflake 算法需要人工为每台机器去指定一个机器 id, 如果机器很多或者机器扩展时, 挨个配置肯定不太现实, 而且类似 docker 容器的流行, 使得这个机器 id 已经不能狭隘地停留在 "物理" 层面上了, 应该把机器 id 扩展为当前 "实例" 的 id, 比如百度开源的基于 snowflake 算法的 uid-generator, 在每个应用实例启动时, 会插一条记录到数据库并返回所谓的机器 id. 类似的还有美团开源的 leaf.
基于中间件
分布式 ID 和分布式锁有一些类似, 一般也可以依赖 MySQL,Redis,zk 等中间件, 其中 MySQL 基于 auto_increment, Redis 基于 incr, zk 基于有序节点.
分布式 id 要求 key 值不停地渐变, 所以为了提高性能, 一般会采用 "预生成" 策略, 即一次生成 N 个 id 的号段缓存在本地, 这样做还有另外一个好处, 就是哪怕中间件宕机一小会儿也没什么影响.
此外, 如果中间件部署架构是无中心的, 比如两个 master, 那么为了防止冲突, 一般采用初始 id 不一样但 "步长" 一样的策略, 比如两台 MySQL 的初始 id 为 1 和 2, 步长为 2, 则各自节点的 id 为 1,3,5...; 2,4,6... 不会冲突.
来源: http://www.bubuko.com/infodetail-3343804.html