分布式id生成方案
1. segment 号段模式
1.1 普通号段
1.2 双buffer优化优化
2. 雪花算法 或者改进
雪花算法 一位固定位+41时间戳+10机器码+12序列号
雪花算法缺点:
时钟回拨
- 记录最近一次生成时间进行比较,如果小于5ms等待两倍时间重试
- 跨度过大直接抛异常人工处理
3. 案例
美团Leaf:https://tech.meituan.com/2019...
leaf-segment 方案
- 优化:双buffer + 预分配
- 容灾:Mysql DB 一主两从,异地机房,半同步方式
- 缺点:如果用segment号段式方案:id是递增,可计算的,不适用于订单ID生成场景,比如竞对在两天中午12点分别下单,通过订单id号相减就能大致计算出公司一天的订单量,这个是不能忍受的。
leaf-snowflake方案
- 使用Zookeeper持久顺序节点的特性自动对snowflake节点配置workerID
- 1.启动Leaf-snowflake服务,连接Zookeeper,在leaf_forever父节点下检查自己是否已经注册过(是否有该顺序子节点)。
- 2.如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。
- 3.如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。
- 缓存workerID,减少第三方组件的依赖
- 由于强依赖时钟,对时间的要求比较敏感,在机器工作时NTP同步也会造成秒级别的回退,建议可以直接关闭NTP同步。要么在时钟回拨的时候直接不提供服务直接返回ERROR_CODE,等时钟追上即可。或者做一层重试,然后上报报警系统,更或者是发现有时钟回拨之后自动摘除本身节点并报警
- 使用Zookeeper持久顺序节点的特性自动对snowflake节点配置workerID
百度UIDGenerator: