Snowflake ID组成

Snowflake ID有64bits长,由以下三部分组成:

  • time—42bits,精确到ms,那就意味着其可以表示长达(2^42-1)/(1000360024*365)=139.5年,另外使用者可以自己定义一个开始纪元(epoch),然后用(当前时间-开始纪元)算出time,这表示在time这个部分在140年的时间里是不会重复的,官方文档在这里写成了41bits,应该是写错了。另外,这里用time还有一个很重要的原因,就是可以直接更具time进行排序,对于twitter这种更新频繁的应用,时间排序就显得尤为重要了。

  • machine id—10bits,该部分其实由datacenterId和workerId两部分组成,这两部分是在配置文件中指明的。

    • datacenterId的作用(个人看法)

      1.方便搭建多个生成uid的service,并保证uid不重复,比如在datacenter0将机器0,1,2组成了一个生成uid的service,而datacenter1此时也需要一个生成uid的service,从本中心获取uid显然是最快最方便的,那么它可以在自己中心搭建,只要保证datacenterId唯一。如果没有datacenterId,即用10bits,那么在搭建一个新的service前必须知道目前已经在用的id,否则不能保证生成的id唯一,比如搭建的两个uid service中都有machine id为100的机器,如果其server时间相同,那么产生相同id的情况不可避免。

      2.加快server启动速度。启动一台uid server时,会去检查zk同workerId目录中其他机器的情况,如其在zk上注册的id和向它请求返回的work_id是否相同,是否处同一个datacenter下,另外还会检查该server的时间与目前已有机器的平均时间误差是否在10s范围内等,这些检查是会耗费一定时间的。将一个datacenter下的机器数限制在32台(5bits)以内,在一定程度上也保证了server的启动速度。

    • workerId是实际server机器的代号,最大到32,同一个datacenter下的workerId是不能重复的。它会被注册到zookeeper上,确保workerId未被其他机器占用,并将host:port值存入,注册成功后就可以对外提供服务了。

  • sequence id —12bits,该id可以表示4096个数字,它是在time相同的情况下,递增该值直到为0,即一个循环结束,此时便只能等到下一个ms到来,一般情况下4096/ms的请求是不太可能出现的,所以足够使用了。

Snowflake ID便是通过这三部分实现了UID的产生,策略也并不复杂。下面我们来看看它的一些关键源码

/**
* 核心代码就是毫秒级时间41位+机器ID 10位+毫秒内序列12位
* */

public class IdWorker {

private long workerId; 
private long datacenterId; 
private long sequence = 0L;

private long twepoch = 1288834974657L;

private long workerIdBits = 5L; 
private long datacenterIdBits = 5L; 
private long maxWorkerId = -1L ^ (-1L << workerIdBits); 
private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); 
private long sequenceBits = 12L;

private long workerIdShift = sequenceBits; 
private long datacenterIdShift = sequenceBits + workerIdBits; 
private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; 
private long sequenceMask = -1L ^ (-1L << sequenceBits);

private long lastTimestamp = -1L;

public IdWorker(long workerId, long datacenterId) { 
// sanity check for workerId 
if (workerId > maxWorkerId || workerId < 0) { 
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 

if (datacenterId > maxDatacenterId || datacenterId < 0) { 
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); 

this.workerId = workerId; 
this.datacenterId = datacenterId; 
}

public synchronized long nextId() { 
long timestamp = timeGen();

if (timestamp < lastTimestamp) { 
System.out.println("clock is moving backwards. Rejecting requests until "+lastTimestamp);
throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); 
}

if (lastTimestamp == timestamp) { 
sequence = (sequence + 1) & sequenceMask; 
if (sequence == 0) { 
timestamp = tilNextMillis(lastTimestamp); 

} else { 
sequence = 0L; 
}

lastTimestamp = timestamp;

return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; 
}

protected long tilNextMillis(long lastTimestamp) { 
long timestamp = timeGen(); 
while (timestamp <= lastTimestamp) { 
timestamp = timeGen(); 

return timestamp; 
}

protected long timeGen() { 
return System.currentTimeMillis(); 

}

原文:https://www.cnblogs.com/dayhand/p/3851248.html

全局唯一ID生成器(Snowflake ID组成) 分析的更多相关文章

  1. 分布式ID生成器 snowflake(雪花)算法

    在springboot的启动类中引入 @Bean public IdWorker idWorkker(){ return new IdWorker(1, 1); } 在代码中调用 @Autowired ...

  2. 分布式全局ID生成器原理剖析及非常齐全开源方案应用示例

    为何需要分布式ID生成器 **本人博客网站 **IT小神 www.itxiaoshen.com **拿我们系统常用Mysql数据库来说,在之前的单体架构基本是单库结构,每个业务表的ID一般从1增,通过 ...

  3. 常用的分布式ID生成器

    为何需要分布式ID生成器 **本人博客网站 **IT小神 www.itxiaoshen.com **拿我们系统常用Mysql数据库来说,在之前的单体架构基本是单库结构,每个业务表的ID一般从1增,通过 ...

  4. snowflake 分布式唯一ID生成器

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 原文参考运维生存和开源中国上的代码整理 我的环境是pytho ...

  5. Spring Boot集成全局唯一ID生成器

    流水号生成器(全局唯一 ID生成器)是服务化系统的基础设施,其在保障系统的正确运行和高可用方面发挥着重要作用.而关于流水号生成算法首屈一指的当属 Snowflake雪花算法,然而 Snowflake本 ...

  6. 全局唯一ID生成器

    分布式环境中,如何保证生成的id是唯一不重复的? twitter,开源出了一个snowflake算法,现在很多企业都按照该算法作为参照,实现了自己的一套id生成器. 该算法的主要思路为: 刚好64位的 ...

  7. SnowFlake 生成全局唯一id

    public class SnowFlakeUtil { private long workerId; private long datacenterId; private long sequence ...

  8. 分布式唯一id:snowflake算法思考

    匠心零度 转载请注明原创出处,谢谢! 缘起 为什么会突然谈到分布式唯一id呢?原因是最近在准备使用RocketMQ,看看官网介绍: 一句话,消息可能会重复,所以消费端需要做幂等.为什么消息会重复后续R ...

  9. 全局唯一ID发号器的几个思路

    标识(ID / Identifier)是无处不在的,生成标识的主体是人,那么它就是一个命名过程,如果是计算机,那么它就是一个生成过程.如何保证分布式系统下,并行生成标识的唯一与标识的命名空间有着密不可 ...

随机推荐

  1. h5开发安卓机型点击输入框调起输入法,输入框被键盘遮挡的解决方法

    前言: 从以前的项目中找一个问题的解决方案,顺带找到了这个安卓机型调起输入法,页面没有自动上滑导致输入框被弹起的键盘遮挡的解决方案.这个问题只有安卓机型页面中的输入框处于底部(也就是底部键盘区域)的时 ...

  2. Blob/DataURL/canvas/image的相互转换

    函数都比较简单,直接看就ok了 /*-----------------------------------------------------------------------*/ // canva ...

  3. saltstack执行state.sls耗时长的坑

    一直用的 jenkins + saltstack 自动化构建发布项目,一共也就不超过20台服务器,奈何运行时间越来越慢,并且负载越来越高(这里大部分都是使用state模块),但是不用state模块效率 ...

  4. copyProperties 忽略null值字段

    在做项目时遇到需要copy两个对象之间的属性值,但是有源对象有null值,在使用BeanUtils来copy时null值会覆盖目标对象的同名字段属性值,然后采用以下方法找到null值字段,然后忽略: ...

  5. ehcache和redis的区别及适用场景

    区别: (1)Redis 独立程序,是通过socket访问到缓存服务,效率比ecache低,比数据库要快很多,处理集群和分布式缓存方便,有成熟的方案 (2)Ehcache 直接在jvm虚拟机中缓存,速 ...

  6. IIS中发布FTP支持断点续传

    IIS10中发布FTP默认就是支持断点续传的.

  7. Ubuntu查看与结束任务进程

    1.打开终端 2.敲  ps -ef  查出进程的编号(就是PID那列) 3.输入 kill PID 即可(如果PID是123456,则kill 123456) 例如: 我想把splash关闭,直接输 ...

  8. spring security的BCryptPasswordEncoder加密和对密码验证的原理

    目录 BCryptPasswordEncoder加密和对密码验证的原理 一.加密算法和hash算法的区别 二.源码解析 1. encode方法 2. BCrypt.hashpw方法 3. matche ...

  9. 设置程序崩溃时产生 core 文件的配置

    /* 不限制 core 文件的大小 */ ulimit -c unlimited /* 使用 pid 进行命名 */ echo " > /proc/sys/kernel/core_us ...

  10. Python Tkinter 文本框(Entry)

    Python Tkinter 文本框用来让用户输入一行文本字符串. 你如果需要输入多行文本,可以使用 Text 组件. 你如果需要显示一行或多行文本且不允许用户修改,你可以使用 Label 组件. 语 ...