【架构演进】从 MySQL 迁移到 OceanBase,如何处理自增主键(Auto Increment)在分布式下的性能瓶颈?

公司计划将核心交易库从 MySQL 迁移到 OceanBase。目前 MySQL 表中大量使用了 BIGINT AUTO_INCREMENT 作为主键。

我知道 OceanBase 是分布式架构,如果继续用传统的自增主键,会不会导致所有插入请求都路由到同一个 Partition Leader 上,从而产生写热点?我看文档提到了“分组自增”和“序列(Sequence)”,但对于存量代码改造量太大。

请问在 OB 4.0 版本中,有没有既能保留 AUTO_INCREMENT 语法,又能避免写热点的最佳实践?是否需要强制要求业务方改用雪花算法(Snowflake)?

2 个赞

等一个答案

2 个赞

@论坛小助手

1 个赞

在从 MySQL 迁移到 OceanBase 时,确实需要考虑自增主键(AUTO_INCREMENT)在分布式环境下可能引起的性能瓶颈。以下是针对您的问题的建议:

  1. 使用序列(Sequence)

    • 序列(Sequence)是 OceanBase 提供的一种扩展功能,不与表绑定,可以独立创建,也可以跨表使用。序列支持循环(CYCLE)能力,这在某些业务场景中是非常有用的。
    • 对于现有代码改造,可以将原有的自增主键(AUTO_INCREMENT)改为使用序列。虽然需要一些代码改动,但可以通过批量脚本或工具来自动化这一过程,减少工作量。
    • 相关文档片段:
      • doc_id: 571
      • doc_id: 573
      • doc_id: 574
  2. 使用 NOORDER 模式的自增列

    • OceanBase 支持两种自增模式:ORDERNOORDERORDER 模式保证自增列的值全局递增,而 NOORDER 模式仅保证值的全局唯一,不保证全局递增。
    • 使用 NOORDER 模式可以避免写热点问题,因为每个 OBServer 节点可以独立生成自增值,而不需要每次都向 Leader 节点申请。
    • 相关文档片段:
      • doc_id: 573
      • doc_id: 574
  3. 使用 BIGINT 或 BIGINT UNSIGNED 类型

    • 为了防止自增列值耗尽,建议使用 BIGINTBIGINT UNSIGNED 类型,因为这些类型可以容纳更大的值范围。
    • 相关文档片段:
      • doc_id: 19395
  4. 关于雪花算法(Snowflake)

    • 雪花算法是一种分布式 ID 生成算法,适用于需要高性能和低延迟的场景。如果您现有的业务逻辑允许,可以考虑使用雪花算法替代自增主键。
    • 但是,这需要业务方进行较大的代码改造,可能会增加迁移的复杂性和风险。
    • 相关文档片段:无

综上所述,建议您优先考虑使用 NOORDER 模式的自增列,因为它既保留了 AUTO_INCREMENT 的语法,又避免了写热点问题。如果业务方愿意进行更多的代码改造,可以考虑使用序列或雪花算法。

详情请参考:

  1. OceanBase 数据库在 MySQL 模式租户下的扩展功能
  2. Schema 规范

会不会「所有插入都打到同一个 Partition Leader」?

不一定,主要取决于表是不是分区、分区键怎么选。

  • 未做分区的表:在 OceanBase 里通常对应少量 tablet/分区(常见就是整块数据在一个逻辑分区上),高并发插入时,数据写入很容易集中在该分区 Leader 上,这和「单调递增主键总是往 B+ 树一侧长」是同一类现象,只是从单机变成了「单分区 Leader」。
  • 做了分区且分区键能打散写入(例如按 HASH(业务键)KEY 分区等,而不是按单调递增的 idRANGE 且总是插最大端):不同主键值会落到不同分区,数据面的 Leader 可以分散。此时不是「所有写都到一个分区 Leader」。
  • 注意:若主键是 BIGINT AUTO_INCREMENT,只有在你用主键(或包含它的方式)参与分区且能打散时,数据写才会跟着散;若分区键与插入模式无关或表未分区,热点仍可能存在。
2 个赞

学习了。

2 个赞

一起等

1 个赞

赞赞

1 个赞