【分布式利器:分布式ID】7、分布式数据库方案:TiDB/OceanBase全局ID实战

系列导读

上一篇的中间件方案适合复用现有Redis/ZooKeeper的场景,但如果你的系统已经部署了分布式数据库(如TiDB、OceanBase),就没必要再引入其他方案了------分布式数据库原生支持"全局自增ID",底层通过分布式协议(如Paxos、Raft)保证唯一性和有序性,无需额外开发,无缝集成业务。

本文详解TiDB和OceanBase的全局ID实现,帮你快速落地核心业务的分布式ID。

一、适用场景

  • 已使用分布式数据库(TiDB、OceanBase、CockroachDB);
  • 核心业务(金融交易、电商核心订单、支付流水);
  • 需ID唯一有序、高可用、高吞吐;
  • 不想额外开发分布式ID逻辑,追求"零成本集成";
  • 代表业务:银行转账流水、电商核心订单、保险保单号。

二、核心原理:分布式数据库的全局序列机制

分布式数据库之所以能支持全局ID,是因为底层通过"全局序列服务"协调多节点的ID生成:

  1. 全局序列服务:分布式数据库内置独立的序列服务(如TiDB的PD集群、OceanBase的RootService),负责生成全局唯一的自增ID;
  2. 分布式协议保证:通过Paxos/Raft协议确保序列服务的高可用和数据一致性,避免ID重复;
  3. 本地缓存优化:数据库节点会预申请一段ID号段缓存到本地,减少对全局序列服务的访问,提升性能。

简单说:分布式数据库的全局ID,本质是"号段模式的内置实现",你无需关心底层细节,直接用类似单机自增ID的方式使用即可。

三、方案1:TiDB全局ID(AUTO_RANDOM/AUTO_INCREMENT)

TiDB是PingCAP开源的分布式数据库,兼容MySQL协议,提供两种全局ID方案:AUTO_RANDOM(无序)和AUTO_INCREMENT(有序)。

1. 方案1.1:AUTO_RANDOM(无序,高性能)

  • 原理:生成64位无序ID,底层通过预分配号段实现,性能极高(QPS万级+);
  • 优点:无序性避免热点写入(如TiDB分表场景,ID无序分布到不同分片);
  • 缺点:ID无序,不支持排序和分页;
  • 适用场景:无需有序的业务(如用户ID、文件ID)。
实战SQL(创建表时指定AUTO_RANDOM)
sql 复制代码
-- 创建用户表,id字段用AUTO_RANDOM(全局唯一无序)
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_RANDOM(5) COMMENT '全局唯一用户ID(无序)',
  `username` varchar(32) NOT NULL COMMENT '用户名',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- 插入数据(无需指定id字段,TiDB自动生成)
INSERT INTO `user` (`username`) VALUES ('zhangsan'), ('lisi');

-- 查询结果(id为无序的64位整数)
SELECT * FROM `user`;
/*
id                  | username | create_time
--------------------|----------|---------------------
101580745387390977  | zhangsan | 2024-05-20 10:00:00
101580745387390978  | lisi     | 2024-05-20 10:01:00
*/

关键说明

  • AUTO_RANDOM(5):括号内的数字是"分片位"(0~20),用于控制ID在TiDB分表中的分布,默认5位;
  • 不支持更新ID字段,也不支持手动插入ID(需开启allow_auto_rand_insert参数)。

2. 方案1.2:AUTO_INCREMENT(有序,支持分页)

  • 原理:生成有序的全局自增ID,底层基于TiDB的PD集群(全局序列服务),支持预分配号段;
  • 优点:ID有序递增,支持排序和分页;
  • 缺点:高并发下可能出现热点分片(如ID递增集中在某一个分片);
  • 适用场景:需有序的核心业务(如订单ID、交易流水号)。
实战SQL(创建表时指定AUTO_INCREMENT)
sql 复制代码
-- 创建订单表,id字段用AUTO_INCREMENT(全局唯一有序)
CREATE TABLE `order` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '全局唯一订单ID(有序)',
  `user_id` bigint NOT NULL COMMENT '用户ID',
  `amount` decimal(10,2) NOT NULL COMMENT '订单金额',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

-- 插入数据(无需指定id字段,TiDB自动生成)
INSERT INTO `order` (`user_id`, `amount`) VALUES (1-- 补全TiDB订单表插入SQL
INSERT INTO `order` (`user_id`, `amount`) VALUES (101580745387390977, 99.90), (101580745387390978, 199.50);

-- 查询结果(id为全局有序递增)
SELECT * FROM `order`;
/*
id  | user_id             | amount  | create_time
-----|---------------------|---------|---------------------
1    | 101580745387390977  | 99.90   | 2024-05-20 10:05:00
2    | 101580745387390978  | 199.50  | 2024-05-20 10:06:00
*/

关键配置(优化有序ID性能)

TiDB的AUTO_INCREMENT默认由PD集群分配号段(默认步长=1000),可通过参数调整:

sql 复制代码
-- 修改TiDB全局参数,调整号段步长(适用于高并发场景)
SET GLOBAL tidb_auto_increment_step = 2000; -- 号段步长=2000
SET GLOBAL tidb_auto_increment_offset = 1; -- 起始偏移量=1

四、方案2:OceanBase全局ID(GLOBAL_SEQUENCE)

OceanBase是蚂蚁集团开源的分布式数据库,提供"全局序列(GLOBAL_SEQUENCE)"功能,支持自定义步长、起始值、缓存策略,灵活性更高。

1. 核心原理

  • 全局序列服务:OceanBase的RootService(根服务)负责生成全局唯一序列,通过Paxos协议保证高可用;
  • 缓存优化:数据库节点会预缓存一段序列(默认缓存1000个ID),减少网络开销;
  • 灵活配置:支持自定义起始值、步长、缓存大小,适配不同业务场景。

2. 实战用法(3种方式)

2.1 方式1:创建独立全局序列,手动调用

适用于需要手动控制ID生成的场景(如批量生成ID):

sql 复制代码
-- 1. 创建全局序列(订单ID序列)
CREATE GLOBAL SEQUENCE order_seq
START WITH 10000001 -- 起始值
INCREMENT BY 1 -- 步长
CACHE 2000 -- 节点缓存2000个ID
CYCLE OFF; -- 不循环(到达最大值后报错)

-- 2. 调用序列生成ID
SELECT nextval('order_seq'); -- 生成下一个ID(10000001)
SELECT currval('order_seq'); -- 获取当前ID(10000001)

-- 3. 插入订单表时使用
INSERT INTO `order` (`id`, `user_id`, `amount`)
VALUES (nextval('order_seq'), 101580745387390977, 299.00);
2.2 方式2:序列作为字段默认值(推荐)

插入数据时无需手动调用,字段自动获取序列值:

sql 复制代码
-- 创建订单表,id字段默认使用全局序列
CREATE TABLE `order` (
  `id` bigint NOT NULL DEFAULT nextval('order_seq') COMMENT '全局唯一订单ID(有序)',
  `user_id` bigint NOT NULL COMMENT '用户ID',
  `amount` decimal(10,2) NOT NULL COMMENT '订单金额',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

-- 插入数据(无需指定id字段)
INSERT INTO `order` (`user_id`, `amount`)
VALUES (101580745387390978, 399.90);

-- 查询结果(id自动从序列获取,有序递增)
SELECT * FROM `order`;
/*
id        | user_id             | amount  | create_time
-----------|---------------------|---------|---------------------
10000002   | 101580745387390978  | 399.90  | 2024-05-20 10:10:00
*/
2.3 方式3:创建表时内置序列(简化操作)

无需单独创建序列,直接在表字段中定义:

sql 复制代码
CREATE TABLE `pay_flow` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '支付流水ID',
  `order_id` bigint NOT NULL COMMENT '订单ID',
  `pay_amount` decimal(10,2) NOT NULL COMMENT '支付金额',
  `pay_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_id` (`order_id`)
) ENGINE=InnoDB 
DEFAULT CHARSET=utf8mb4 
COMMENT='支付流水表'
-- 内置全局序列配置
AUTO_INCREMENT = 20000001 -- 起始值
AUTO_INCREMENT_CACHE = 1500 -- 缓存大小
AUTO_INCREMENT_INCREMENT = 1; -- 步长

五、TiDB vs OceanBase全局ID方案对比

特性 TiDB全局ID(AUTO_RANDOM/AUTO_INCREMENT) OceanBase全局ID(GLOBAL_SEQUENCE)
有序性 AUTO_RANDOM无序,AUTO_INCREMENT有序 支持有序(默认),可配置无序
灵活性 配置项较少(步长、分片位) 高(自定义起始值、步长、缓存大小)
性能 高(QPS万级+) 高(QPS万级+,缓存可优化)
易用性 高(兼容MySQL语法,无需额外学习) 中(需学习序列创建语法)
热点优化 AUTO_RANDOM支持分片均匀分布 支持序列分片,避免热点
适用场景 电商订单、用户ID、中小型核心业务 金融交易、保险保单、大型核心业务

六、避坑指南:分布式数据库全局ID关键问题

1. TiDB避坑

  • 坑1:AUTO_INCREMENT导致热点分片(高并发下ID集中在一个分片);
    解决方案:
    • 高并发场景用AUTO_RANDOM(无序分布);
    • 调整tidb_auto_increment_step(步长=分片数),让ID均匀分布到多个分片。
  • 坑2:TiDB主从切换导致ID重复;
    解决方案:TiDB的AUTO_INCREMENT由PD集群统一分配,主从切换不影响ID唯一性,无需额外处理。

2. OceanBase避坑

  • 坑1:序列缓存过大导致ID断层;
    解决方案:
    • 缓存大小(CACHE)根据业务并发调整(低并发=100,高并发=2000);
    • 重要业务(如金融)设置CACHE 1(无缓存,每次从RootService获取,避免断层)。
  • 坑2:序列循环导致ID重复;
    解决方案:创建序列时指定CYCLE OFF(默认),避免ID循环复用。

七、优点&缺点(分布式数据库全局ID方案)

  • 优点:
    1. 零开发成本:数据库原生支持,无需额外编写代码或引入组件;
    2. 高可用:依赖分布式数据库的集群协议(Paxos/Raft),无单点故障;
    3. 高性能:支持号段缓存,QPS可达万级+;
    4. 有序性:支持有序ID,适配排序、分页需求。
  • 缺点:
    1. 依赖分布式数据库:未使用分布式数据库的系统无法复用;
    2. 迁移成本高:切换数据库时需重新适配全局ID逻辑;
    3. 配置复杂:需熟悉分布式数据库的序列参数,优化性能。

实战Tips

  1. 选型优先:已使用TiDB/OceanBase的核心业务,优先用数据库内置全局ID,避免重复开发;
  2. 有序vs无序:需排序分页用AUTO_INCREMENT(TiDB)或GLOBAL_SEQUENCE(OceanBase),无需有序用AUTO_RANDOM(TiDB);
  3. 缓存优化:高并发场景增大号段缓存(TiDB步长、OceanBase CACHE),减少数据库节点与序列服务的通信;
  4. 监控告警:监控序列剩余缓存量,避免缓存耗尽导致性能下降。

下一篇预告

至此,分布式ID的7种核心方案已全部拆解完毕!最后一篇我们将做"终极总结"------整理全方案对比表,给出"低并发→中高并发→超高并发"的选型决策逻辑,附上生产环境避坑清单,帮你快速"按场景对号入座",不再为分布式ID选型发愁!

你在项目中用的哪种分布式数据库?评论区聊聊~

相关推荐
倔强的石头_5 小时前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
jiayou641 天前
KingbaseES 实战:深度解析数据库对象访问权限管理
数据库
李广坤2 天前
MySQL 大表字段变更实践(改名 + 改类型 + 改长度)
数据库
初次攀爬者3 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
爱可生开源社区3 天前
2026 年,优秀的 DBA 需要具备哪些素质?
数据库·人工智能·dba
随逸1773 天前
《从零搭建NestJS项目》
数据库·typescript
加号34 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
シ風箏4 天前
MySQL【部署 04】Docker部署 MySQL8.0.32 版本(网盘镜像及启动命令分享)
数据库·mysql·docker
李慕婉学姐4 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
百锦再4 天前
Django实现接口token检测的实现方案
数据库·python·django·sqlite·flask·fastapi·pip