分布式ID生成之雪花算法

分布式ID生成--雪花算法

一.背景介绍

SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的。

 

二.原理分析

 

0 - 0000000000 0000000000 0000000000 0000000000 0 - 10001 - 11001 - 000000000000

这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。

 


第一个部分,是 1 个 bit:0,这个是无意义的。

 

第二个部分是 41 个 bit:表示的是时间戳。

 

第三个部分是 5 个 bit:表示的是机房 id,10001。

 

第四个部分是 5 个 bit:表示的是机器 id,1 1001。

 

第五个部分是 12 个 bit:表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 id 的序号,000000000000

 

①1 bit:是不用的,为啥呢?

因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。

 

②41 bit:表示的是时间戳,单位是毫秒。

41 bit 可以表示的数字多达 2^41 - 1,也就是可以标识 2 ^ 41 - 1 个毫秒值,换算成年就是表示 69 年的时间。

 

③10 bit:记录工作机器 id,代表的是这个服务最多可以部署在 2^10 台机器上,也就是 1024 台机器。

 

但是 10 bit 里 5 个 bit 代表机房 id,5 个 bit 代表机器 id。意思就是最多代表 2 ^ 5 个机房(32 个机房),每个机房里可以代表 2 ^ 5 个机器(32 台机器)。

 

 ④12 bit:这个是用来记录同一个毫秒内产生的不同 id。

 

12 bit 可以代表的最大正整数是 2 ^ 12 - 1 = 4096,也就是说可以用这个 12 bit 代表的数字来区分同一个毫秒内的 4096 个不同的 id。

 

 简单来说,你的某个服务假设要生成一个全局唯一 id,那么就可以发送一个请求给部署了 SnowFlake 算法的系统,由这个 SnowFlake 算法系统来生成唯一 id。

 

这个 SnowFlake 算法系统首先肯定是知道自己所在的机房和机器的,比如机房 id = 10,机器 id = 1。

 

接着 SnowFlake 算法系统接收到这个请求之后,首先就会用二进制位运算的方式生成一个 64 bit 的 long 型 id,64 个 bit 中的第一个 bit 是无意义的。

 

接着 41 个 bit,就可以用当前时间戳(单位到毫秒),然后接着 5 个 bit 设置上这个机房 id,还有 5 个 bit 设置上机器 id。

 

最后再判断一下,当前这台机房的这台机器上这一毫秒内,这是第几个请求,给这次生成 id 的请求累加一个序号,作为最后的 12 个 bit。

 

 最终一个 64 个 bit 的 id 就出来了,类似于:

 

0 - 1111111010 1111111111 0010000011 0000111000 1 -  00000- 00000 - 000000010010

 

这个算法可以保证说,一个机房的一台机器上,在同一毫秒内,生成了一个唯一的 id。可能一个毫秒内会生成多个 id,但是有最后 12 个 bit 的序号来区分开来。

 

三.java实现方式

public class SnowflakeIdWorker {

    // ==============================Fields===========================================//
    /** 开始时间截 (2015-01-01) */
    private final long twepoch = 1420041600000L;

    /** 机器id所占的位数 */
    private final long workerIdBits = 5L;

    /** 数据标识id所占的位数 */
    private final long datacenterIdBits = 5L;

    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);

    /** 支持的最大数据标识id,结果是31 */
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);

    /** 序列在id中占的位数 */
    private final long sequenceBits = 12L;

    /** 机器ID向左移12位 */
    private final long workerIdShift = sequenceBits;

    /** 数据标识id向左移17位(12+5) */
    private final long datacenterIdShift = sequenceBits + workerIdBits;

    /** 时间截向左移22位(5+5+12) */
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;

    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    /** 工作机器ID(0~31) */
    private long workerId;

    /** 数据中心ID(0~31) */
    private long datacenterId;

    /** 毫秒内序列(0~4095) */
    private long sequence = 0L;

    /** 上次生成ID的时间截 */
    private long lastTimestamp = -1L;

    //==============================Constructors=====================================//
    /**
     * 构造函数
     * @param workerId 工作ID (0~31)
     */
    public SnowflakeIdWorker(long workerId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        this.workerId = workerId;
        this.datacenterId = 1;
    }
    /**
     * 构造函数
     * @param workerId 工作ID (0~31)
     * @param datacenterId 数据中心ID (0~31)
     */
    public SnowflakeIdWorker(long workerId, long datacenterId) {
        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;
    }

    // ==============================Methods==========================================//
    /**
     * 获得下一个ID (该方法是线程安全的)
     * @return SnowflakeId
     */
    public synchronized long nextId() {
        long timestamp = timeGen();

        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
        if (timestamp < 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;
        }

        //上次生成ID的时间截
        lastTimestamp = timestamp;

        //移位并通过或运算拼到一起组成64位的ID
        return ((timestamp - twepoch) << timestampLeftShift) 
                | (datacenterId << datacenterIdShift) 
                | (workerId << workerIdShift) 
                | sequence;
    }

    /**
     * 阻塞到下一个毫秒,直到获得新的时间戳
     * @param lastTimestamp 上次生成ID的时间截
     * @return 当前时间戳
     */
    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    /**
     * 返回以毫秒为单位的当前时间
     * @return 当前时间(毫秒)
     */
    protected long timeGen() {
        return System.currentTimeMillis();
    }
}
 

四.测试

 public static void main(String[] args) {
        SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);
        for (int i = 0; i < 100; i++) {
            long id = idWorker.nextId();
            System.out.println(id+"--------"+Long.toBinaryString(id));
        }
    }

测试结果:

647824078551519232--------100011111101100010001001000100101111000000100001000000000000
647824078551519233--------100011111101100010001001000100101111000000100001000000000001
647824078551519234--------100011111101100010001001000100101111000000100001000000000010
647824078551519235--------100011111101100010001001000100101111000000100001000000000011
647824078551519236--------100011111101100010001001000100101111000000100001000000000100
647824078555713536--------100011111101100010001001000100101111010000100001000000000000
647824078555713537--------100011111101100010001001000100101111010000100001000000000001
647824078555713538--------100011111101100010001001000100101111010000100001000000000010
647824078555713539--------100011111101100010001001000100101111010000100001000000000011
647824078555713540--------100011111101100010001001000100101111010000100001000000000100
647824078555713541--------100011111101100010001001000100101111010000100001000000000101
647824078555713542--------100011111101100010001001000100101111010000100001000000000110
647824078555713543--------100011111101100010001001000100101111010000100001000000000111
647824078555713544--------100011111101100010001001000100101111010000100001000000001000
647824078555713545--------100011111101100010001001000100101111010000100001000000001001
647824078555713546--------100011111101100010001001000100101111010000100001000000001010
647824078559907840--------100011111101100010001001000100101111100000100001000000000000
647824078559907841--------100011111101100010001001000100101111100000100001000000000001
647824078559907842--------100011111101100010001001000100101111100000100001000000000010
647824078559907843--------100011111101100010001001000100101111100000100001000000000011
647824078559907844--------100011111101100010001001000100101111100000100001000000000100
647824078559907845--------100011111101100010001001000100101111100000100001000000000101
647824078559907846--------100011111101100010001001000100101111100000100001000000000110
647824078559907847--------100011111101100010001001000100101111100000100001000000000111
647824078559907848--------100011111101100010001001000100101111100000100001000000001000
647824078559907849--------100011111101100010001001000100101111100000100001000000001001
647824078559907850--------100011111101100010001001000100101111100000100001000000001010
647824078559907851--------100011111101100010001001000100101111100000100001000000001011
647824078559907852--------100011111101100010001001000100101111100000100001000000001100
647824078559907853--------100011111101100010001001000100101111100000100001000000001101
647824078559907854--------100011111101100010001001000100101111100000100001000000001110
647824078564102144--------100011111101100010001001000100101111110000100001000000000000
647824078564102145--------100011111101100010001001000100101111110000100001000000000001
647824078564102146--------100011111101100010001001000100101111110000100001000000000010
647824078564102147--------100011111101100010001001000100101111110000100001000000000011
647824078564102148--------100011111101100010001001000100101111110000100001000000000100
647824078564102149--------100011111101100010001001000100101111110000100001000000000101
647824078564102150--------100011111101100010001001000100101111110000100001000000000110
647824078564102151--------100011111101100010001001000100101111110000100001000000000111
647824078564102152--------100011111101100010001001000100101111110000100001000000001000
647824078564102153--------100011111101100010001001000100101111110000100001000000001001
647824078564102154--------100011111101100010001001000100101111110000100001000000001010
647824078564102155--------100011111101100010001001000100101111110000100001000000001011
647824078564102156--------100011111101100010001001000100101111110000100001000000001100
647824078564102157--------100011111101100010001001000100101111110000100001000000001101
647824078564102158--------100011111101100010001001000100101111110000100001000000001110
647824078564102159--------100011111101100010001001000100101111110000100001000000001111
647824078568296448--------100011111101100010001001000100110000000000100001000000000000
647824078568296449--------100011111101100010001001000100110000000000100001000000000001
647824078568296450--------100011111101100010001001000100110000000000100001000000000010
647824078568296451--------100011111101100010001001000100110000000000100001000000000011
647824078568296452--------100011111101100010001001000100110000000000100001000000000100
647824078568296453--------100011111101100010001001000100110000000000100001000000000101
647824078568296454--------100011111101100010001001000100110000000000100001000000000110
647824078568296455--------100011111101100010001001000100110000000000100001000000000111
647824078568296456--------100011111101100010001001000100110000000000100001000000001000
647824078568296457--------100011111101100010001001000100110000000000100001000000001001
647824078568296458--------100011111101100010001001000100110000000000100001000000001010
647824078568296459--------100011111101100010001001000100110000000000100001000000001011
647824078568296460--------100011111101100010001001000100110000000000100001000000001100
647824078568296461--------100011111101100010001001000100110000000000100001000000001101
647824078568296462--------100011111101100010001001000100110000000000100001000000001110
647824078568296463--------100011111101100010001001000100110000000000100001000000001111
647824078568296464--------100011111101100010001001000100110000000000100001000000010000
647824078568296465--------100011111101100010001001000100110000000000100001000000010001
647824078572490752--------100011111101100010001001000100110000010000100001000000000000
647824078572490753--------100011111101100010001001000100110000010000100001000000000001
647824078572490754--------100011111101100010001001000100110000010000100001000000000010
647824078572490755--------100011111101100010001001000100110000010000100001000000000011
647824078572490756--------100011111101100010001001000100110000010000100001000000000100
647824078572490757--------100011111101100010001001000100110000010000100001000000000101
647824078572490758--------100011111101100010001001000100110000010000100001000000000110
647824078572490759--------100011111101100010001001000100110000010000100001000000000111
647824078572490760--------100011111101100010001001000100110000010000100001000000001000
647824078572490761--------100011111101100010001001000100110000010000100001000000001001
647824078576685056--------100011111101100010001001000100110000100000100001000000000000
647824078576685057--------100011111101100010001001000100110000100000100001000000000001
647824078576685058--------100011111101100010001001000100110000100000100001000000000010
647824078576685059--------100011111101100010001001000100110000100000100001000000000011
647824078576685060--------100011111101100010001001000100110000100000100001000000000100
647824078576685061--------100011111101100010001001000100110000100000100001000000000101
647824078576685062--------100011111101100010001001000100110000100000100001000000000110
647824078576685063--------100011111101100010001001000100110000100000100001000000000111
647824078576685064--------100011111101100010001001000100110000100000100001000000001000
647824078576685065--------100011111101100010001001000100110000100000100001000000001001
647824078576685066--------100011111101100010001001000100110000100000100001000000001010
647824078576685067--------100011111101100010001001000100110000100000100001000000001011
647824078576685068--------100011111101100010001001000100110000100000100001000000001100
647824078576685069--------100011111101100010001001000100110000100000100001000000001101
647824078576685070--------100011111101100010001001000100110000100000100001000000001110
647824078576685071--------100011111101100010001001000100110000100000100001000000001111
647824078576685072--------100011111101100010001001000100110000100000100001000000010000
647824078576685073--------100011111101100010001001000100110000100000100001000000010001
647824078580879360--------100011111101100010001001000100110000110000100001000000000000
647824078580879361--------100011111101100010001001000100110000110000100001000000000001
647824078580879362--------100011111101100010001001000100110000110000100001000000000010
647824078580879363--------100011111101100010001001000100110000110000100001000000000011
647824078580879364--------100011111101100010001001000100110000110000100001000000000100
647824078580879365--------100011111101100010001001000100110000110000100001000000000101
647824078580879366--------100011111101100010001001000100110000110000100001000000000110

五.结束语

     1.总之就是用一个 64 bit 的数字中各个 bit 位来设置不同的标志位,区分每一个 id。

     2.实际中我们的机器并没有那么多,可以改进改算法,将10bit的机器id优化和我们系统相关的业务。

     3.雪花算法只是一种思想,活学活用,切记生搬硬套。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值