改进的雪花算法——解决时钟回拨问题

原创 公众号: 软件设计活跃区

改进的雪花算法——姑且称为梨花算法吧(忽如一夜春风来,千树万树梨花开)。

改进目标:解决雪花算法的时钟回拨问题;部分避免机器id重复时,号码冲突问题。

分布式唯一ID的方案有很多,雪花算法,组成结构大致分为为符号位、时间位、机器位和序列号位。其特点是趋势递增、有序、纯数字组成查询效率高且不依赖于数据库。适合在分布式的场景中应用,可根据需求调整具体实现细节。

snowflake算法

这种方案把64-bit分别划分成多段,分开来标示机器、时间等,比如在snowflake中的64-bit分别表示如下图(图片来自网络)所示:

snowflake算法得到的ID是分段组成的:

•     1bit:符号位,固定是0,表示全部ID都是正整数

•     与指定日期的时间差(毫秒级),41位,够用69年

•     集群ID 机器ID, 10位,最多支持1024台机器

•     序列,12位,每台机器每毫秒内最多产生4096个序列号

41-bit的时间可以表示(1L<<41)/(1000L*3600*24*365)=69年的时间,10-bit机器可以分别表示1024台机器。如果我们对IDC划分有需求,还可以将10-bit分5-bit给IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,可以根据自身需求定义。12个自增序列号可以表示2^12个ID,理论上snowflake方案的QPS约为409.6w/s,这种分配方式可以保证在任何一个IDC的任何一台机器在任意毫秒内生成的ID都是不同的。

这种方式的优缺点是:

优点:

•   毫秒数在高位,自增序列在低位,整个ID都是趋势递增的。

作为DB表的主键,索引效率高。

•   不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。

高性能高可用:生成时不依赖于数据库,完全在内存中生成。

容量大:每秒中能生成数百万的自增ID。

•   可以根据自身业务特性分配bit位,非常灵活。

缺点:

•     强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。

•     可能会出现不是全局递增的情况。

改进的雪花算法——姑且称为梨花算法吧(忽如一夜春风来,千树万树梨花开)。

改进目标:解决雪花算法的时钟回拨问题;部分避免机器id重复时,号码冲突问题。

long型的64位分成以下几个部分组成:

符号位:1位

时间:31位   (精确到秒)够用68年

段号(批次号):3位    每秒可分为8个段

机器id号:10位   最多支持1024台机器

序列号:19位   可表示:0--524287

如下图所示:

注:根据情况,机器id号可以放到最后部分。

(一)

经过调整,时间只对秒灵敏,成功回避了服务器间几百毫秒的时间误差引起的时间回拨问题;若第59秒的8个段号没有用完,则当润秒来临时,还可继续使用。另外具体实现上,可设置一定的秒数(如3秒)内提前消费。比如第10秒的号码,在800毫秒用完了,可以继续使用第11秒的号码。这样,下1秒用的号码不是很多时,就可以借给上1秒使用。

以上的方案是与时间强相关的。若某一段时间内的号码没用使用,也会浪费掉。当在分布式DB的表主键这种应用场景时,只需要全局id不重复,且是递增的。类似这种场景,可以设计成时间不相关的。

(二)

供分布式DB表主键等类似场景使用的,不浪费号码的方案。long型的64位分配还是一样。只不过,取号时,是取上一个号码加1,而不用管现在的时间是什么时候。当突然down机时,重启又获取当前的时间,重新开始分派号码;这时之前节省下的号码就被浪费掉了。为解决这个问题,可以在一段时间或分派一定数量的号(如10000),就将当前分派的号码记录到日志,或同步到DB表,等重启时,可以设置初始值。实现上,还是要控制分派的速度,若每秒几百万的号不够用,可用表名分隔命名空间,每个表单独取自己的号;即使号码够用,也可以这样做,因为这样得到的号在同一张表里就比较连续,而不只是递增而矣。当各个机器分派的id速度相差太大时,各机器得到的id大小就比较乱;这种问题,可以设置负载均衡,让每台机器轮流出号。

(三)

机器id重复的问题。当两台机器的id一样时,分派的号就会重复。若0-7八个段号(段号3位),每次都是从0-3随机获取一个开始的段号,比方说获取到2,那重复机器id的服务要是获取到0或1的段号就可以避免号码重复的冲突。当然了,这都是基于每秒用不完号码的情况下的。可以循环使用段号,如获取到3,那就从3-7,0,1,2这样使用段号,后面0,1,2这几个段号要是分派出去,号码就不递增了。具体怎么用,还是要根据自己的情况做取舍。

Java版的梨花算法实现,期待下期与你一起讨论!

(  已实现, 有三种方式.

#1:SerialUniqueId  ,2:OneTimeSnowflakeId  ,3:PearFlowerId. default is 1.
bee.distribution.genid.idGenerator=1

源码地址:

https://github.com/automvc/bee

https://gitee.com/automvc/bee

https://github.com/automvc/bee/blob/master/src/main/java/org/teasoft/bee/distribution/GenId.java

)

欢迎关注微信公众号!

长按二维码可关注(公众号: AiTeaSoft)

        更多重磅文章等着你!

QQ群:   992650213

微信群:    IT软件设计交流群3

相关:

教你如何避开雪花算法的坑

https://blog.csdn.net/abckingaa/article/details/108653637

分布式全局唯一ID生成算法(改进的雪花算法——解决时钟回拨问题)相关推荐

  1. [分布式] ------ 全局唯一id生成之雪花算法(Twitter_Snowflake)

    雪花算法(Twitter_Snowflake) 我们知道,分布式全局唯一id的生成,一般是以下几种: 基于雪花算法生成 基于数据库 基于redis 基于zookeeper 本文说下雪花算法,后面附源码 ...

  2. java 唯一id生成算法_分布式全局唯一ID生成方案之snowflake算法

    已有的方案: 可大致分为: 完全依赖关系/非关系型数据库递增的方案 完全不依赖数据源作为生成因子的UUID 半依赖数据源作为生成因子的snowflake 为什么推荐snowflake? 这个问题,可以 ...

  3. 雪花算法及运用PHP,雪花算法生成全局唯一ID,参考了下网上雪花算法生成规则,机器ID和序列号自动获取 理论上毫秒可生成 1024*4096个唯一ID

    任务要求毫秒生成10000个唯一ID 研究了下twitter/snowflake的算法思想: 参考了下网上雪花算法生成规则,把数据中心和机器编号整合一起,变成10位机器ID, 机器ID和序列号自动获取 ...

  4. snowflake算法 php,Snowflake —— 分布式全局唯一 id 生成算法

    简介 Snowflake 是 Twitter 提出一种的分布式唯一序列号生成算法,理论上单节点 1 毫秒可以生成 4096 个(每秒四百万个)唯一序列,这个序列是个 long 类型的数字,在数据库中的 ...

  5. 微服务架构分布式全局唯一ID生成策略及算法

    全局唯一的 ID 几乎是所有系统都会遇到的刚需.这个 id 在搜索, 存储数据, 加快检索速度 等等很多方面都有着重要的意义.工业上有多种策略来获取这个全局唯一的id,针对常见的几种场景,我在这里进行 ...

  6. 分布式全局唯一ID的实现

    分布式全局唯一ID的实现 前言 上周末考完试,这周正好把工作整理整理,然后也把之前的一些素材,整理一番,也当自己再学习一番. 一方面正好最近看到几篇这方面的文章,另一方面也是正好工作上有所涉及,所以决 ...

  7. 全局唯一id生成之雪花算法

    雪花算法(Twitter_Snowflake) 我们知道,分布式全局唯一id的生成,一般是以下几种: 基于雪花算法生成 基于数据库 基于redis 基于zookeeper 本文说下雪花算法,后面附源码 ...

  8. c#随机数生成编号_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法...

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

  9. 微信用户全局唯一标识_忘掉 Snowflake,感受一下性能高出587倍的全局唯一ID生成算法...

    今天我们来拆解 Snowflake 算法,同时领略百度.美团.腾讯等大厂在全局唯一 ID 服务方面做的设计,接着根据具体需求设计一款全新的全局唯一 ID 生成算法.这还不够,我们会讨论到全局唯一 ID ...

最新文章

  1. 只有程序员才能看懂的30张图,绝配!
  2. 以下是ECMAScript 2016、2017和2018中所有新增功能的示例
  3. firefox input file宽度失效
  4. shell 写入文件_phpMyAdmin利用日志文件GetSHELL
  5. 使用plugins让打包更便捷
  6. 只开窗不镀锡_开窗也有大学问,只有老司机才懂这些车窗使用技巧
  7. win7 gho封装教程
  8. 软件著作权申请流程(自助申请免费登记)
  9. java语言飞机大战代码_飞机大战JAVA代码
  10. 计算机组成原理串行加法器延迟时间,2021考研408计算机组成原理:串行加法器和并行加法器...
  11. echart水滴_echart 水滴图
  12. RFID在图书馆系统管理中的有哪些应用优势?
  13. Linux 操作系统的体系结构
  14. Python操作excel基础
  15. 跨境网上收款 找PayPal没错(php如何实现paypal支付)
  16. c语言订餐系统项目范例,C语言订餐系统.doc
  17. 美团 键盘大小写转换 最小敲击次数
  18. 2021年电赛元器件物品清单
  19. 移动硬盘安装debian,支持BIOS和uefi双引导
  20. 张孝祥java面试大全

热门文章

  1. 【Java 线程池 概念+深析】简单理解
  2. ARM体系架构—ARMv7-A指令集:协处理器指令
  3. TEE技术与Meltdown Spectre
  4. js截取数组slice() 和 splice() 的用法
  5. HRBUST 1849 商品中心
  6. 什么样的故障让阿里云换了总裁?
  7. Qt获取QTextEdit中的内容
  8. JVM--Java虚拟机
  9. MPB:广东生态土壤所孙蔚旻组-DNA稳定同位素示踪与宏基因组单菌草图组装联用技术...
  10. [git报错] fatal: reference is not a tree: xxx 以及 Unable to checkout ‘xxx‘ in submodule path xxx