集群下必须要有全局唯一ID
要求:
全局唯一
趋势递增
在MySQL的InnoDB引擎中使用的是聚集索引,由于多数RDBMS使用Btree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能
单调递增
保证下一个ID一定大于上一个ID,例如事务版本号,IM增量消息、排序等特殊需求
信息安全
如果ID是连续的,就容易被恶意爬取或者让 竞争对手知道公司一天的单量。所以在一些应用场景下,需要ID无规则不规则,不让对方猜到规律
含时间戳
ID号生成系统的可用性要求:高可用、低延迟、高 QPS
一般通用方案 :UUID、数据库自增主键、基于Redis生成全局id策略
UUID:性能高,本地生成,没有网络消耗,如果只考虑唯一,满足 。
缺点:但是入数据库性能差
为什么UUID入数据库性能差
1。无序,无法预测他的生成顺序,不能生产递增有序的数字
首先分布式id一般都会作为主键 ,但是MySQL官方推荐主键要尽量越短越好,UUID每一个都很长,所以不是很推荐。
2。主键,ID作为主键时在特定的环境会存在一些问题。
比如做DB主键的场景下,UUID就非常不适用。MySQL官方推荐主键要尽量越短越好
3。索引,B+树索引的分裂
既然分布式ID是主键,然后主键是包含索引的,然后MySQL的索引是通过B+树来实现的,每一次新的UUID数据的插入,为了查询的优化,都会对索引底层的B+树进行修改,因为UUID是无序的,所以每一次UUID数据的插入都会对主键的B+树进行很大的修改,这一点很不好。插入完全无序,不但会导致一些中间节点产生分裂,也会白白创造出很多不饱和的节点,这样大大降低了数据库的插入的性能。
用数据库自增长,在单机下不能并发,分布式下不太好做,要做不同的增长步长 。
基于Redis生成全局id策略。redis投入太大
所以要考虑雪花算法
优点
- 每秒生成26万个自增可排序的ID
- 生成的ID能够按照时间有序生成
- 雪花算法生成id的结果是一个64bit大小的证书,为一个Long型(转换成字符串后长度最多19)
- 分布式系统内不会产生ID碰撞。(由datacenter和workderid作区分)并且效率较高
优点:
毫秒数在高位,自增序列在低位,整个ID都是趋势递增
不依赖数据库等第三方库,以服务的方式部署,稳定性高,生成ID的性能也高
可以依据自身业务特性分配bit位,非常灵活
缺点:
依赖机器时钟,如果机器时间回拨,会导致重复ID生成。
再单机 上是递增的,但涉及到分布式,每台 机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况
(此缺点可以认为无所谓,一般分布式ID只要求趋势递增 ,并不会严格要求递增,90%的需求都只要求趋势递增)