雪花算法SnowFlake 细致易懂 Java/Springboot实现

04-11 1345阅读 0评论

文章目录

  • 一、雪花算法是什么?
  • 二、雪花算法的构成
  • 三、雪花算法实现思路
    • 3.1 如何把 时间戳,机器ID,序列号等合在一起变成一个long类型数字?
    • 3.2 如果并发访问 同一时间对于 要生成ID多于2的12次方个 也就是多余4096个ID如何处理?
    • 3.3 发生时钟回拨如何处理?
      • 3.1的思路是
      • 3.2 问题思路
      • 3.3 问题思路
      • 三、Java代码实现
      • 四、Springboot代码实现
        • 4.1 Maven引入依赖
        • 4.2 创建 SnowFlakeProperties java文件
        • 4.3 创建 SnowFlake java文件
        • 4.4 在任意@Configuration 或者启动各类加上注解
          • 配置类里这样写即可
          • 我是这样写的
          • 如何设置机器ID,数据中心ID呢?
          • 由于前端(Web) 最大支持53位(二进制)数字 所以后端传给前端转换字符串来存 否则精度会损失
          • 测试
          • 结尾

            一、雪花算法是什么?

            分布式中生成唯一性ID的一种算法 。

            为啥不用数据库的自增主键呢?

            • 唯一性: 如果数据库数据特别多,你会同一张表建立不同节点上,数据也在不同节点上存,那么如果俩ID都是 001 违背主键 定义吗?

            • 顺序性: 雪花算法计算出来ID 有顺序 如果你了解数据库 B+树 ,对于索引来说 字段是 数字类型 ,有顺序, 唯一 在查找以及插入效率很高 而UUID是字符串没顺序不适合做数据库主键了

              二、雪花算法的构成

              雪花算法 由64位构成ID,对应java数据类型的话 long类型 这里位是二进制位

              • 最左一位(图中没有标出)都是 0 因为二进制中 最左符号位 1代表负数 0是正数 而我们生成ID肯定是正数所以是0
              • timestamp : 时间戳 我们一般情况给初始时间 用系统当前时间 减去 初始时间 这个差值的时间戳作为ID的时间戳也就是timestamp占用41位。至于为啥差值作为时间戳 1.减小时间戳长度 2.时钟回拨处理
              • instance :这个表示机器个数 分布式系统中 多个节点 可以左边5位是机器的ID 右边5位 数据中心ID(机房ID)加起来是10位
              • sequence:序列号 这个主要用途 并发执行代码 有时候获取时间一样的 那么区分ID 用序列号自增进行区分

                雪花算法SnowFlake 细致易懂 Java/Springboot实现

                时钟回拨: 一种情况管理员手动把时间调整当前系统之前时间,这样的话生成ID和之前ID可能冲突了。虽然上边时间戳插值减轻该问题但是插值仍有可能为正值,

                三、雪花算法实现思路

                3.1 如何把 时间戳,机器ID,序列号等合在一起变成一个long类型数字?

                3.2 如果并发访问 同一时间对于 要生成ID多于2的12次方个 也就是多余4096个ID如何处理?

                3.3 发生时钟回拨如何处理?


                3.1的思路是

                • 首先移动好说的 。数据中心ID datacenterID (属于instance) 假设 1L 号 用long表示可以 (二进制)

                  0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001

                  将它左移动12位(序列号最长位)代码 datacenterID //起始时间戳 private static long startTimeStamp; //机器ID private static long workID; //数据中心ID private static long dataCenterID; //序列号 private static long sequence; //数据中心ID移动位数 private static long dataCenterIndex; //机器ID移动位数 private static long workIDIndex; //时间戳移动位数 private static long timeStampIndex; //记录上一次时间戳 private static long lastTimeStamp; //序列号掩码 private static long sequenceMask; //序列号长度12位 private static long sequenceLength; //初始化数据 static { startTimeStamp = 1577808000000L; //设置机器编号 1 workID = 1L; //设置数据中心ID 1 dataCenterID = 1L; //起始序列号 0开始 sequence = 0L; //数据中心位移位数 dataCenterIndex = 12L; //机器ID位移位数 workIDIndex = 17L; //时间戳位移位数 timeStampIndex = 22L; //记录上次时间戳 lastTimeStamp = -1L; //序列号长度 sequenceLength = 12L; //序列号掩码 sequenceMask = -1L ^ (-1L //获得当前时间 long now = System.currentTimeMillis(); //当前系统时间小于上一次记录时间 if (now


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1345人围观)

还没有评论,来说两句吧...

目录[+]