雪花算法根据时间戳生成有序的 64 bit 的 Long 类型的唯一 ID

各 bit 含义:

  • 1 bit: 符号位,0 是正数 1 是负数, ID 为正数,所以恒取 0
  • 41 bit: 时间差,我们可以选择一个参考点,用它来计算与当前时间的时间差 (毫秒数),41 bit 存储时间差,足够使用 69 年
  • 10 bit: 机器码,能编码 1024 台机器;可以手动指定含义,比如前5 bit 作为机器编号、后 5 bit 作为进程编号
  • 12 bit: 序列号,同一机器同一毫秒内产生不同的序列号,12 bit 可以支持 4096 个序列号

优点:

  • 灵活配置:机器码可以根据需求灵活配置含义
  • 无需持久化:如果序号自增往往需要持久化,本算法不需要持久化
  • ID 有含义/可逆性:ID 可以反解出来,对 ID 进行统计分析,可以很简单的分析出整个系统的繁忙曲线,还可以定位到每个机器,在某段时间承担了多少工作,分析出负载均衡情况
  • 高性能:生成速度很快
public class Snowflake {/*** 每一部分所占位数*/private final long unusedBits = 1L;private final long timestampBits = 41L;private final long datacenterIdBits = 5L;private final long workerIdBits = 5L;private final long sequenceBits = 12L;/*** 向左的位移*/private final long timestampShift = sequenceBits + datacenterIdBits + workerIdBits;private final long datacenterIdShift = sequenceBits + workerIdBits;private final long workerIdShift = sequenceBits;/*** 起始时间戳,初始化后不可修改*/private final long epoch = 1451606400000L; // 2016-01-01/*** 数据中心编码,初始化后不可修改* 最大值: 2^5-1 取值范围: [0,31]*/private final long datacenterId;/*** 机器或进程编码,初始化后不可修改* 最大值: 2^5-1 取值范围: [0,31]*/private final long workerId;/*** 序列号* 最大值: 2^12-1 取值范围: [0,4095]*/private long sequence = 0L;/** 上次执行生成 ID 方法的时间戳 */private long lastTimestamp = -1L;/** 每一部分最大值*/private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 2^5-1private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 2^5-1private final long maxSequence = -1L ^ (-1L << sequenceBits); // 2^12-1/*** 生成序列号*/public synchronized long nextId() {long currTimestamp = timestampGen();if (currTimestamp < lastTimestamp) {throw new IllegalStateException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",lastTimestamp - currTimestamp));}if (currTimestamp == lastTimestamp) {sequence = (sequence + 1) & maxSequence;if (sequence == 0) { // overflow: greater than max sequencecurrTimestamp = waitNextMillis(currTimestamp);}} else { // reset to 0 for next period/millisecondsequence = 0L;}// track and memo the time stamp last snowflake ID generatedlastTimestamp = currTimestamp;return ((currTimestamp - epoch) << timestampShift) | //(datacenterId << datacenterIdShift) | //(workerId << workerIdShift) | // new line for nice lookingsequence;}public Snowflake(long datacenterId, long workerId) {if (datacenterId > maxDatacenterId || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));}if (workerId > maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));}this.datacenterId = datacenterId;this.workerId = workerId;}/*** 追踪调用 waitNextMillis 方法的次数*/private final AtomicLong waitCount = new AtomicLong(0);public long getWaitCount() {return waitCount.get();}/*** 循环阻塞直到下一秒*/protected long waitNextMillis(long currTimestamp) {waitCount.incrementAndGet();while (currTimestamp <= lastTimestamp) {currTimestamp = timestampGen();}return currTimestamp;}/*** 获取当前时间戳*/public long timestampGen() {return System.currentTimeMillis();}
}

参考:snowflake ID 生成算法

完整代码:GitHub

转载于:https://www.cnblogs.com/victorbu/p/11101850.html

雪花算法 Java 版相关推荐

  1. java 随机金额_java_微信随机生成红包金额算法java版,最近几年玩得最疯狂的应该是 - phpStudy...

    微信随机生成红包金额算法java版 最近几年玩得最疯狂的应该是发红包了,尤其是过年的时候特别受欢迎,下面写了红包的随机算法,其实挺简单的,仅是提供一种思路,希望可以给大家一些启发. public cl ...

  2. 最小生成树Prim算法Java版

    最小生成树Prim算法Java版 算法描述: 在一个加权连通图中,顶点集合V,边集合为E 任意选出一个点作为初始顶点,标记为visit,计算所有与之相连接的点的距离,选择距离最短的,标记visit. ...

  3. Java算法:华为机试算法(下),华为算法Java版,牛客网华为算法73~108题

    接上篇:Java算法:华为机试算法(中),华为算法Java版,牛客网华为算法55~72题   HJ73 计算日期到天数转换 计算日期到天数转换 题目描述 根据输入的日期,计算是这一年的第几天.. 测试 ...

  4. 雪花算法-java实现

    雪花算法用途 用来保证分布式环境生成ID唯一. 雪花算法实现 雪花算法用64位二进制表示,其中二进制位数作用划分为: 1bit:符号位,无使用 41bit:时间位,用于表示毫秒可以使用69年 10bi ...

  5. Java算法:牛客网小米笔试真题算法Java版1-40题

    题号 题目 知识点 难度 通过率 XM1 小米Git 树 困难 10.22% XM2 懂二进制 中等 29.90% XM3 风口的猪-中国牛市 动态规划 较难 18.73% XM4 电话号码分身 中等 ...

  6. 雪花算法-Java实现-解决时钟回拨的一种方法

    背景: 前不久发生了一次严重的生产事件, 与雪花算法有关,但不是雪花算法的问题 具体问题参考代码main中的注释, 结论如下 序列可以使用69年, 序列的长度变化是这样的, 假设以当前时间为初始化值 ...

  7. Java算法:华为机试算法第二版(上),华为算法Java版

    牛客网华为机试练习题 文章目录 牛客网华为机试练习题 动态规划问题详解 前言 生活中的动态规划 2. 几个简单的概念 3. DP的典型应用:DAG最短路 4. 对DP原理的一点讨论 5. 例题:最长上 ...

  8. 跑胡子c语言算法,跑胡子胡牌算法Java版(带赖子、基于回溯算法)

    跑胡子规则 跑胡子,小写"一"到"十"各4张共40张,大写"壹"到"拾"各4张共40张. 砌牌:跑胡子为3人同玩,庄家砌 ...

  9. 推特雪花算法 java实现

    2019独角兽企业重金招聘Python工程师标准>>> package twiter.snowflake;/*** twitter的snowflake算法 -- java实现*/ p ...

最新文章

  1. java float转换int
  2. Linux下的vim编辑器与gcc编译器及静动态库的制作
  3. 错误代码: 1054 Unknown column #39;t.createUsrId#39; in #39;group statement#39;
  4. smarty二维foreach示例[顺代一维数组],再次加强版
  5. 设计模式学习笔记——中介者(Mediator)模式
  6. Web应用功能测试测试点
  7. Sharding-JDBC水平分表(分片策略)_Sharding-Sphere,Sharding-JDBC分布式_分库分表工作笔记008
  8. SQL Management Studio Express 安装缺少MSXML6解决
  9. SCN和Checkpoint
  10. Android常用提示框(dialog和popuwindow)
  11. Atitit session的概念总结
  12. 微信小程序 自定义底部导航栏(tabBar)
  13. 计算机类普刊有哪些,计算机类普刊期刊发表推荐
  14. spline曲线使用
  15. 计算机公共基础知识论文,公共基础知识学术论文.docx
  16. python读取excel数据使用pyecharts展示
  17. 查看windows系统和office是否永久激活(转载)
  18. 高德地图:点击获取火星坐标(经纬度)
  19. vue2升级到 Vue3的异同(入门须知)
  20. 快速傅里叶变换-快速傅里叶变换

热门文章

  1. 开发Eclipse自定义控件
  2. 薏米红豆粥的功效和实践演示
  3. 如何 搭建 RMAN 备份平台
  4. html页面视频标签,html5基础标签(html5视频标签 html5新标签用法)
  5. awk linux 获取端口号_Linux提权后获取敏感信息命令
  6. php数组包含对象吗,在包含数组的PHP对象上调用方法
  7. iPhone PHP获取文件,IOS中获取各种文件的目录路径的方法
  8. java new 引用_java不用new运算符也能创建引用吗?
  9. linux定时任务定向到空,Linux 定时任务下 /dev/null 21 相关知识说明
  10. java数据和窗口怎么结合_卖jsp编程技巧的那个垃圾的所有实例的答案全部