分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。

有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。

而twitter的SnowFlake解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。

原理

Twitter的雪花算法SnowFlake,使用Java语言实现。

SnowFlake算法产生的ID是一个64位的整型,结构如下(每一部分用“-”符号分隔):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

1位标识部分,在java中由于long的最高位是符号位,正数是0,负数是1,一般生成的ID为正数,所以为0;

41位时间戳部分,这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;

10位节点部分,Twitter实现中使用前5位作为数据中心标识,后5位作为机器标识,可以部署1024个节点;

12位序列号部分,支持同一毫秒内同一个节点可以生成4096个ID;

SnowFlake算法生成的ID大致上是按照时间递增的,用在分布式系统中时,需要注意数据中心标识和机器标识必须唯一,这样就能保证每个节点生成的ID都是唯一的。或许我们不一定都需要像上面那样使用5位作为数据中心标识,5位作为机器标识,可以根据我们业务的需要,灵活分配节点部分,如:若不需要数据中心,完全可以使用全部10位作为机器标识;若数据中心不多,也可以只使用3位作为数据中心,7位作为机器标识。

snowflake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),并且效率较高。据说:snowflake每秒能够产生26万个ID。

源码

本机实测:100万个ID 耗时5秒

/*** 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)* https://github.com/souyunku/SnowFlake** @author yanpenglei* @create 2018-03-13 12:37**/
public class SnowFlake {/*** 起始的时间戳*/private final static long START_STMP = 1480166465631L;/*** 每一部分占用的位数*/private final static long SEQUENCE_BIT = 12; //序列号占用的位数private final static long MACHINE_BIT = 5;   //机器标识占用的位数private final static long DATACENTER_BIT = 5;//数据中心占用的位数/*** 每一部分的最大值*/private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);/*** 每一部分向左的位移*/private final static long MACHINE_LEFT = SEQUENCE_BIT;private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;private long datacenterId;  //数据中心private long machineId;     //机器标识private long sequence = 0L; //序列号private long lastStmp = -1L;//上一次时间戳public SnowFlake(long datacenterId, long machineId) {if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");}if (machineId > MAX_MACHINE_NUM || machineId < 0) {throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");}this.datacenterId = datacenterId;this.machineId = machineId;}/*** 产生下一个ID** @return*/public synchronized long nextId() {long currStmp = getNewstmp();if (currStmp < lastStmp) {throw new RuntimeException("Clock moved backwards.  Refusing to generate id");}if (currStmp == lastStmp) {//相同毫秒内,序列号自增sequence = (sequence + 1) & MAX_SEQUENCE;//同一毫秒的序列数已经达到最大if (sequence == 0L) {currStmp = getNextMill();}} else {//不同毫秒内,序列号置为0sequence = 0L;}lastStmp = currStmp;return (currStmp - START_STMP) << TIMESTMP_LEFT //时间戳部分| datacenterId << DATACENTER_LEFT       //数据中心部分| machineId << MACHINE_LEFT             //机器标识部分| sequence;                             //序列号部分}private long getNextMill() {long mill = getNewstmp();while (mill <= lastStmp) {mill = getNewstmp();}return mill;}private long getNewstmp() {return System.currentTimeMillis();}public static void main(String[] args) {SnowFlake snowFlake = new SnowFlake(2, 3);long start = System.currentTimeMillis();for (int i = 0; i < 1000000; i++) {System.out.println(snowFlake.nextId());}System.out.println(System.currentTimeMillis() - start);}
}

循环生成的ID,运行结果如下:

170916032679263329
170916032679263330
170916032679263331
170916032679263332
170916032679263333
170916032679263334
170916032679263335
170916032679263336
170916032679263337
170916032679263338
170916032679263339
170916032679263340
170916032679263341
170916032679263342

开源地址

Github:https://github.com/souyunku/SnowFlake

Twitter的分布式雪花算法 SnowFlake 每秒自增生成26个万个可排序的ID (Java版)相关推荐

  1. Twitter的分布式雪花算法 SnowFlake

    为什么80%的码农都做不了架构师?>>>    原理 Twitter的雪花算法SnowFlake,使用Java语言实现. SnowFlake算法产生的ID是一个64位的整型,结构如下 ...

  2. 雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论

    文章目录 一.前言 二.雪花算法snowflake 1.基本定义 2.snowflake的优缺点 三.Java代码实现snowflake 1.组装生成id 2.计算最大值的几种方式 3.反解析ID 4 ...

  3. mysql snowflake_雪花算法-snowflake

    雪花算法-snowflake 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有 ...

  4. 分布式--雪花算法--使用/原理/实例

    原文网址:分布式--雪花算法--使用/原理/实例_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍分布式中的雪花算法.包括:用法.原理. 雪花算法用于生成全局的唯一ID. 使用时的注意事项 需要 ...

  5. 雪花算法-Snowflake Snowflake

    雪花算法-Snowflake Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义.而 Java中64b ...

  6. 发号器:雪花算法(Snowflake)

    雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器. 第一个bit位(1bit):Ja ...

  7. 分布式--雪花算法改进版--美团的Leaf

    原文网址:分布式--雪花算法改进版--美团的Leaf_IT利刃出鞘的博客-CSDN博客 简介 说明 美团的Leaf用来生成全局的唯一ID,其中的Leaf-snowflake方案是雪花算法的改进版. 官 ...

  8. 雪花算法(snowflake)容器化部署支持动态增加节点

    先简单的介绍一下雪花算法,雪花算法生成的Id由:1bit 不用 + 41bit时间戳+10bit工作机器id+12bit序列号,如下图: 不用:1bit,因为最高位是符号位,0表示正,1表示负,所以这 ...

  9. java 有穷自动机_Java实现雪花算法(snowflake)

    本文主要介绍了Java实现雪花算法(snowflake),分享给大家,具体如下: 简单描述 最高位是符号位,始终为0,不可用. 41位的时间序列,精确到毫秒级,41位的长度可以使用69年.时间位还有一 ...

最新文章

  1. 2005年上半年 网络工程师 上下午试卷【附带答案】
  2. python怎么用函数查看变量类型_查看变量类型的Python内置函数是()。
  3. 方舟服务器如何修改恐龙,方块方舟人物及驯养恐龙属性修改教程 人物属性怎么修改_游侠网...
  4. 20162318 2016-2017-2 《程序设计与数据结构》第7周学习总结
  5. 2-09 CentOS系统参数优化
  6. k8s安装之Linux centos7升级内核到4.18以上
  7. GoldenGate学习笔记(11)_常用参数
  8. jsf集成spring_JSF – PrimeFaces和Hibernate集成项目
  9. adf4351使用_ADF:将UI类别与动态表单一起使用
  10. 项目中的textarea遇到的小问题
  11. G - 数据结构实验之链表五:单链表的拆分
  12. 声音就是你的武器!这样的攻防大赛你一定没有见过!
  13. 四川大学计算机学院保研规定,2020四川大学计算机学院保研夏令营通知
  14. 神舟笔记本风扇偏移调多少_神舟战神怎么调节风扇我们该办正事了
  15. 计算机acm国际排名,acm(中国大学acm综合排名)
  16. limbo模拟器安装linux,limbo模拟器win10镜像安装使用教程(附下载)
  17. tipask二次开发总结_tipask二次开发总结.docx
  18. 中国马铃薯全粉产业经营策略与销售渠道研究报告(2022-2027年)
  19. 谁抢走你的棒棒糖?精彩的创意让你得到的不仅仅是震撼 值得一看(图)
  20. 我是云南的云南怒江的是什么梗 我是云南的云南怒江的梗出处

热门文章

  1. 字符串转换成utf-8编码
  2. Android进阶笔记:Messenger源码详解
  3. 读书笔记——javascript闭包
  4. qq图片选择效果的处理
  5. 如何改变一个地图的Zoom单位
  6. 网络管理员比赛回顾04-DHCP
  7. vue颜色选择器_如何制作? Vue的颜色选择器!
  8. java开放源码_开放源码的第一周:我是如何参与的,以及我学到的东西
  9. Spring Cloud应用开发(二:实现服务间的调用)
  10. golang socket读写同时_epoll在Golang的应用