1、为什么需要分布式 ID?
对于单体系统来说,主键 ID 可能会常用主键自动的方式进行设置,这种 ID 生成方法在单体项目是可行的,但是对于分布式系统,分库分表之后,就不适应了,比如订单表数据量太大了,分成了多个库,如果还采用数据库主键自增的方式,就会出现在不同库 id 一致的情况,虽然是不符合业务的
2、业务系统对分布式 ID 有什么要求?
-
全局唯一性:ID 是作为唯一的标识,不能出现重复
-
趋势递增:互联网比较喜欢 MySQL 数据库,而 MySQL 数据库默认使用 InnoDB 存储引擎,其使用的是聚集索引,使用有序的主键 ID 有利于保证写入的效率
-
单调递增:保证下一个 ID 大于上一个 ID,这种情况可以保证事务版本号,排序等特殊需求实现
-
信息安全:前面说了 ID 要递增,但是最好不要连续,如果 ID 是连续的,容易被恶意爬取数据,指定一系列连续的,所以 ID 递增但是不规则是最好的
3、分布式 ID 生成方案
-
UUID
-
数据库自增
-
号段模式
-
Redis 实现
-
雪花算法(SnowFlake)
-
百度 Uidgenerator
-
美团 Leaf
-
滴滴 TinyID
3.1 UUID
UUID (Universally Unique Identifier),通用唯一识别码的缩写。UUID 的标准型式包含 32 个 16 进制数字,以连字号分为五段,形式为 8-4-4-4-12 的 36 个字符,示例: 863e254b-ae34-4371-87da-204b71d46a7b。UUID 理论上的总数为 1632=2128,约等于 3.4 x 10^38。
-
优点性能非常高,本地生成的,不依赖于网络
-
缺点不易存储,16 字节 128 位,36 位长度的字符串信息不安全,基于 MAC 地址生成 UUID 的算法可能会造成 MAC 地址泄露,暴露使用者的位置 uuid 的无序性可能会引起数据位置频繁变动,影响性能
3.2、数据库自增
在分布式环境也可以使用 mysql 的自增实现分布式 ID 的生成,如果分库分表了,当然不是简单的设置好 auto_increment_increment 和 auto_increment_offset 即可,在分布式系统中我们可以多部署几台机器,每台机器设置不同的初始值,且步长和机器数相等。比如有两台机器。设置步长 step 为 2,Server1 的初始值为 1(1,3,5,7,9,11…)、Server2 的初始值为 2(2,4,6