前言
对于主键生成,相信接触过数据库的童鞋都不会陌生。可能对于大部分童鞋来说,主键的生成还停留在自增长上面。那么,你知道它的优缺点吗~
实现方式
自增长
MySQL的自增长对于早期的系统来说基本不会有任何问题,但随着数据量的爆炸上升以及分布式系统的必要性,自增长早已无法满足目前的需求。
优点
- 依赖于数据库层面,减少了服务层代码量。
缺点
- 对于
int
型自增,在第一位是符号数的情况下,长度为2^31 - 1
,大概是40多亿。当然一般到达这个程度的单表,已经做了分表的操作了。 - 表合并:在某些需求下,可能会对分布式系统的多张表进行合并,这时候主键会有一定概率重复,这时候需要按照业务对主键进行修改。其实这就是没有满足主键的唯一性。
- 对于数据被攻击后,由于主键自增的特性,可能会泄漏某些信息。
Redis Incr
将Redis作为一个中心化主键生成器。由于Redis IO多路复用的模型,以及单线程的原子性操作,可以在保证速度的前提下,做到主键的唯一性。同时redis的长度为64位的有符号数,不太可能单表有数据会到达这个量级。
优点
- 唯一性。
- 顺序性。
缺点
- 一旦Redis宕机,数据库的所有写入操作会失效。因此需要维护Redis节点,同时需要确保高可用性。
- 上述的第三点。
UUID
UUID的方式可能是用的较多的(不确定哈~~),这种生成方式的优点显而易见,可以确保生成的主键是唯一的。
优点
- 唯一性
缺点
- UUID的长度较长,占用的空间相对于Int较大,
- 为了确保数据的查询速度,主键索引采用的都是树的数据结构,如B树,B+树 。在这种情况下,UUID生成的主键无法保证顺序性,每次生成的主键可能会导致主键索引的节点变化较大。(参考平衡二叉树)
雪花算法
通过上述的几个例子,想必大家都发现了主键生成的几个必要条件。
- 唯一性。
- 有序字段
- 长度没有限制。
优点
Twitter的雪花算法,同时确保了这三点。
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
第一部分 为符号位 0或1
第二部分 41位时间戳差值,一定程度上确保了有序,当然这个41还能用69年。。。
第三部分 十位的标识部分,这边可以按照业务以及节点标识划分。
第四部分 12位序列号部分,支持同一毫秒内同一个节点可以生成4096个ID;
复制代码
通过上面的四个部分,已经满足了上述三个条件
缺点
- 需要自己实现生成方式,同时要保证生成效率。
结尾
对于这篇文章,也是笔者在面试被问到的问题。同时对于雪花算法也是面试结束后,才了解到的,参考 链接:猛戳我。
希望这篇文章能对大家有所帮助~~