雪花算法生成ID

2023-10-26

雪花算法生成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结果展示:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

雪花算法生成ID 的相关文章

  • 使用three.js在Vue中创建3D图

    使用three js创建3D图 1 电梯 注意 只为自己做笔记用的 全部是收藏的博客地址当电梯用 1 电梯 1 展示 https wow techbrood com fiddle 34388 闪光球 https blog csdn net
  • 字典树(介绍+实现+例题)

    字典树 介绍 字典树也叫前缀树 Trie树等 字典树是一颗非典型的多叉树模型 字典树的结点包含有一个长度为26的指针数组 分别对应26个字母 指向当前字母对应的下一个字母 字典树充分利用了字符串的公共前缀 包含三个单词 sea sells

随机推荐

  • 【华为OD统一考试B卷

    在线OJ 已购买本专栏用户 请私信博主开通账号 在线刷题 运行出现 Runtime Error 0Aborted 请忽略 华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一
  • 多线程如何在 C 中实现?

    多线程 英语 multithreading 是指从软件或者硬件上实现多个线程并发执行的技术 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多于一个线程 进而提升整体处理性能 具有这种能力的系统包括对称多处理机 多核心处理器以及芯片级
  • java内存马查杀工具

    java memshell scanner 扫描java内存马
  • 模版之AnyType

    title 模版之AnyType date 2023 02 19 21 49 53 permalink pages 54a0bf categories 通用领域 编程语言 C tags C 元编程 author name zhengzhib
  • Java里NonNull和NotNull

    https blog csdn net yangyangrenren article details 121180269 lombok NonNull 这个 annotation 是 lombok 提供的 根据官方的解释可以看出它是用来辅助
  • 华为OD机试 - 组成最大数(Java)

    题目描述 小组中每位都有一张卡片 卡片上是6位内的正整数 将卡片连起来可以组成多种数字 计算组成的最大数字 输入描述 号分割的多个正整数字符串 不需要考虑非数字异常情况 小组最多25个人 输出描述 最大的数字字符串 用例 输入 22 221
  • Pycharm 交互式Console BUG问题解决 - OSError: [Errno 22] Invalid argument: ‘D:\pyCHram\<input>‘

    引言 Pycharm python console是一个很好用的交互式编程栏 但是在跑一些深度学习模型的时候 偶尔会发生类似于这种错误的报错 导致无法在交互式的Python console模式下运行测试代码 Pycharm 问题解决 OSE
  • 攻防世界NewsCenter思路

    打开环境后发现是这样一个页面 考虑到xss或者sql注入 尝试了alert无果 便试试sql注入 随便输入aaa后使用burp抓包 将这些保存在1 txt里 用sqlmap抓包 命令 sqlmap py r 1 txt dbs 这里看到一个
  • U-Boot相关命令开发板烧写问题及解决方案

    前言 最近在学习u boot命令在开发板的烧写 在进行该实验的过程中 出现了很多问题和错误 在这里我根据自己的开发历程 将我出现的几大问题进行了汇总 并附有相关解决办法 这些解决方案都经过我亲自验证有效 希望能让大家在开发过程中有所启发 问
  • C++实现复化梯形公式求积分算法

    1 算法原理简介 步1 将积分区间2n等分 步2 调用复化梯形公式 2 应用实例 取 n 10 利用复化梯形公式计算积分 3 程序代码 include
  • BLDC无刷直流电机驱动电路-硬石电子

    1 BLDC无刷直流电机驱动电路 因为BLDC是三相完全一样的驱动电路 下图为其中一相电路图 其他两相完全一样 主要元器件 高速光耦 TLP715 MOS管驱动IC IR2110S MOS IRF540NS D7和C13为自举电路 2 霍尔
  • ubuntu18.04安装之后没有网络,不显示网络图标

    新安装的ubuntu18 04 06安装完成后插着网线 但是没有有线网 桌面上不显示网络图标 原因是因为ubuntu系统安装时自带的网卡驱动不兼容导致的 下面来讲解解决方法 首先 先试用手机连接线 将手机连接到电脑usb口 使用手机上的US
  • matlab中hash和map的用法总结

    若要在matlab中使用hash 有两种方式 1 采用matlab官方给出的结构类型map containers Map http cn mathworks com help matlab map containers html 2 调用J
  • 到底要不要孩子学习机器人编程

    人工智能发展迅猛 很多技术已经成熟应用到我们生活场景中 如果再不从小让孩子学习机器人编程教育 掌握更多编程语言 那未来就out啦 格物斯坦小坦克可以告诉你关于机器人编程要不要学的答案 教育部也将启动中小学生信息素养测评 并推动在中小学阶段设
  • uni-app利用chooseImage方法封装一个图片选择组件

    效果如图 可以预览 长按可删除 可以设置最多上传数量 这里封装的组件有个MaxNumber number类型 用的时候在父组件传就行了 这里默认给的8 废话不多说直接上代码 封装好了之后我们用的时候只需要引入直接用就行
  • 从etcd看Raft协议

    首先 什么是etcd 看官方的定义 A highly available key value store for shared configuration and service discovery 翻译过来就是 用于配置共享和服务发现的K
  • 动态规划(五)

    01背包问题 01 Knapsack problem 有10件货物要从甲地运送到乙地 每件货物的重量 单位 吨 和利润 单位 元 如下表所示 由于只有一辆最大载重为30t的货车能用来运送货物 所以只能选择部分货物配送 要求确定运送哪些货物
  • 如何快速画AltiumDesigner封装——用Ultralibrarian生成库文件---官网最新打开方式

    如何用Ultralibrarian生成库文件 官网最新打开方式 步骤1 下载元器件 步骤2 AltiumDesigner生成库文件 Ultralibrarian软件比较常用的生成库文件的软件 网上对于它的介绍大多还停留在软件使用层面上 但官
  • 区块链的工作流程

    工作流程 通过前两篇文章 相信大家对区块链有了基本的认识 区块链系统有很多种 第一个应用区块链的软件就是比特币 事实上区块链就是比特币带出来的 到现在为止 已经出现很多基于区块链的系统了 比如超级账本 以太坊等 每一类系统都有自己的特点 无
  • 雪花算法生成ID

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