2021-06-01

十、分布式数据库之自增主键

 

1、自增主键的理想特征

 

  • 首先是唯一性,这是必须保证的,否则还能叫主键吗?
  • 其次是单调递增,也就是后插入记录的自增主键值一定比先插入记录要大。
  • 最后就是连续递增,自增主键每次加 1。有些应用系统甚至会基于自增主键的“连续递增”特性来设计业务逻辑。

 

但很多情况下,这些特性无法同时满足。

 

2、单体数据库的自增主键

 

只能真正的满足唯一性的约束,单调和连续性无法得到满足。

 

2.1、无法连续递增

 

在多数情况下,自增主键确实表现为连续递增。但是当事务发生冲突时,主键就会跳跃,留下空洞。

 

如下图,ID表示主键,两个事物T1和T2,T1回滚后,其对应的ID就被跳过了

 

 

为什么不支持连续递增呢?这是因为自增字段所依赖的计数器并不是和事务绑定的。如果要做到连续递增,就要保证计数器提供的每个主键都被使用。

 

怎么确保每个主键都被使用呢?那就要等待使用主键的事务都提交成功。这意味着,必须前一个事务提交后,计数器才能为后一个事务提供新的主键,这个计数器就变成了一个表级锁。

 

2.2、无法单调递增

 

对于单体数据库自身来说,自增主键确实是单调递增的。但使用自增主键也是有前提的,那就是主键生成的速度要能够满足应用系统的并发需求。而在高并发量场景下,每个事务都要去申请主键,数据库如果无法及时处理,自增主键就会成为瓶颈。那么,这时只用自增主键已经不能解决问题了,往往还要在应用系统上做些优化。

 

比如,对于 Oracle 数据库,常见的优化方式就是由 Sequence 负责生成主键的高位,由应用服务器负责生成低位数字,拼接起来形成完整的主键。

 

这个方案虽然使用了 Sequence,但也只能保证全局唯一,数据表中最终保存的主键不再是单调递增的了

 

3、分布式数据库下自增主键的问题

 

具体来说是两个问题,一是在自增主键的产生环节,二是在自增主键的使用环节。

 

首先,产生自增主键难点就在单调递增。单调递增这个要求和全局时钟中的 TSO 是很相似的。你现在已经知道,TSO 实现起来比较复杂,也容易成为系统的瓶颈,如果再用作主键的发生器,显然不大合适。

 

其次,使用单调递增的主键,也会给分布式数据库的写入带来问题。这个问题是在 Range 分片下发生的,我们通常将这个问题称为 “尾部热点”。

 

3.1、尾部热点

 

在使用Range 分片的情况下,测试程序的生成主键是单调递增的,所以新写入的数据往往集中在一个 Range 范围内,而 Range 又是数据调度的最小单位,只能存在于单节点,那么这时集群就退化成单机的写入性能,不能充分利用分布式读写的扩展优势了。当所有写操作都集中在集群的一个节点时,就出现了我们常说的数据访问热点(Hotspot)。

 

性能问题的根因已经找到了,就是同时使用自增主键和 Range 分片。主流产品的默认方案是保持 Range 分片,放弃自增主键,转而用随机主键来代替。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值