雪花算法生成ID

雪花算法生成ID

Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将64-bit位分割成多个部分,每个部分代表不同的含义。而Java中64bit的整数是Long类型,所以在Java中 SnowFlake算法生成的ID就是long来存储的。

  • 第1位占用1bit,其值始终是0,可看做是符号位不使用。

  • 第2位开始的41位是时间戳,41-bit位可表示2^41个数,每个数代表毫秒,那么雪花算法可用的时间年限是(1L<<41)/(1000L360024*365)=69年的时间。

  • 中间的10-bit位可表示机器数,即2^10=1024台机器,但是一般情况下我们不会部署这么台机器。如果我们对IDC(互联网数据中心)有需求,还可以将10-bit分5-bit给IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,具体的划分可以根据自身需求定义。

  • 最后12-bit位是自增序列,可表示2^12= 4096个数。

这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们IDC和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。
在这里插入图片描述
Java 代码实现

package com.royali.test;

public class SnowFlakeDistributedId {

    //开始时间戳
    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位;
    private final long datacenterIdShift = sequenceBits + workerIdBits;
    //时间戳向左移22位(12+5+5)
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    //生成序列的掩码,这里为4095
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
    //工作机器id
    private long workerId;
    //数据中心id
    private long datacenterId;
    //毫秒内序列
    private long sequence = 0L;
    //上次id的时间戳
    private long lastTimestamp = -1L;

    /**
     *
     * @param workerId 工作ID(0-31)
     * @param datacenterId 数据中心ID (0-31)
     */
    public SnowFlakeDistributedId(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;
    }

    public synchronized long nextId(){
        long timestamp = timeGen();
        //如果当前时间小于上次ID生成的时间戳,说明系统时钟回退过这个时候应该报错
        if (timestamp < lastTimestamp){
            throw new IllegalArgumentException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
        //如果是同一时间生成的,则进行毫秒内序列
        if (lastTimestamp == timestamp){
            sequence = (sequence+1) & sequence;
            //毫秒内序列溢出
            if (sequence == 0){
                // 阻塞到下一个毫秒,获得新的时间戳
                timestamp = tillNextMillis(lastTimestamp);
            }
        }else {
            sequence = 0L;
        }
        //上次生成ID的时间戳
        lastTimestamp = timestamp;
        //移位并通过或运算拼到一起组成64位的ID
        return ((timestamp -twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
    }

    private long tillNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp){
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }

    public static void main(String[] args) {
        SnowFlakeDistributedId idWorker = new SnowFlakeDistributedId(0, 0);
        for (int i = 0; i < 1000; i++) {
            System.out.println(idWorker.nextId());
        }
    }

}

id结果展示:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用Mybatis-Plus生成雪花算法生成id非常简单。Mybatis-Plus已经内置了雪花算法生成分布式唯一id的功能。你可以在IDEA中双击shift搜索Sequence类来查看具体的实现代码。这个类使用的就是雪花算法生成id。关于如何在项目中使用雪花算法生成id,你可以参考CSDN上的一篇博文《mybatis-plus雪花算法增强idworker》。这篇博文详细介绍了如何在Mybatis-Plus中配置和使用雪花算法生成id。你可以按照这篇博文的步骤进行操作,非常简单易懂。总结起来,使用Mybatis-Plus生成雪花算法生成id的步骤包括建表、新建测试工程和单元测试等。在实现分析中,你可以了解到为什么Mybatis-Plus默认就是使用雪花算法生成id。此外,你还可以通过主动设置id生成策略来使用Mybatis-Plus生成雪花算法生成id。Mybatis-Plus还提供了内置的雪花算法工具类IdWorker,方便你在项目中使用雪花算法生成id。希望这些信息对你有帮助!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [mybatis-plus雪花算法生成Id使用详解](https://blog.csdn.net/w1014074794/article/details/125604191)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闪耀太阳a

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值