同步表

最近更新时间:2025-12-24 12:03:42

我的收藏

概述

同步表是一种特殊的表。数据写入时,它的修改需要强同步到多个 Follower 副本后,才能返回。因此,它的多个 Follower 副本能提供强一致性读服务。它适合写入频率较低,读操作较多、读操作延迟要求高的负载。
目前同步表以广播表的形式对外提供服务,用户的所有同步表的 Region 共用一个特殊的广播同步 RG(Replication Group)。该 RG 在用户创建第一个同步表时创建,后续用户的其他同步表 Region 也会调度到该同步 RG。广播同步 RG 在系统内每个节点上均包含一个副本,每个 Follower 定期向 Leader 申请租约,在 Leader 上发生写入时,需要等待直到修改强同步到每个持有有效租约的 Follower 上后才能返回。在有读取请求时,同步表会先尝试本地读取,本地读取失败再读取 Leader 。

工作原理

普通事务写入流程

1. 数据在事务提交前会暂存在事务上下文的 write batch 中。
2. 进入提交阶段,Leader 会将 write batch 中的数据落盘形成事务日志,通过 Raft 协议同步到各副本所在节点。
3. 形成多数派后,Leader 再把数据先写入 RocksDB,然后返回客户端。Follower 副本则回放 Raft 日志并写入 RocksDB。

同步表事务写入流程

1. 在执行阶段,同步表事务和普通事务一样都把数据暂存在事务上下文的 write batch 中。
2. 进入提交阶段后,Leader 同样会以 Raft 日志的形式将数据同步给 Follower。
3. 和普通事务不同的是,同步表要求所有有效的 Follower 都返回了日志,然后才能返回客户端。

具体来说,对于分布式事务,Leader 向 Follower 做强同步的逻辑如下:
3.1 提交 redo 和 prepare 日志。
3.2 
获取所有 lease valid 的副本。

3.3 询问每个副本是否已经回放 prepare 日志。
3.4 如果所有副本已经回放 prepare 日志,应答协调者。
3.5 否则,跳转到 步骤2 重试。
Follower 上收到读请求时不能再直接报错,而是需要检查可读性(包括 lease 检查等),可读性检查通过后读的逻辑和 Leader 上一致,即先检查锁信息看是否有处于 prepare 状态的事务需要阻塞自己,没有则直接根据读版本号读取 RocksDB。
Leader 需要维护一个有效 Follower 列表,提交阶段需要向所有有效 Follower 进行强同步。这个有效 Follower 列表是通过 lease 机制来维护的。Follower 定期向 Leader 申请 lease,Leader 收到 lease申请后,如果同意授予 lease,则将该节点加入有效 Follower 列表,并通过 Raft 日志同步 lease log。之后 Leader 上的所有修改都需要向该 Follower 同步。如果 Follower 长时间未续约 lease 导致 lease 过期,Leader 将该 Follower 踢出有效列表,后续不再向该 Follower 做强同步。Follower 在 lease 有效期内才可以对外提供强同步服务,lease 过期则禁止提供强同步服务。该机制保证 Follower 上的 lease 先过期,即 Follower 先停止提供强同步服务;Leader 上的 lease 后过期,即 Leader 后停止强同步。

使用限制

目前同步表以广播表的形式对外提供服务,用户必须创建广播同步表来使用同步表。
任意一个 Follower 副本故障,可能导致写请求卡顿一个租约的时间。
读请求路由策略本地优先,本地访问失败则访问 Leader 。
目前暂不支持同步表的属性变换,即不支持从同步表变为非同步表,也不支持从非同步表变为同步表。
同步表不能是分区表。
广播同步日志流一旦被创建出来后就不会再被销毁,即使用户删除所有的同步表。
副本个数过多会导致写请求性能下降。

使用说明

同步表适用于读多写少且对延迟敏感的业务表。如系统参数、全局配置表、数据仓库维度表(如 TPCC 中的 item 表)。

语法

CREATE TABLE table_name (
column_definitions
) sync_level = node(all) distribution = node(all);
同步表的读写访问语法和普通表保持一致。但读取时,具体访问的节点和连接有关。具体来说,TDSQL Boundless 会优先访问连接所在的本地节点的同步表副本,只有当本地节点不可读时(例如 lease 过期),才会退化为访问 Leader 节点。

示例

tdsql [demo]> CREATE TABLE test_sync_table(
c1 INT PRIMARY KEY,
c2 INT,
c3 INT,
INDEX idx(c2)
) sync_level = node(all) distribution = node(all);
Query OK, 0 rows affected (2.90 sec)

相关参数

参数名
默认值
说明
tdstore_sync_table_max_allowed_log_lag
1024
Leader 在决定是否授予 Follower lease 时,需要考虑 Follower 的日志回放进度。如果 Follower 当前回放进度落后于 Leader 超过该参数值时,Leader 将不会授予 lease。
tdstore_sync_table_lease_interval_ms
2000
Follower 向 Leader 申请 lease 的周期。
tdstore_sync_table_log_interval_ms
1000
Leader 同步 Raft lease log 的周期。
tdstore_sync_table_lease_len_us
10000000
Leader 每次向 Follower 授予的 lease 有效期。