【分布式】分布式 ID
一、什么是分布式ID?二、为什么需要分布式ID?三、如何生成分布式ID?
目录
一、什么是分布式ID?
日常开发中,我们需要对系统中的各种数据使用 ID 唯一表示,比如用户 ID 对应且仅对应一个人,商品 ID 对应且仅对应一件商品,订单ID对应且仅对应一个订单。
我们现实生活中也有各种 ID,比如身份证 ID 对应且仅对应一个人、地址 ID 对应且仅对应
简单来说,ID 就是数据的唯一标识。
分布式 ID 是分布式系统下的 ID。
二、为什么需要分布式ID?
随着系统的数据量越来越大,单机MySQL已经没办法支撑了,需要进行分库分表。
对数据库分库分表之后, 数据遍布在不同服务器上的数据库,数据库的自增主键已经没办法满足生成的主键唯一了,此时我们就需要生成分布式 ID了。
三、如何生成分布式ID?
1. 要求
一个最基本的分布式 ID 需要满足下面这些要求:
- 全局唯一 :ID 的全局唯一性肯定是首先要满足的!
- 高性能 : 分布式 ID 的生成速度要快,对本地资源消耗要小。
- 高可用 :生成分布式 ID 的服务要保证可用性无限接近于 100%。
- 方便易用 :拿来即用,使用方便,快速接入!
除了这些之外,一个比较好的分布式 ID 还应保证:
- 安全 :ID 中不包含敏感信息。
- 有序递增 :如果要把 ID 存放在数据库的话,ID 的有序性可以提升数据库写入速度。并且,很多时候 ,我们还很有可能会直接通过 ID 来进行排序。
- 有具体的业务含义 :生成的 ID 如果能有具体的业务含义,可以让定位问题以及开发更透明化(通过 ID 就能确定是哪个业务)。
- 独立部署 :也就是分布式系统单独有一个发号器服务,专门用来生成分布式 ID。这样就生成 ID 的服务可以和业务相关的服务解耦。不过,这样同样带来了网络调用消耗增加的问题。总的来说,如果需要用到分布式 ID 的场景比较多的话,独立部署的发号器服务还是很有必要的。
2. 解决方案
2.1 基于数据库
(1)数据库主键自增
通过关系型数据库的自增主键产生来唯一的 ID。
(2)数据库号段模式
批量获取,存在内存里,用的时候直接从内存里获取。
解决了数据库主键自增方案每次获取 ID 都要访问一次数据库的问题。
(3)Redis自增
通过 Redis 的 incr 命令即可实现对 id 原子顺序递增。
2.2 基于算法
(1)UUID
包含 32 个 16 进制数字(8-4-4-4-12),其生成规则包括 MAC 地址、时间戳、名字空间(Namespace)、随机或伪随机数、时序等元素。
(2)Snowflake
生成一个long类型的ID,一个long大小8字节,一个字节8个比特位,因此它使用64个比特位来确定一个分布式ID。其中1bit为标识位,41bit代表时间戳,10bit标识一台机器,12bit则用来标识每个id。
| 分类 | 方案 | 优点 | 缺点 |
| 数据库 | 数据库主键自增 |
1)实现起来比较简单 2)ID 有序递增 3)存储消耗空间小 |
1)支持的并发量不大 2)存在数据库单点问题(可以使用数据库集群解决,不过增加了复杂度) 3)ID 没有具体业务含义 4)安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量 ) 5)每次获取 ID 都要访问一次数据库(增加了对数据库的压力,获取速度也慢) |
|
数据库号段模式 |
1)ID 有序递增 2)存储消耗空间小 |
1)存在数据库单点问题(可以使用数据库集群解决,不过增加了复杂度) 2)ID 没有具体业务含义 3)安全问题(比如根据订单 ID 的递增规律就能推算出每天的订单量) |
|
| Redis自增 | 1)性能不错并且生成的 ID 是有序递增的 | 1)和数据库主键自增方案的缺点类似 | |
| 算法 |
UUID |
1)生成速度比较快 2)简单易用 |
1)存储消耗空间大(32 个字符串,128 位) 2)不安全(基于 MAC 地址生成 UUID 的算法会造成 MAC 地址泄露) 3)无序(非自增) 4)没有具体业务含义 5)需要解决重复 ID 问题(当机器时间不对的情况下,可能导致会产生重复 ID) |
|
Snowflake |
1)生成速度比较快 2)生成的 ID 有序递增 3)比较灵活(可以对 Snowflake 算法进行简单的改造比如加入业务 ID) |
1)需要解决重复 ID 问题(依赖时间,当机器时间不对的情况下,可能导致会产生重复 ID) |
3. 开源框架
3.1 UidGenerator(百度)
基于 Snowflake 的唯一 ID 生成器,并对其进行了改进。其中1bit为标识位,28bit代表时间戳,22bit标识一台机器,13bit则用来标识每个id。
详见:UidGenerator
3.2 Leaf(美团)
提供了 号段模式 和 Snowflake 这两种模式来生成分布式 ID。
Leaf 对原有的号段模式进行改进,比如它这里增加了双号段避免获取 DB 在获取号段的时候阻塞请求获取 ID 的线程。简单来说,就是我一个号段还没用完之前,我自己就主动提前去获取下一个号段。
3.3 Tinyid(滴滴)
基于数据库号段模式的唯一 ID 生成器。
相比于基于数据库号段模式的简单架构方案,Tinyid 方案主要做了下面这些优化:
- 双号段缓存 :为了避免在获取新号段的情况下,程序获取唯一 ID 的速度比较慢。 Tinyid 中的号段在用到一定程度的时候,就会去异步加载下一个号段,保证内存中始终有可用号段。
- 增加多 db 支持 :支持多个 DB,并且,每个 DB 都能生成唯一 ID,提高了可用性。
- 增加 tinyid-client :纯本地操作,无 HTTP 请求消耗,性能和可用性都有很大提升。
详见:Tinyid原理介绍
更多推荐

所有评论(0)