雪花算法详解

╰半夏微凉° 2024-03-22 17:35 135阅读 0赞

雪花算法介绍

SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id

68a88c66176e4b759ce57ee23cf34b36.png

  • 1位,不用。二进制中最高位为1的都是负数,但是生成的id都是正数,所以这个最高位固定是0
  • 41位,用来记录时间戳(毫秒)。

    • 41位可以表示241-1个数字,
    • 如果只用来表示正整数(计算机中正数包含0),可以表示的数值范围是:0 至 241 - 1,减1是因为可表示的数值范围是从0开始算的,而不是1。
    • 也就是说41位可以表示241 - 1个毫秒的值,转化成单位年则是241 - 1 / (1000 * 60 * 60 * 24 * 365) = 69年
  • 10位,用来记录工作机器id。

    • 可以部署在210 = 1024个节点,包括5位datacenterId5位workerId
    • 5位(bit)可以表示的最大正整数是25 - 1 = 31,即可以用0、1、2、3、….31这32个数字,来表示不同的datecenterId或workerId
  • 12位,序列号,用来记录同毫秒内产生的不同id。

    • 12位(bit)可以表示的最大正整数是212 - 1 = 4095,即可以用0、1、2、3、….4095这4096个数字,来表示同一机器同一时间截(毫秒)内产生的4096个ID序号,减1是因为可表示的数值范围是从0开始算的,而不是1。

同一毫秒:0-4095 4096,因为这一毫秒生产的ID数已经满了,因此需要让CPU空转,使得毫秒数增加1,那么此时这一毫秒的ID生成应该从0重新开始

算法实现

  1. package com.qf.electronic.util;
  2. /**
  3. * 雪花算法
  4. */
  5. public class SnowFlake {
  6. /**
  7. * 这里需要记录最后一次生成ID的时间,因为同一毫秒内,可能会生成多个ID,记录后可以用来做比对
  8. */
  9. private long lastTime = -1L;
  10. /**
  11. * 初始时间,因为时间占41位,所以可以从这个时间开始,差不多使用69年
  12. */
  13. private long startTime = System.currentTimeMillis();
  14. /**
  15. * 机房ID,占5位,因此最多能够对32个机房有效
  16. */
  17. private long dataCenterId;
  18. /**
  19. * 机器ID,占5位,因此最多能够对32个机器有效
  20. */
  21. private long workId;
  22. /**
  23. * 序列号,占12位,因此在一毫秒内最多生成2^12 = 4096个序列号
  24. */
  25. private long sequence;
  26. public SnowFlake(long dataCenterId, long workId, long sequence){
  27. //机房ID最小值为0,最大值为31
  28. if(dataCenterId > 31 || dataCenterId < 0){
  29. throw new IllegalArgumentException("机房ID必须>=0且<=31,当前使用机房ID:" + dataCenterId);
  30. }
  31. if(workId > 31 || workId < 0){
  32. throw new IllegalArgumentException("机器ID必须>=0且<=31,当前使用机器ID:" + workId);
  33. }
  34. this.dataCenterId = dataCenterId;
  35. this.workId = workId;
  36. this.sequence = sequence;
  37. }
  38. public long generateId(){
  39. long time = System.currentTimeMillis(); //获取系统当前时间
  40. if(time < lastTime){//防止时间回拨,必须手动将时间拨回
  41. throw new RuntimeException("时间回拨");
  42. }
  43. if(time == lastTime){//同一时间段内,生成多个ID
  44. //按位与操作符所得结果最大值不会超过参与运算的最小操作数,这里不能超过4096
  45. sequence = (sequence + 1) & 4095;
  46. if(sequence == 0){//如果计数重新归0,表示该毫秒内,ID生成的数量已满
  47. //CPU空转1毫秒
  48. while ((time = System.currentTimeMillis()) == lastTime);
  49. }
  50. } else {
  51. sequence = 0;
  52. }
  53. //时间本身占41位,但是需要向左移动22位才能在指定的位置上
  54. //机房ID占5位,但是需要向左移动17位才能在指定的位置上
  55. //机器ID占5位,但是需要向左移动12位才能在指定的位置上
  56. long id = (time - startTime) << 22 | dataCenterId << 17 | workId << 12 | sequence;
  57. lastTime = time;
  58. return id;
  59. }
  60. }

发表评论

表情:
评论列表 (有 0 条评论,135人围观)

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

相关阅读

    相关 算法------雪花算法简介

    算法------雪花算法 数据库扩展的主要方式:业务分库,主从复制(实现读写分离)、数据库分表 数据库分表: 将不同业务数据分散存储到不同的数据库服务器,能够支撑

    相关 雪花算法详解

    1. 雪花算法概念 雪花算法(Snowflake)是一种生成唯一ID的算法,主要应用于分布式系统中。它可以在不依赖于数据库等其他存储设施的情况下,生成全局唯一的ID。

    相关 雪花算法

    雪花算法生成的ID可用于做分布式系统ID 生成的ID格式 1位标识符(始终是0)+41位时间戳 + 10位机器标识符(5位datacenterId+5位WorkId) +12

    相关 雪花算法

    我们都知道在一个分布式系统中生成一个无重复的标识是非常重要的,业界也有很多算法。 雪花(snowflake)在自然界中,是极具独特美丽,又变幻莫测的东西: 1. 雪花属于

    相关 雪花算法

    雪花算法 `雪花算法`的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等。 结构: ![在这里插入图片描述][watermark_type