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,8,10…)。这是Flickr团队在2010年撰文介绍的