分布式ID
1. 为什么需要分布式ID
在单体结构的应用中,我们可以使用 MySQL 数据库的主键自增来为我们的数据设置唯一标识 ID,但是在分布式环境中,单个数据库的吞吐量成为整个应用的性能瓶颈,我们就可以搭建数据库集群来提升数据库的性能,此时如果还使用 MySQL 的主键自增来设置数据 ID 的话,就会出现重复的 ID,这样就会出现主键冲突的情况。
如果使用分布式的全局唯一 ID 就不用担心会出现这个问题了
2 分布式ID
一个好的分布式ID,一般要满足下列特性:
- 唯一性:保证全局唯一
- 高可用,可以由主从、集群等模式保证可用性
- 高性能,比如基于内存
- 递增性:适合作为数据库索引
- 安全性:id如果是顺序递增,则容易暴露业务信息
3 全局唯一ID生成策略
1. 数据库自增ID
利用数据库的自增主键特性,每次插入记录时,数据库会自动生成一个唯一的ID。
优点:
- 简单易用,直接使用数据库提供的功能。
- 保证唯一性。
缺点:
- 存在单点故障,数据库成为瓶颈。
- 考虑数据量大时,可能需要分库分表.
2. UUID(Universally Unique Identifier)
UUID 是一种标准的唯一标识符,通常为128位长,可以保证全局唯一性。在 Java 中可以使用 java.util.UUID 的 randomUUID() 方法来获得:
1 |
|
优点:
- 生成简单,不依赖中心化服务。
- 唯一性强。
缺点:
- 较长,占用空间大,不适合作为数据库索引。
- 无序,无法实现范围查询
- 插入时需要维护B+树,而B+树是有序的,因此插入操作的性能比自增ID要差,有些博客测评插入性能要差4倍
建议用自增ID作为主键,业务上采取UUID作为唯一标识
3. Twitter的Snowflake算法
Snowflake 是 Twitter 开源的分布式ID生成算法,通过组合时间戳、机器ID和序列号生成ID。
ID结构:
- 1位符号位:始终为0。
- 41位时间戳:毫秒级时间戳,可使用69年。
- 10位机器ID:支持1024台机器。
- 12位序列号:每毫秒支持生成4096个ID。
优点:
- 高性能,低延迟。
- 时间有序生成,适合数据库索引。
缺点:
- 依赖机器时间,时钟回拨可能导致ID重复或冲突。
时钟回拨问题,在一些Snowflake的变种已经解决掉了,如百度的uid-generator
4. 使用Redis生成ID
利用Redis的原子性递增操作,生成分布式唯一ID。使用 Redis 的 Incr 命令来把 <key,value> 中 key 的数值加 1 并返回,如果这个 key 不存在,则 key 值会被初始化为 0,再执行 Incr 命令来进行加 1 操作
1 |
|
优点:
- 简单,利用Redis的原子操作保证唯一性。
- 性能高,Redis操作速度快。
缺点:
- 依赖Redis服务,可能成为瓶颈。
- 需要处理Redis的持久化和高可用性。
分布式ID
http://example.com/分布式ID/