17.分布式自增ID雪花算法

分布式ID生成-雪花算法 一、介绍 雪花算法的原始版本是scala版,用于生成分布式ID(纯数字,时间顺序),订单编号等。 自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景。 GUID:采用无意义字符串,数据量增大时造成访问过慢,且不宜排序。 1 1bit,不用,因为二进制中最高位是符号位,1表示负数,0表示正数。生成的id一般都是用整数,所以最高位固定为0。 41bit-时间戳,用来记录时间戳,毫秒级。 - 41位可以表示个数字, - 如果只用来表示正整数(计算机中正数包含0),可以表示的数值 阅读详情

目的:在高并发场景下实现不重复的id值


1.在mysql数据库中,主键为自增,但在高并发分布式场景下,需要在自增字段的基础上加上机器码等特征码,用来区分id

启动顺序:eureka–>saasplatform-common–>saasplatform-coupon-war-core
在chitai-public的IDeploy中配置数据库生成自增id的配置,初始值设为1

注意:没有配置则会报错:
在这里插入图片描述
解决办法:
在指定位置创建两个文件,设置初始值都是1


2.雪花算法代码:(生成64位长度18的id)

  • 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0
  • 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
  • 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69
  • 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId
  • 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号

    加起来刚好64位,为一个Long型。
package com.chitai.saasplatform.base.util;


import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;


import java.net.*;
import java.util.Enumeration;


/**
 * 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
 *
 * @create 2018-03-13 12:37
 **/

public class SnowFlake {

    public static Long mac;
    public static Long ip;


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

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

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

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

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

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

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

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

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

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

    /**
     * 获得下一个ID (该方法是线程安全的)
     *
     * @return SnowflakeId
     */
    private static 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;

        if (mac == null) {
            mac = getMac();
        }
        if (ip == null) {
            ip = getIp();
        }
        // 移位并通过或运算拼到一起组成64位的ID
        return ((timestamp - twepoch) << timestampLeftShift) //
                | (mac << datacenterIdShift) //
                | (ip << workerIdShift) //
                | sequence;
    }

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

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


    public static Long getMac() {
        try {
            NetworkInterface net=null;
            Enumeration Interfaces = NetworkInterface.getNetworkInterfaces();
            while(Interfaces.hasMoreElements())
            {
                NetworkInterface Interface = (NetworkInterface)Interfaces.nextElement();
                Interface.getHardwareAddress();
                if (Interface.getHardwareAddress()!=null){
//                    System.out.println(Interface.getHardwareAddress());
                    net=Interface;
                    break;
                }
            }
            byte[] macBytes = net.getHardwareAddress();
            int sum = 0;
            for (int b : macBytes) {
                sum += Math.abs(b);
            }
            return (long) (sum % 32);
        } catch (Exception e) {
            e.printStackTrace();
            return RandomUtils.nextLong(0, 31);
        }

    }

    public static Long getIp() {
        try {
            String hostAddress = Inet4Address.getLocalHost().getHostAddress();
            int[] ints = StringUtils.toCodePoints(hostAddress);
            int sums = 0;
            for (int b : ints) {
                sums += b;
            }
            return (long) (sums % 32);
        } catch (UnknownHostException e) {
            e.printStackTrace();
            // 如果获取失败,则使用随机数备用
            return RandomUtils.nextLong(0, 31);
        }

    }

    public static String getNextId() {
        return nextId() + String.format("%02d", System.nanoTime() % 100);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {

            System.out.println(SnowFlake.getNextId());
        }

    }


}
分布式ID生成方案-snowflake算法 背景 在互联网的业务系统中,涉及到各种各样的ID,这些ID需要保证全局唯一。我们称之为分布式ID,分布式ID需要满足 唯一性、趋势递增性、高可用性、高性能等特点。 snowflake算法,也叫雪花算法,是其中的一种分布式ID生成方案。是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。 讲解雪花算法前,我们先概述一下分布式ID有哪些生成方案。 分布式ID生成方案 分布式ID有以下几种生成方式: UUID 算法的核心思想是结合 阅读详情

相关推荐

分布式自增ID算法snowflake(雪花算法)

前言 在分布式系统中,有时存在需要使用全局唯一ID的场景。此时为了防止ID冲突,可以使用36位的UUID。但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。因此我们希望能使用一种简单点的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake(雪花算法)解决了这种需求,最初Twitter把存储系统从MySQL迁移到Cassandra,因为Cassandra没有顺序ID生成机制,所以开发了这样一套全局唯一ID生成服务。 snowflake结构 首位未使用,接下来的41位

许文杰的博客 1170

Java系列之雪花算法和原理

SnowFlake 算法:是 Twitter 开源的分布式 id 生成算法。 核心思想:使用一个 64 bit 的 long 型的数字作为全局唯一 id。 首先了解一下雪花ID的结构:从网上盗用一张; 针对上面各个部分做简单说明: 1bit:不用;因为二进制中最高位是符号位,1表示负数,0表示正数。生成的id一般都是用整数,所以最高位固定为0。 41bit-时间戳,用来记录时间戳,毫秒级。 41位可以表示241-1个数字, 如果只用来表示正整数(计算机中正数包含0),可以表示的数值范围是:0

增量星球 2978

ego-planner启动参数深度解析:从配置到实战避障应用

本文深入解析EGO-Planner启动参数的配置与实战应用,重点探讨无人机自主导航中的避障性能优化。通过环境感知、运动约束和算法控制三类参数的详细说明,结合ROS和RViz工具,提供从基础配置到高级调优的完整指南,帮助开发者提升无人机在复杂场景下的规划效率和安全性。

rum55的博客 246

雪花算法(SnowFlake)

现在的服务基本是分布式、微服务形式的,而且大数据量也导致分库分表的产生,对于水平分表就需要保证表中 id 的全局唯一性。对于 MySQL 而言,一个表中的主键 id 一般使用自增的方式,但是如果进行水平分表之后,多个表中会生成重复的 id 值。那么如何保证水平分表后的多张表中的 id 是全局唯一性的呢?如果还是借助数据库主键自增的形式,那么可以让不同表初始化一个不同的初始值,然后按指定的步长进行自增。例如有3张拆分表,初始主键值为1,2,3,自增步长为3。当然也有人使用 UUID 来作为主键,但是 UUID

fox_bert的博客 776

从零到一:基于Docker与OSM数据构建Valhalla路径规划服务及Mapbox风格可视化

本文详细介绍了如何从零开始,基于Docker容器技术快速部署开源的Valhalla路径规划服务。通过获取免费的OSM地图数据并构建路网,最终实现服务调用与Mapbox风格的地图可视化,为出行应用原型开发或本地化路径规划服务提供了一套完整、高效的实践方案。

weixin_29297127的博客 161

用大白话讲解Carplay(原创)

用大白话讲解Carplay: Carplay是美国苹果公司开发的一套服务,用户通过这套服务可以将iPhone与车载系统连接,然后在车载大屏上操作使用iPhone手机。个人理解,Carplay不能叫车载系统,不是操作系统,只能算一种服务。让你在车上的大屏上使用iPhone,这样用起来更方便,不需要在手机小屏幕上操作。基于这一点,有些人也说Carplay就是个投屏的功能,将手机屏幕投屏到了车机大屏上。可以简单这么理解,但是并不只是投屏这么简单,如果只是投屏的话,车子只是起到了一个显示器的功能,其实不止,手机和

cici2013的专栏 2万+

生成17位id

package ssm.itcast.util; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; //生成17位id public class IdUtil { public static String getId(String str){ String sdf = new...

qq_38941333的博客 713

rag综述——RAG技术发展流程、最新技术挑战与系统级优化

RAG技术发展综述:本文系统梳理了检索增强生成(RAG)技术的演进历程,从2017年开放域问答中的早期探索,到2020年正式提出RAG架构并与大模型深度融合,再到2025年向系统化、可信化和智能体化发展。当前RAG面临检索可靠性、系统效率和生成可信度三大核心挑战,解决方案包括领域自适应训练、强化语义编码、迭代检索策略等优化方向。未来RAG将向GraphRAG、SafeRAG等方向发展,从单纯性能优化转向构建可控、可审计的语言系统框架,成为高可靠大模型应用的基础设施。

lovehu6686的博客 1240

ID生成器,Twitter的雪花算法(Java)

/** * Twitter_Snowflake * SnowFlake的结构如下(每部分用-分开): * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是

xiaopeng9275的博客 1万+

别再让 AI 瞎写 SAP 代码了!这套 Claude Code Skill 的验证机制才是关键

本文深入解析了专为SAP CAP开发设计的AI辅助工具sap-cap-capire的技术架构。该工具采用四层设计:协议层集成MCP和LSP实现实时模型访问与语法检查;智能层通过4个专业化Agent(数据建模、服务开发等)分工协作;验证层确保代码质量;知识层存储文档模板。这种工程化设计解决了通用AI在CAP开发中面临的上下文不足、专业性缺失和代码质量保证等核心问题,通过本地化服务和实时反馈机制显著提升了开发效率。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 881

【Altium designer】BOM导出 Bill of Materials 如何自定义格式

【Altium designer】如何自定义BOM导出格式 我们用Excel做一个xx.xlt的2003的模版文件,取文件名为:AltiumDesiger PCB BOM Template.xlt 将AltiumDesiger PCB BOM Template.xlt文件存放在:AltiumDesiger 安装目录的Template文件夹内

夜半少年的博客 2717

雪花算法snowflake分布式id生成原理详解,以及对解决时钟回拨问题几种方案讨论

雪花算法的原理很简单,主要由时间戳+机器id+序列号生成64bit的ID,整体趋势递增,且全局唯一,性能也不错。每种组成标识的bit都可以自定义,灵活性很高。因为雪花算法强依赖机器时钟,就难以避免时钟回拨问题,解决的方式很多,无非从避免和缓解两个角度出发。

你学废了吗? 9921

【入门AUTOSAR网络管理测试】AUTOSAR网络管理规范需求解读

AUTOSARAutomotive Open System Architecture,汽车开放系统架构,由全球汽车制造商、部件供应商及其他电子、半导体和软件系统公司联合建立,致力于制定汽车电子软件标准的联盟。网络管理网络管理的目的是使网络中的ECU节点有序的睡眠和唤醒。在没有通信需求的时候睡眠,在需要通信的时候唤醒,可以节约汽车电池的电量。

测试领域技术分享 5163

自增ID、UUID、雪花算法的区别

自增ID、UUID、雪花算法的区别

qq_59093178的博客 579

磁悬浮分子泵:起源、现状与未来趋势深度解析

摘要 磁悬浮分子泵作为高真空获取的关键设备,通过磁悬浮技术实现转子无接触高速运转,大幅提升了真空系统的性能和可靠性。本文系统梳理了分子泵从机械轴承到磁悬浮的技术演变历程,分析了当前行业格局及主要厂商产品特性,包括爱德华兹、普发真空等国际巨头的技术优势。研究进一步探讨了磁悬浮分子泵在半导体制造、科研设备等领域的核心应用,通过数学模型揭示了其性能参数关系。最后,展望了未来在智能化、节能化等方面的发展趋势,为相关领域的技术创新提供参考。 关键词:磁悬浮分子泵;高真空技术;半导体制造;科研设备;技术发展

技术工作者 690

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Java使用雪花算法实现生成全局唯一id

简介 雪花的基本形状是六角形,但是大自然中却几乎找不出两朵完全相同的雪花 我们生成ID的方式有多种,比如说UUID,比如说自动增长... 使用场景 随着业务的增长与用户数量的增长,单个服务越来越多,数据库也分得越来越细,有些一个业务分成好几个库,这时候自增主键或者序列之类的主键id生成方式已经不再满足需求,分布式系统中需要的是一个全局唯一的id生成规则 雪花算法的结构如下(每部分用-分开): 0 - 0000000000 0000000000 0000000000 0000000000 0

田野上的风筝 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

SpringBoot快速开发(六)【雪花算法(snowflake)自增ID】

参考:https://blog.csdn.net/linghuanxu/article/details/78896317 一、为什么用snowflake     数据库自增有自增ID,但是使用起来有以下几个问题: 会依赖于数据库的具体实现,比如,mysql有自增,oracle没有,得用序列,mongo似乎也没有。 自增ID是连续的,它就依赖于数据库自身的锁,所以数据库就有瓶颈。     雪...

nsxqf的博客 2万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

分布式ID 与自增区别

根据业务需求合理选择ID生成策略,在分布式环境下通常优先考虑分布式ID方案,但在特定场景下自增ID仍具有不可替代的优势。[类型前缀(2位)][时间戳(32位)][自增序列(20位)][机器ID(10位)]:水平扩展时需考虑分库分表后的ID冲突。-- 实例2分配100万-200万。需要隐藏业务量的场景(安全考虑)-- PostgreSQL序列。// 使用递增计数器+机器ID。高并发写入需求(如电商下单)-- 实例1分配1-100万。-- 采用分段分配策略。:各节点独立生成ID。-- MySQL实现。

C18298182575的博客 1003

分布式唯一ID生成之雪花算法

分布式ID生成之雪花算法 分布式唯一ID的方案有很多,本文主要讨论了雪花算法,组成结构大致分为了无效位、时间位、机器位和序列号位。 唯一ID可以标识数据的唯一性,在分布式系统中生成唯一ID的方案有很多,常见的方式大概有以下三种: 依赖数据库,使用如MySQL自增列或Oracle序列等。 UUID随机数 snowflake雪花算法(本文将要讨论) 一、数据库和UUID方案的不足之处 采用数据库自增序列: 读写分离时,只有主节点可以进行写操作,可能有单点故障的风险 分表分库,数据迁移合并等比较麻烦 UUID随机

weixin_43564627的博客 839

雪花算法生成ID【细糠】

ID生成策略,UUID的介绍,数据库自增的利弊,以及保姆级讲解雪花算法

记录学习,共同进步 2190

全局唯一ID实现方案——雪花算法

Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将 64-bit位分割成多个部分,每个部分代表不同的含义。而 Java中64bit的整数是Long类型,所以在 Java 中 SnowFlake 算法生成的 ID 就是 long 来存储的。这样的划分之后相当于在一毫秒一个数据中心的一台机器上可产生4096个有序的不重复的ID。但是我们 IDC 和机器数肯定不止一个,所以毫秒内能生成的有序ID数是翻倍的。

Lxl1418的博客 1677

雪花算法实现分布式环境下的高效动态ID生成

雪花算法是Twitter提出的分布式ID生成方案,通过64位分段设计实现高性能ID生成。文章详细解析了算法原理:1位符号位+41位时间戳(69年跨度)+5位数据中心ID+5位工作节点ID+12位序列号(单机每毫秒4096个ID)。提供了完整的Python实现,包括初始化参数校验、线程安全处理、时钟回拨异常检测等关键逻辑。算法优势在于去中心化、趋势递增和高吞吐量,适用于大规模分布式系统。实现中通过位运算高效拼接各部分,并处理了序列号溢出、多线程竞争等边界情况,保证了ID生成的可靠性和唯一性。

闲人编程的博客 1690

分布式 ID 生成方案总结

分布式ID生成方案对比与雪花算法详解 本文介绍了四种常见的分布式ID生成方案: UUID:简单但无序且占用空间大 数据库号段模式:有序但依赖数据库 Redis自增:高性能但依赖Redis持久化 雪花算法:本地生成、高性能、趋势有序 重点分析了雪花算法的实现原理: 64位ID结构划分(时间戳41位+数据中心5位+机器ID5位+序列号12位) 单机每秒可生成400万+ID 包含时钟回拨处理逻辑 雪花算法的优缺点: 优点:高性能、趋势有序、无外部依赖 缺点:时钟回拨问题、机器ID需提前分配、同一毫秒内不完全有序

GQ_666的博客 1441

分布式ID之雪花算法

雪花算法、时间回拨

q_334173630的博客 1025

数据库主键设计:自增ID、UUID与雪花算法的探讨

在数据库设计中,选择合适的主键是至关重要的。主键的选择不仅影响到数据的唯一性,还关系到查询性能、存储空间以及系统的可扩展性。当雪花算法中的序列号达到最大值后重置为零时,可能会导致短时间内生成的ID分布不均匀。一种解决方案是在序列号部分引入时间戳的最后一位,这样即使序列号重置,ID也不会完全相同,从而解决了分布不均的问题。在实际应用中,应根据具体的业务需求和系统规模来选择最合适的主键策略。最终组合得到的64位ID将是这些部分的二进制形式的按位或运算结果。适用于单库单表且不需要考虑分布式环境的情况;

2301_80011650的博客 1629

7.雪花算法(高并发场景下自增id的生成)

前言: 在高并发场景下,如果使用mysql数据库自增的id,那么同一时间内会有重复的id生成。 一、雪花算法的原理: 使用一个 64 bit 的 long 型的数字作为全局唯一 id 第一个部分是1 个 bit:0,这个是无意义的。由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0 第二个部分是 41 个 bit:表示的是时间...

CC的博客 8309
上一篇: 16.禁用双层for循环后的替代方法
下一篇: 9.Excel转List
cuichen97
博客等级 码龄7年 34粉丝 209原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值