广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java 基于雪花算法生成分布式id
  • 264
分享到

Java 基于雪花算法生成分布式id

2024-04-02 19:04:59 264人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录SnowFlake算法原理介绍 算法实现 SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为

SnowFlake算法原理介绍

分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为了让整个系统能够承载更大的访问量。诸如订单号这些我们需要它是全局唯一的,同时我们基本上都会将它作为查询条件;出于系统安全考虑不应当让其它人轻易的就猜出我们的订单号,同时也要防止公司的竞争对手直接通过订单号猜测出公司业务体量;为了保证系统的快速响应那么生成算法不能太耗时。而雪花算法正好解决了这些问题。

SnowFlake 算法(雪花算法), 是Twitter开源的分布式id生成算法。其核心思想就是: 使用一个64 bit的long型的数字作为全局唯一id。它的结构如下:

下面我们来对每一部分进一步的分析:

  • 符号标识位(1位):计算机中为了区分负数(1)和正数(0),设计者将第一位做为符号位,ID通常使用正数,因此最高位固定为0;
  • 41位时间截(毫秒),这个是使用 当前时间 减去 开始时间 得到的值;因此一旦我们的算法投入使用,那么程序中设置的开始时间就不能再去随意更改了,否则将可能出现重复的id值;

由于是基于时间来实现的且只有41位,由此可以计算出该算法只能使用70年左右:(2^41)/(1000*60*60*24*365) = 69.7 年 ;

  • 10位机器ID:共计1024个节点,通常将其分为2部分:机房ID(dataCenterId) 和 机器ID(workerId);
  • 12 位序列号:毫秒内的计数,共计4098个;简单来说就是每毫秒内从0开始计算得到值;
  • 最终SnowFlake算法总结如下:整体上按照时间自增排序,并且整个分布式系统内不会产生ID 碰撞(由机房ID和机器ID作区分),并且效率较高。最多支持1024台机器,每台机器每毫秒能够生成最多4096个ID,整个集群理论上每秒可以生成 1024 * 1000 * 4096 = 42 亿个ID。

这里不要觉得每毫秒4098个ID少了,我们计算一下每台机器理论上每秒可以支持 4096*1000 = 400万左右;要知道天猫双11那么大的订单量每秒也才50万笔;因此是完全够用的。

算法实现

我们在上面已经了解了SnowFlake的算法结构,下面是Java版本的实现。注意我们在实现该算法时,不一定要死死的按照上面的来实现,可以根据自身业务情况进行定制化;比如说机器ID,对于大部分的小项目来说根本不会分啥机房,因此我们完全可以根据服务器IP来弄;同时Twitter公布的算法中最终生成的id长度为15,但是还是根据自身业务情况进行调整。比如标准的算法只支持使用70年左右,但是我们可以通过扩展长度来增加年限。


public class SnowFlakeIdWorker {

    
    private static final long TW_EPOCH = 1622476800000L;

    
    private static final long WORKER_ID_BITS = 5L;

    
    private static final long DATA_CENTER_ID_BITS = 5L;

    
    private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);

    
    private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);

    
    private static final long SEQUENCE_BITS = 12L;

    
    private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;

    
    private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;

    
    private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;

    
    private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);

    
    private final long workerId;

    
    private final long dataCenterId;

    
    private long sequence = 0L;

    
    private long lastTimestamp = -1L;

    
    public SnowFlakeIdWorker(long workerId) {
        // 计算最大值
        long maxMachineId = (MAX_DATA_CENTER_ID + 1) * (MAX_WORKER_ID + 1) - 1;

        if (workerId < 0 || workerId > maxMachineId) {
            throw new IllegalArgumentException(String.fORMat("Worker ID can't be greater than %d or less than 0", maxMachineId));
        }

        // 取高位部分作为机房ID部分
        this.dataCenterId = (workerId >> WORKER_ID_BITS) & MAX_DATA_CENTER_ID;
        // 取低位部分作为机器ID部分
        this.workerId = workerId & MAX_WORKER_ID;
    }

    
    public SnowFlakeIdWorker(long dataCenterId, long workerId) {
        if (workerId > MAX_WORKER_ID || workerId < 0) {
            throw new IllegalArgumentException(String.format("Worker ID can't be greater than %d or less than 0", MAX_WORKER_ID));
        }
        if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
            throw new IllegalArgumentException(String.format("DataCenter ID can't be greater than %d or less than 0", MAX_DATA_CENTER_ID));
        }

        this.workerId = workerId;
        this.dataCenterId = dataCenterId;
    }

    
    public synchronized long nextId() {
        long timestamp = timeGen();
        // 如果当前时间小于上一次 ID 生成的时间戳,说明发生时钟回拨,为保证ID不重复抛出异常。
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            // 同一时间生成的,则序号+1
            sequence = (sequence + 1) & SEQUENCE_MASK;
            // 毫秒内序列溢出:超过最大值
            if (sequence == 0) {
                // 阻塞到下一个毫秒,获得新的时间戳
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            // 时间戳改变,毫秒内序列重置
            sequence = 0L;
        }
        // 上次生成 ID 的时间戳
        lastTimestamp = timestamp;

        // 移位并通过或运算拼到一起
        return ((timestamp - TW_EPOCH) << TIMESTAMP_LEFT_SHIFT)
                | (dataCenterId << DATA_CENTER_ID_SHIFT)
                | (workerId << WORKER_ID_SHIFT)
                | sequence;
    }

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

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

使用示例


// 初始化
SnowFlakeIdWorker idWorker = new SnowFlakeIdWorker(1, 0);

// 生成ID
for(int i=0; i<100; i++){
    System.out.println(idWorker.nextId());
}

注意服务器不能发生时钟回拨,即系统时间发生错误,因为雪花算法是基于时间来生成,所有当发生时钟回拨后会导致出现重复ID的问题。

以上就是Java 基于雪花算法生成分布式id的详细内容,更多关于Java 雪花算法生成分布式id的资料请关注编程网其它相关文章!

--结束END--

本文标题: Java 基于雪花算法生成分布式id

本文链接: https://www.lsjlt.com/news/127767.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java 基于雪花算法生成分布式id
    目录SnowFlake算法原理介绍 算法实现 SnowFlake算法原理介绍 在分布式系统中会将一个业务的系统部署到多台服务器上,用户随机访问其中一台,而之所以引入分布式系统就是为...
    99+
    2022-11-12
  • springboot中使用雪花算法生成雪花ID
    目录1、什么是雪花算法2、雪花算法的优缺点3、spring boot项目中使用雪花算法使用1、引入雪花算法依赖2、在配置文件中配置雪花算法参数3、注入雪花算法对象1、什么是雪花算法 ...
    99+
    2023-03-19
    springboot生成雪花ID springboot 雪花ID
  • Go实现分布式唯一ID的生成之雪花算法
    目录背景:特性:雪花算法:分布式唯一ID的生成 背景: 在分布式架构下,唯一序列号生成是我们在设计一个尤其是数据库使用分库分表的时候会常见的一个问题 特性: 全局唯一,这是基本要求,...
    99+
    2022-11-13
  • spring boot中使用雪花算法生成雪花ID
    目录 1、什么是雪花算法 2、雪花算法的优缺点 3、spring boot项目中使用雪花算法使用 1、什么是雪花算法 雪花算法(Snowflake)是一种生成全局唯一ID的算法,由Twitter公司开发。它可以在分布式系统中生成全局唯...
    99+
    2023-09-05
    spring boot java spring 算法
  • Java使用雪花id生成算法详解
    目录什么是雪花算法位段详解优点问题实际应用具体实现什么是雪花算法 雪花算法的本质为生成一个64位长度的具有自增性的分布式全局唯一id。在64bits中,会对不同段的位进行划分。可分为...
    99+
    2022-12-20
    Java雪花id生成算法 Java雪花id
  • 基于雪花算法实现增强版ID生成器详解
    目录基于雪花算法的增强版ID生成器快速开始配置解析目前提供两个配置类详情生产推荐使用方式JMH 性能测试测试机硬件情况Sequence 配置参数JMH参数测试结果Tip基于雪花算法的...
    99+
    2022-11-13
    雪花算法实现ID生成器 雪花算法 ID生成
  • springboot中如何使用雪花算法生成雪花ID
    这篇文章主要介绍“springboot中如何使用雪花算法生成雪花ID”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“springboot中如何使用雪花算法生成雪花ID”文章能帮助大家解决问题。1、什么...
    99+
    2023-07-05
  • Java 通过手写分布式雪花SnowFlake生成ID方法详解
    目录SnowFlake算法SnowFlake优点SnowFlake不足SnowFlake算法 SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图: 分为...
    99+
    2022-11-13
  • Java怎么通过手写分布式雪花SnowFlake生成ID
    本文小编为大家详细介绍“Java怎么通过手写分布式雪花SnowFlake生成ID”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java怎么通过手写分布式雪花SnowFlake生成ID”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一...
    99+
    2023-06-29
  • mybatisplus雪花算法生成Id怎么使用
    这篇文章主要讲解了“mybatisplus雪花算法生成Id怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mybatisplus雪花算法生成Id怎么使用”吧!雪花算法实战建表DROP&...
    99+
    2023-07-02
  • mybatis-plus雪花算法生成Id使用详解
    目录前言一、mybatis-plus官网二、雪花算法实战三、实现分析四、为什么默认就是雪花算法五、主动设置Id生成策略总结前言 在实际开发过程中,数据库自增主键生成Id能满足大部分的...
    99+
    2022-11-13
  • PHP利用雪花(SnowFlake)算法生成唯一ID
    目录一、雪花算法原理解析1. 分布式ID常见生成策略2. 雪花算法的结构二、PHP源码实现案例1.demo12.demo2这个算法的好处很简单可以在每秒产生约400W个不同的16位数...
    99+
    2022-11-13
  • PHP怎么利用雪花算法生成唯一ID
    这篇文章主要讲解了“PHP怎么利用雪花算法生成唯一ID”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PHP怎么利用雪花算法生成唯一ID”吧!一、雪花算法原理解析1. 分布式ID常见生成策略分...
    99+
    2023-06-30
  • mybatis-plus 如何使用雪花算法ID生成策略
    目录mybatis-plus 可以通过@TableId注解指定主键生成策略看一下源码大概找一下雪花算法的实现方式自定义ID生成器实现Mybatis-plus 中生成雪花算法id的工具...
    99+
    2022-11-12
  • mybatis-plus怎么使用雪花算法ID生成策略
    本篇内容介绍了“mybatis-plus怎么使用雪花算法ID生成策略”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!mybatis-plus ...
    99+
    2023-06-21
  • GoLang分布式锁与snowflake雪花算法
    目录分布式id生成器分布式锁负载均衡go语言在网络服务模块有着得天独厚的优势;传送门详细介绍了涉及到的分布式相关技术。 分布式id生成器 Snowflake(雪花算法),由Twitt...
    99+
    2022-12-22
    GoLang分布式锁 GoLang snowflake雪花算法
  • mybatis-plus雪花算法自动生成机器id原理的示例分析
    这篇文章主要介绍了mybatis-plus雪花算法自动生成机器id原理的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。1、雪花算法原理  &nbs...
    99+
    2023-06-15
  • mybatis-plus雪花算法自动生成机器id原理及源码
    目录1、雪花算法原理2、自动生成唯一机器号源码1、雪花算法原理         雪花算法使用一个 64...
    99+
    2022-11-12
  • SpringBoot集成yitter-idgenerator(雪花漂移)分布式Id自增的实现
    目录场景实现方案基于第一种实现方案关键部分代码场景 yitter-idgenerator 是基于雪花算法进行改造的分布式ID自增算法,集成时需要为每个服务设置唯一的机器号,才能保证生...
    99+
    2022-11-12
  • java分布式ID生成方法是什么
    本篇内容介绍了“java分布式ID生成方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、需求缘起几乎所有的业务系统,都有生成一个唯...
    99+
    2023-06-04
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作