1、为什么要全局分布式ID
- 在复杂的分布式系统中,需要对大量的数据和消息进行唯一标识,
- 对数据分库分表后需要有一个唯一ID来标识一条数据或消息,方便未来能够分库分表
2、ID生成规则部分硬性要求
2.1、全局唯一
不能出现重复的ID号
2.2、趋势递增
在Mysql的InnoDb引擎中使用的是聚集索引,有序的主键能保证写入性能。
2.3、单调递增
保证下一个ID一定大于上一个ID
2.4、信息安全:
如果ID是连续的,恶意用户的扒取工作就很容易了,直接按顺序下载指定的URL就行,如果订单号就更危险了,竞争对手可以直接知道我们一天的单量。所以在一些应用场景下,需要ID无规则,让竞争对手不好猜。
2.5、含时间戳
让我们知道这个ID在什么时候生成的。
3、ID生成系统的可用性要求
3.1、高可用
发一个获取分布式ID的请求同,服务器要保证100%的情况下给我们创建一个唯一的分布式ID
3.2、低延时
毫秒级的生成,如,一毫秒生成4096个
3.3、高QPS(Queries-per-second每秒查询率)
4、通用的解决方案
4.1、自增ID:auto_increment
使用数据库的自动增长(auto_increment),是比较简单和常见的ID生成方案,数据库内部可以确保生成id的唯一性。
优点:
- 数据库自动编号,速度快,而且是增量增长,聚集型主键按顺序存放,对于检索非常有利。
- 数字型,占用空间小,易排序,在程序中传递方便。
缺点
- 不支持水平分片架构,不能保证全局唯一,有主键冲突风险。
- 对数据库有依赖,每种数据库可能实现不一样,数据库切换时候,涉及到代码的修改,不利于
4.2、数据库自增主键:replace into
replace into 作用
replace into首先尝试插入数据列表中,如果发现表中已有的此行数据(根据主键或唯一索引判断),则先删除,再插入。否则直接插入新数据。
REPLACE INTO 的含义是插入一行记录,如查表中唯一索引的值遇到冲突,则替换老数据。
CREATE TABLE t_test(
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
stub CHAR(1) NOT NULL DEFAULT '',
UNIQUE KEY stub (stub)
);
REPLACE INTO t_test(stub) values('x');
步骤1:创建一个表 u,id 自增长
CREATE TABLE u(
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
stub CHAR(1) NOT NULL DEFAULT '',
UNIQUE KEY stub (stub)
);
步骤2:所有插入操作的主键id,都通过对u表插入操作来获取。
//如果x冲突,x对应数据删除,新增一个(x,id+1)的数据
REPLACE INTO t_test(stub) values('x');
//获取当前客户端插入的主键id,也就是刚刚的id+1
SELECT LAST_INSERT_ID();
步骤3:建立统一的主键生成表(路由表)
- 通过一个统一的表(所有系统共享),给所有的业务表分配主键id
- 当如果业务压力很大,每秒都要大量的插入,可以设置N个类似u的表,主键跨步也要设置为N,这样是防止不同的u表生产的id冲突。
缺点
单机性能不够,数据库横向扩展非常麻烦
4.4、UUID
UUID(Universally Unique Identifier)的标准形式包含32个16进制的数字,以连字号分为5段,形式为8-4-4-4-12个字符,
如:941e3b9a-a6a8-43fd-8b74-d0627f12323f
优点
性能非常高:本地生成,没有网络消耗
缺点
- 不易于存储
- UUID太长,16字节128位,通常以36长度的字符串表示,很多场景不适用。
- 信息不安全
- 基于MAC地址生成UUID的算法可能会造成MAC地址泄露
- 这个漏洞曾被用于寻找梅丽莎病毒的制作者位置。
- UUID是无序的,InnoDb引擎中使用的是聚集索引,无序的主键能会损失写入性能。
- MySQL官方有明确的建议主键要尽量越短越好,36个字符长度的UUID不符合要求。
- 对MySQL索引不利
- 作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。
4.5、基于Redis生成全局主键
因为Redis是单线程原子操作可以使用incr和incrby来实现
优点
并发能力起来了,有点NB了
缺点:
- 代价太大
- redis集群扩容会出现ID不连续的问题(步长不好设置)
4.6、基于zookeeper生成全局主键
原理,使用数据的版本号
缺点
代价太大
4.7、利用hash
- 不同业务的表主键使用自增长,主键的跨步为N(N为数据库集群数量)
4.8、Snowflake(雪花算法,现在非常流行)
https://blog.csdn.net/zhou920786312/article/details/122201559