各种ID生成策略对比

news/2024/11/27 2:11:38/

1. id⾃增的劣势

问题:当数据量庞⼤时,在数据库分库分表后,数据库⾃增id不能满⾜唯⼀id来标识数据;因为每个表都按⾃⼰节奏⾃增,会造成id冲突,⽆法满⾜需求。
所以分布式id就有了一定规则
- 全局唯一:不能重复
- 递增性:MySql的InnoDB 使用的是聚簇索引,由于多数索引我们都是使用的B-tree的数据结构建立的索引,因此在主键上应该尽量选项有序的主键保证读写性能,保证下一个id大于上一个id。
- 安全性:既要保证安全又要有时间戳保证顺序性。
- 高性能高可用性:高并发情况下保证良好的生成id。

2. 分布式Id的实现方案有哪些呢?

2.1 数据库表
我们可以在某个数据库中专门地去维护一张数据表,然后每次无论是哪张数据表需要自增 id,都需要去查这张表的记录,然后再利用 for update 锁表,并将取到的值加一,再把新值记录到数据表中。显然因为每次我们都需要锁表,所以这仅对于并发量小的项目而言是可以接受的
优点:简单粗暴
缺点:严重依赖数据库
2.2 redis
r因为 Redis 是单线程的,所以我们可以在 Redis 中维护一个键值对,之后无论是哪张数据表需要自增 id,都需要直接先去 Redis 中取值并加一。显然这种方式和上面单独维护一张数据表的方式是一样的,对高并发的支持都有所不足
优点:灵活、不依赖数据库
缺点:性能不太好
2.3 ⚠️UUID

我们可以使用 UUID 来作为不重复的主键 id,但是 UUID 是无序的字符串,所以主键索引就会失效
优点:简单、方便、性能好、全球唯一
缺点:无序性、存储的是字符串、查询效率低、传输数据量大
2.4 ⚠️雪花算法
雪花算法是 Twitter 推出的针对分布式环境下的 id 生成算法,其结果是一个 Long 型的 64bit id。具体实现上使用 41bit 作为毫秒数,10bit 作为机器的 id(5bit 是数据中心,5bit 是机器 id),12bit 作为毫秒内的流水号(这意味着每个节点在每毫秒内可以产生 4096 个 id),最后还有一个符号位永远是 0
优点:不依赖数据库、完全在内存中生成 id、高性能高可用、容量大、每秒可生成数百万个 id、id 递增、后续插入数据库的索引时性能较高
缺点:严重依赖系统时钟,如果某台机器的系统时钟发生回拨,就有可能会造成 id 冲突甚至 id 乱序

3.自增Id和UUID效率对比

自增 id
自增的主键由于是顺序的,所以 InnoDB 会把每一条记录都存储在前一条记录的后面,当达到页的最大填充因子时(InnoDB 默认的最大填充因子是页大小的 15/16,它会预留出 1/16 的空间用作以后的数据修改),下一条记录就会写入到新的页中。
一旦数据按照这种顺序的方式进行加载,那么主键页就会近乎于顺序地填满,这将大大提高页的最大填充率,从而不会造成页的浪费。

此外,新插入的行一定会在原有的最大数据行的下一行,这对 MySQL 的定位和寻址很有帮助,MySQL 不必为计算出新行的位置而做出额外的消耗,并且能减少页分裂以及碎片的产生。
UUID
因为 UUID 是无序的,所以新行的值并不一定会比之前的主键值大,所以 InnoDB 无法做到总是把新行插入到索引的最后,而是需要为新行寻找到合适的位置,从而来分配新的空间(这个过程会需要做很多额外的工作,数据的毫无顺序会导致数据分布散乱)。
同时,写入的目标页很可能已经刷新到磁盘上并且已经从缓存中移除,甚至可能是还没有被加载到缓存中,以至于 InnoDB 在插入前不得不先在磁盘中读取目标页到内存中(这将伴随着大量的随机 I/O)。
又因为写入是乱序的,InnoDB 不得不频繁地做页分裂的操作,以便为新行分配空间。页分裂会导致需要移动大量的数据,一次插入操作最少需要修改三个页以上,而频繁地页分裂会导致页变得稀疏并且被不规则地填充,最终造成数据碎片。


http://www.ppmy.cn/news/61875.html

相关文章

三角函数最小正周期

由于 2 π 是正弦函数 y sin ⁡ x , x ∈ R 的周期, 由于2\pi是正弦函数y\sin x,x\in R的周期, 由于2π是正弦函数ysinx,x∈R的周期, 下面只需证明任一小于 2 π 的正数都不是那个函数的周期。 下面只需证明任一小于2\pi的正数都不是那个函数…

USB2.0(一):基础

一、总线标准 USB1.1:支持12Mbps全速率(FullSpeed)和1.5Mbps低速率( HalfSpeed)USB2.0:支持480Mbps高速率(High Speed),兼容1.1USB3.0:支持5Gbps超高速率&am…

ScriptableObject上的prefab内容暂用,ScriptableObject详解

ScriptableObject是Unity引擎中的一种特殊类型,它允许你创建可扩展的、自定义的数据容器,用于在项目中存储和管理数据。它们非常适合存储那些不直接关联场景对象的数据,例如配置数据、游戏设置、AI行为树、技能和物品属性等。 ScriptableObj…

全方位揭秘!大数据从0到1的完美落地之运行流程和分片机制

一个完整的MapReduce程序在分布式运行时有三类实例进程: MRAppMaster: 负责整个程序的过程调度及状态协调MapTask: 负责Map阶段的整个数据处理流程ReduceTask: 负责Reduce阶段的整个数据处理流程 当一个作业提交后(mr程序启动),大概流程如下&#xff1…

家用洗地机哪款好?2023入门级智能洗地机

现代社会对卫生日益重视,尤其是在工业、商业和公共场所要求越来越高。传统清洁方式不能满足人们的需求,清洁工作效率低且卫生难以保证。而洗地机的出现,正是为了解决这些问题。它能够深入清洁地面,有效防止不必要的污垢、细菌和病…

【Linux】软件包管理器 yum和编辑器-vim的基本使用

文章目录 一、yum背景知识1.商业生态2.开源生态3.Linux软件生态本土化 二、yum的基本使用1.什么是软件包2.查看软件包3.安装软件4.卸载软件5.rzsz 三、vim的基本使用1.vim的基本概念2.vim的基本操作3.vim命令模式命令集4.vim末(底)行模式命令集5.操作总结 四、简单vim配置1.vim…

高级【IO】

目录 一.五种IO模型 (1)阻塞IO: (2)非阻塞IO (3)信号驱动IO: (4)IO多路转接 (5)异步IO 二.高级IO概念 1.同步通信、异步通信 2.阻塞、非阻…

Scala Option类型,异常处理,IO,高阶函数

Option类型 实际开发中, 在返回一些数据时, 难免会遇到空指针异常(NullPointerException), 遇到一次就处理一次相对来讲还是比较繁琐的. 在Scala中, 我们返回某些数据时,可以返回一个Option类型的对象来封装具体的数据,从而实现有效的避免空指针异常。S…