
系列导读
上一篇的中间件方案适合复用现有Redis/ZooKeeper的场景,但如果你的系统已经部署了分布式数据库(如TiDB、OceanBase),就没必要再引入其他方案了------分布式数据库原生支持"全局自增ID",底层通过分布式协议(如Paxos、Raft)保证唯一性和有序性,无需额外开发,无缝集成业务。
本文详解TiDB和OceanBase的全局ID实现,帮你快速落地核心业务的分布式ID。
一、适用场景
- 已使用分布式数据库(TiDB、OceanBase、CockroachDB);
- 核心业务(金融交易、电商核心订单、支付流水);
- 需ID唯一有序、高可用、高吞吐;
- 不想额外开发分布式ID逻辑,追求"零成本集成";
- 代表业务:银行转账流水、电商核心订单、保险保单号。
二、核心原理:分布式数据库的全局序列机制
分布式数据库之所以能支持全局ID,是因为底层通过"全局序列服务"协调多节点的ID生成:
- 全局序列服务:分布式数据库内置独立的序列服务(如TiDB的PD集群、OceanBase的RootService),负责生成全局唯一的自增ID;
- 分布式协议保证:通过Paxos/Raft协议确保序列服务的高可用和数据一致性,避免ID重复;
- 本地缓存优化:数据库节点会预申请一段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方案)
- 优点:
- 零开发成本:数据库原生支持,无需额外编写代码或引入组件;
- 高可用:依赖分布式数据库的集群协议(Paxos/Raft),无单点故障;
- 高性能:支持号段缓存,QPS可达万级+;
- 有序性:支持有序ID,适配排序、分页需求。
- 缺点:
- 依赖分布式数据库:未使用分布式数据库的系统无法复用;
- 迁移成本高:切换数据库时需重新适配全局ID逻辑;
- 配置复杂:需熟悉分布式数据库的序列参数,优化性能。
实战Tips
- 选型优先:已使用TiDB/OceanBase的核心业务,优先用数据库内置全局ID,避免重复开发;
- 有序vs无序:需排序分页用AUTO_INCREMENT(TiDB)或GLOBAL_SEQUENCE(OceanBase),无需有序用AUTO_RANDOM(TiDB);
- 缓存优化:高并发场景增大号段缓存(TiDB步长、OceanBase CACHE),减少数据库节点与序列服务的通信;
- 监控告警:监控序列剩余缓存量,避免缓存耗尽导致性能下降。
下一篇预告
至此,分布式ID的7种核心方案已全部拆解完毕!最后一篇我们将做"终极总结"------整理全方案对比表,给出"低并发→中高并发→超高并发"的选型决策逻辑,附上生产环境避坑清单,帮你快速"按场景对号入座",不再为分布式ID选型发愁!
你在项目中用的哪种分布式数据库?评论区聊聊~