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. ROS tf-深入Time和TF

    博客转载自:https://www.ncnynl.com/archives/201702/1313.html ROS与C++入门教程-tf-深入Time和TF 说明: 介绍使用waitForTrans ...

  2. React之改变页面上方图标

    首先在public/index.html中 <!-- <link rel="shortcut icon" href="%PUBLIC_URL%/bitbug6 ...

  3. Python - Django - 使用 Bootstrap 样式修改注册页

    reg2 函数: from django.shortcuts import render, HttpResponse from app01 import models def reg2(request ...

  4. Servlet2.5版本和Servlet3.0版本

    在学习这节之前你需要在你自己的电脑进行如下配置: 配置Java运行环境:JDK+JRE的安装配置,参考博客Windows下配置Java开发环境: 安装Eclipse:参考博客Windows下配置Jav ...

  5. Pytest单元测试框架-Pytest环境安装

    unittest是python自带的单元测试框架,它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作,使得单元测试易于开展,因为它的易用性,很多同学也拿它来做功能测试和接口测试,只需简单开发 ...

  6. [LeetCode] 97. Interleaving String 交织相错的字符串

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1and s2. Example 1: Input: s1 = ...

  7. DotNetty是微软的Azure团队,使用C#实现的Netty的版本发布

    DotNetty是微软的Azure团队,使用C#实现的Netty的版本发布 Netty(DotNetty)原理解析 一.背景介绍 DotNetty是微软的Azure团队,使用C#实现的Netty的版本 ...

  8. linux 环境搭建

    1.安装jdk 上传tar包,解压缩 vim /etc/profile JAVA_HOME=/usr/local/jdk1.8.0_152CLASSPATH=$JAVA_HOME/lib/PATH=$ ...

  9. Kafka Streams | 流,实时处理和功能

    1.目标 在我们之前的Kafka教程中,我们讨论了Kafka中的ZooKeeper.今天,在这个Kafka Streams教程中,我们将学习Kafka中Streams的实际含义.此外,我们将看到Kaf ...

  10. 34 多线程(六)——线程安全 synchronized

    关键字synchronized可以写在方法和代码块中 写在普通方法中:锁住的对象是this,即类的实例.也就是说锁住的是类下面的类变量(成员变量),而不是方法中的变量. 写在静态方法中:锁住的对象时c ...