分布式ID生成方法的超详细分析(全)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 目录前言1. UUID2. 数据库自增3. 数据库集群4. 数据库号段5. redis模式6. 雪花算法7. 其他总结前言关于什么是分布式ID数据量不是很多的时候,单一个数据库表可以支撑其业务,即使数据在大也可以主从复制到一定量的数据时,实现分库分表的时候,就需要一个全局唯一的ID,订单的编号就是分布式ID关于上面牵扯到的主从复制可看我之前的文章进行查缺补漏关于主从复制的超详细解析(全)关于数据库的分布式ID可看我之前在Mycat种提及到具体都有如下:在实现分库分表的情况下,数据库自增主

前言

关于什么是分布式ID

数据量不是很多的时候,单一个数据库表可以支撑其业务,即使数据在大也可以主从复制
到一定量的数据时,实现分库分表的时候,就需要一个全局唯一的ID,订单的编号就是分布式ID

关于上面牵扯到的主从复制
可看我之前的文章进行查缺补漏
关于主从复制的超详细解析(全)

关于数据库的分布式ID可看我之前在Mycat种提及到

具体都有如下

在实现分库分表的情况下,数据库自增主键已无法保证自增主键的全局唯一。为此,Mycat 提供了全局 sequence

  • 本地文件

优点:本地加载,读取速度较快
缺点:抗风险能力差,Mycat 所在主机宕机后,无法读取本地文件

  • 数据库方式

利用数据库一个表 来进行计数累加。但是并不是每次生成序列都读写数据库,这样效率太低。Mycat 会预加载一部分号段到 Mycat 的内存中,这样大部分读写序列都是在内存中完成的。如果内存中的号段用完了 Mycat 会再向数据库要一次

  • 时间戳方式

全局序列ID= 64 位二进制 (42(毫秒)+5(机器 ID)+5(业务编码)+12(重复累加) 换算成十进制为 18 位数的
long 类型,每毫秒可以并发 12 位二进制的累加。
优点:配置简单
缺点:18 位 ID 过长

而涉及到程序上实现的分布式ID可看下面的文章
可通过UUID、雪花算法等

1. UUID

具体UUID是什么以及可看我之前的文章
java之UUID.randomUUID().toString()详细解析(全)
这里直接push过来

UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,主要是让让分布式系统中的所有元素,都能有唯一的辨识信息。

  • 为了提高效率,常用的UUID可缩短至16位比特数值
  • 使用UUID的一个好处是可以为新的服务创建新的标识符

==源码==
生成的UUID标识符16位具体信息如下:

  • (1)当前日期和时间,值第一部分与时间有关(如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同)
  • (2)时钟序列
  • (3)全局唯一的IEEE机器识别号(如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得)
 public static UUID randomUUID() {
       
        SecureRandom ng = Holder.numberGenerator;
        byte[] randomBytes = new byte[16];
        ng.nextBytes(randomBytes);
        randomBytes[6]  &= 0x0f;  /* clear version        */
        randomBytes[6]  |= 0x40;  /* set to version 4     */
        randomBytes[8]  &= 0x3f;  /* clear variant        */
        randomBytes[8]  |= 0x80;  /* set to IETF variant  */
        return new UUID(randomBytes);
}

==通过randomUUID().toString()生成==
随机生成UUID的标识符是UUID类中的方法
而UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法

public class ThreadDemo4 {
    public static void main(String[] args) {
        //创建ArrayList集合
      List<String> list = new ArrayList<>();

        for (int i = 0; i <30; i++) {

            new Thread(()->{
                //向集合添加内容
                list.add(UUID.randomUUID().toString());
                //从集合获取内容
                System.out.println(list);
            },String.valueOf(i)).start();
        }
    }
}

代码截图
在这里插入图片描述

2. 数据库自增

前言中也有提及到数据库的方式,但是mycat的方式是放一定的序列到内存中,如果宕机之后,前面的序列不会更改,但是刚开始的序列号和之前的序列号会断开,也可以保证高可用

这种数据库的自增是通过数据库种的auto_increment,

用它来实现分布式服务风险比较大

3. 数据库集群

改进上面单个数据库自增的模式,因为怕宕机
那就多加入一个从机,实现主从复制或者是双主模式等

具体的规则就是设置一个起始值和步长值,实现两个mysql的不一样值
具体设置的方法为:

set @@auto_increment_offset = 1;     -- 起始值
set @@auto_increment_increment = 2;  -- 步长

但是如果突然加进来第三个服务器,前面两个序列号就都要重改,也比较麻烦

4. 数据库号段

从数据库批量的获取自增ID,每次从数据库取出一个号段范围,生成的自增ID加载到内存中

这与一开始前言所提及到的mycat比较相像
但是mycat是已经把一部分号段放置到内存中
而这里是在数据库取一部分,再放置到内存中,逻辑不一样

加入号段之后,在每个号段还要加上乐观锁(在数据库表中增加一个version字段),防止高并发的数据量
关于这部分乐观锁可看我之前的文章补充一些知识点,这里就不再赘述
java中各类锁的机制详细解析(全)

不会频繁的访问数据库,对数据库的压力小很多,因为有了缓存在内存中了

5. redis模式

利用redis的 incr命令实现ID的原子性自增

考虑到redis持久化的问题。redis有两种持久化方式RDB和AOF:

(1)RDB会定时打一个快照进行持久化,假如连续自增但redis没及时持久化,而这会Redis挂掉了,重启Redis后会出现ID重复的情况。

(2)AOF会对每条写命令进行持久化,即使Redis挂掉了也不会出现ID重复的情况,但由于incr命令的特殊性,会导致Redis重启恢复的数据时间过长。

6. 雪花算法

指定机器 & 同一时刻 & 某一并发序列,是唯一的。据此可生成一个64 bits的唯一ID(long)

组成部分(64bit)
1.第一位 占用1bit,其值始终是0,没有实际作用。
2.时间戳 占用41bit,精确到毫秒,总共可以容纳约69年的时间。
3.工作机器id 占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,做多可以容纳1024个节点。
4.序列号 占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID。

SnowFlake算法在同一毫秒内最多可以生成多少个全局唯一ID呢: 同一毫秒的ID数量 = 1024 X 4096 = 4194304

==最核心的是中间的10位工作机器ID的分配,做到自动生成workID,避免运维人员的去分配==

关于雪花算法详细分析可看这篇文章
理解分布式id生成算法SnowFlake

7. 其他

关于其他的自增,分布式ID,各大公司都有其一套的的算法
比如:

  • 滴滴出品(TinyID)

数据库中保存了可用的id号段,tinyid会将可用号段加载到内存中,之后生成id会直接内存中产生

  • 百度 (Uidgenerator)

百度的雪花算法是通过数据库来生成workID

  • 美团(Leaf)

美团是通过Zookeeper持久顺序节点的特性自动对snowflake节点配置wokerID

总结

方法 优点 缺点
UUID 1.容易实现,产生快。2.ID唯一。3.无需要中心化服务器。4.不会泄露商业机密 1.可读性过差。2.占用空间过多。3.影响数据库性能
数据库自增 实现简单,ID单调自增,数值类型查询速度快。 单点存在宕机风险,无法扛住高并发场景。
数据库集群 解决DB单点问题 不利于后续扩容,单点压力也会更大不适合高并发
数据库号段 解决单点压力 抗风险能力差,没有集群
redis中的icncr 原子性自增保证不重复 RDB挂掉后出现重复,AOF挂掉重启时间长
雪花算法 所有生成的id按时间趋势递增。不依赖数据库等第三方系统,以服务的方式部署,稳定性更高,生成ID的性能也是非常高的。可以根据自身业务特性分配bit位,非常灵活。 强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
设计模式 安全 Java
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
【分布式技术专题】「Tomcat技术专题」 探索Tomcat技术架构设计模式的奥秘(Server和Service组件原理分析)
35 0
|
2天前
|
SQL 算法
基于若依的ruoyi-nbcio流程管理系统修改代码生成的sql菜单id修改成递增id(谨慎修改,大并发分布式有弊端)
基于若依的ruoyi-nbcio流程管理系统修改代码生成的sql菜单id修改成递增id(谨慎修改,大并发分布式有弊端)
单向/双向V2G环境下分布式电源与电动汽车充电站联合配置方法(matlab代码)
单向/双向V2G环境下分布式电源与电动汽车充电站联合配置方法(matlab代码)
|
5天前
|
调度
考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(matlab代码)
考虑充电负荷空间可调度特性的分布式电源与电动汽车充电站联合配置方法(matlab代码)
|
5天前
|
调度
互动环境下分布式电源与电动汽车充电站的优化配置方法研究-全文复现matlab
互动环境下分布式电源与电动汽车充电站的优化配置方法研究-全文复现matlab
|
6天前
|
算法 关系型数据库 MySQL
Go语言中的分布式ID生成器设计与实现
【5月更文挑战第6天】本文探讨了Go语言在分布式系统中生成全局唯一ID的策略,包括Twitter的Snowflake算法、UUID和MySQL自增ID。Snowflake算法通过时间戳、节点ID和序列号生成ID,Go实现中需处理时间回拨问题。UUID保证全局唯一,但长度较长。MySQL自增ID依赖数据库,可能造成性能瓶颈。选择策略时需考虑业务需求和并发、时间同步等挑战,以确保系统稳定可靠。
113 0
|
13天前
|
数据采集 存储 运维
如何使用SkyWalking收集分析分布式系统的追踪数据
通过以上步骤,你可以使用 SkyWalking 工具实现对分布式系统的数据采集和可视化。SkyWalking 提供了强大的追踪和度量功能,帮助开发者和运维人员更好地理解系统的性能状况。欢迎关注威哥爱编程,一起学习成长。
|
25天前
|
存储 SQL 算法
搞定了 6 种分布式ID,分库分表哪个适合做主键?
在《ShardingSphere5.x分库分表原理与实战》系列的第七篇文章中,作者探讨了分布式ID在分库分表中的重要性,以及如何利用`ShardingSphere-jdbc`的多种主键生成策略。文章介绍了`UUID`、`NanoID`、自定义雪花算法和`CosId`等策略的优缺点,并警告不要在SQL中手动拼接主键字段。此外,文章还展示了如何配置这些策略,并提醒读者`CosId`在5.2.0版本可能不可用。最后,文章讨论了如何自定义分布式主键生成算法,并强调选择策略时要考虑全局唯一性、性能和易用性。
110 1
|
2月前
|
缓存 算法 关系型数据库
深度思考:雪花算法snowflake分布式id生成原理详解
雪花算法snowflake是一种优秀的分布式ID生成方案,其优点突出:它能生成全局唯一且递增的ID,确保了数据的一致性和准确性;同时,该算法灵活性强,可自定义各部分bit位,满足不同业务场景的需求;此外,雪花算法生成ID的速度快,效率高,能有效应对高并发场景,是分布式系统中不可或缺的组件。
108 2
深度思考:雪花算法snowflake分布式id生成原理详解
|
2月前
|
存储 Java 应用服务中间件
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
【分布式技术专题】「架构实践于案例分析」盘点互联网应用服务中常用分布式事务(刚性事务和柔性事务)的原理和方案
61 0