如何在 TiDB 上高效运行序列号生成服务

本文探讨TiDB中序列号服务的优化策略,介绍如何解决写入热点问题,提高唯一序列号生成效率。通过实例演示不同优化方案的效果。

TiDB 从 v4.0 版本开始正式支持序列功能,而除了序列之外还有多种序列号生成方案,这些方案在没有对 TiDB 优化的时候一般会产生写入热点问题。本文将介绍如何应对写入热点问题高效运行序列号服务。

为什么需要(唯一)序列号

主键是关系模型设计中的第二范式,参照第二范式,所有表都应具有主键。实际操作中,OLTP 系统中承载交易的关键表会通过设置主键来确保记录的唯一性。

主键应具有不可变性,而具有业务属性的字段都不具备这样的特性,即使如身份证号,也存在升位、过期、多次办理等业务场景,将身份证号作为主键而不得不进行修改时,就会对业务产生严重影响。因此选取主键的一个基本原则就是采用与业务不相关的字段作为代理键,唯一序列号即承载这样的功能。

常见的序列号生成方案

唯一序列号生成方案有很多种,有依赖数据库自身特性的序列和自增列,有开源的分布式唯一 ID 生成器,也有非常灵活的号段分配方案:

  1. 自增列:自增(auto_increment)是大多数兼容 MySQL 协议的 RDBMS 上列的一种属性,通过配置该属性来使数据库为该列的值自动赋值,用户不需要为该列赋值,该列的值随着表内记录增加会自动增长,并确保唯一性。在大多数场景中,自增列被作为无业务涵义的代理主键使用。自增列的局限性在于:自增列只能采用整型字段,所赋的值也只能为整型。假设业务所需要的序列号由字母、数字及其他字符拼接而成,用户是难以通过自增列来获取序列号中所需的数字自增值的。

  2. 序列(Sequence):序列是一种数据库对象,应用程序通过调用某个序列可以产生递增的序列值,应用程序可以灵活的使用这个序列值为一张表或多张表赋值,也可以使用序列值进行更复杂的加工,来实现文本和数字的组合,来赋予代理键以一定的跟踪和分类的意义。TiDB 从 v4.0 版本开始提供序列功能,详情请参考官方文档

  3. 号段分配方案:号段(segment)分配是从数据库一次获取一批 ID,将获取的 ID 看成一个范围,例如 (500,1000],这个范围称为一个号段或步进(step),应用一次申请一个号段,加载到内存中,然后应用生成 ID,当号段使用完后,再次申请一个新的号段, 这样以批量获取的方式来提高效率,实际使用过程中,可以通过调节获取号段大小控制数据库记录更新频度。号段分配方案需要通过应用代码来实现相关逻辑,具有很好的灵活性,例如可以引入时间因素,来实现序列号在时间上的递增,来避免重复;也可以灵活的通过文本和数字的组合来赋予代理键以一定的跟踪和分类的意义。但相应的带来了一定的额外开发工作量。详细构建方案请参考 tidb-in-action 文章

  4. 类 snowflake 分布式唯一 ID 生成器:这种方案是由 Twitter 提出的分布式 ID 生成方案,它通过划分命名空间来生成 ID,这种方案把 64-bit 划分为多段,切分后的段分别用以标识时间、机器号、序列号等。该方案不依赖于数据据库,稳定性高,ID 生成速度快,还可以根据自身业务配置 bit 位,非常灵活。该方案非常依赖发号机器的本地时钟,时钟回拨可能会导致发号重复,在使用中需要注意这一点。除了 Twitter snowflake 之外,类似的唯一 ID 生成器还有百度 uid-generator 和美团 Leaf 等。详细构建方案请参考 tidb-in-action 文章

图 1. Twitter snowflake 64 位 id 结构

序列号与 TiDB 写入热点

唯一序列号多被用于为表的主键字段赋值。

大部分单机 RDBMS 采用 B+ tree 数据结构,主键往往是用于组织数据的关键索引(此时表被称作索引组织表),同一数据页内的记录按主键顺序存放。因此单机 RDBMS 产品一般推荐写入连续的序列号,这样每次写入新的记录,都会顺序添加到当前 B+ tree 索引节点的后续位置,当前的数据页写满时,会自动开始新一页的写入。相反,过于随机的主键值,会导致新记录被写入到数据页的某个中间位置,造成数据的移动而带来了额外的开销。

虽然 TiDB 具有不同于单机 RDBMS 的数据结构,但顺序的主键值写入,在 TiDB 上也会产生类的效果:TiKV 上一个的 region 被写满,进而分裂出一个新的 region,后续的写入转由新的 reigon 来承载。但甲之蜜糖,乙之砒霜,单机 RDBMS 的最佳实践放到 TiDB 上,会使写入压力总是集中在一个 region 上,这样就构成了持续的写入热点,无法发挥出 TiDB 这种分布式数据库的并行写入能力,降低了业务写入瓶颈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值