地理多活
普通复制只有一个主库能写。Active-Active 让每个区域都是可写的主库,用户就近读写、延迟低到亚毫秒。代价是并发写必然冲突——Redis 用 CRDT 把冲突变成一道确定的合并题,让所有区域最终收敛到同一个结果。
每个区域都是可写的主库
Active-Active(旧称 CRDB)是基于 CRDT 的地理多活数据库。它至少横跨两个参与集群(区域),每个区域各有自己的主节点和 endpoint。应用连最近的区域,本地读写延迟可低于 1ms;某个区域挂了,其它区域照常服务。
这和上一类「一主多从」的复制根本不同:那里只有一个主库能写,从库只读;这里是多主(multi-primary),你连哪个区域都能写。
像一份多人协作文档:每个人(区域)都在编辑自己手上的副本,改动异步同步给其他人。关键不在于"谁先谁后",而在于合并规则足够聪明——谁都不会无声无息地覆盖掉别人的改动。
只复制数据本身。 Active-Active 在区域间同步的是数据,不包括数据库配置、Lua 脚本等——这些要在每个区域各自设置。
低延迟、容灾、合规
全球低延迟
用户就近连本地区域读写,不必跨洋往返,写延迟可低至亚毫秒。
容灾
多主、无单点。一个区域整体故障,其它区域继续对外提供读写。
数据驻留合规
可以把数据保留在特定地理区域,满足数据主权与合规要求。
冲突不可避免,但可以无冲突地解决
既然能连任意区域写,并发且冲突的写入随时可能发生。传统做法是「最后写入者胜」(LWW)——简单,但会丢数据:两地同时给计数器 +1,LWW 只保留一个,结果少算了一次(就像首图里的 6 而非 7)。
CRDT(Conflict-free Replicated Data Type,无冲突复制数据类型)换了思路:为每种数据类型设计一套满足交换律 / 结合律 / 幂等的合并规则,使得无论同步顺序如何,所有副本都收敛到同一结果,而且这个结果符合该类型的语义意图。应用不需要写任何冲突处理代码。
一句话抓住本质:把「谁覆盖谁」的抢占,换成「怎么合并」的运算。 加法可交换,所以两地的 +1 无论先同步哪个,结果都是 +2。
不同数据类型,不同合并规则
CRDT 的冲突解决是「按数据类型 + 命令」定制的——它理解每种类型"本该"怎么合并。
| 数据类型 | 冲突解决 | 说明 |
|---|---|---|
| 计数器 Counter INCR / DECR |
求和 · 无冲突 | 各区域的增减全部累加,不丢更新。并发「删除 vs 自增」→ 自增胜(add-wins),DEL 视为"重置"。 |
| 集合 Set SADD / SREM |
Add-Wins 观察移除 | 并发 SADD 取并集、无冲突(可结合);添加与删除相争时,添加胜。 |
| 字符串 String SET / APPEND |
最后写入者胜 | LWW 寄存器语义。并发设置不同过期时间时,较大的 TTL 胜。 |
| 哈希 Hash HSET / HDEL |
按字段合并 | 映射型 CRDT。改不同字段互不冲突;同一字段按计数器 / 字符串语义解决。 |
| 列表 List LPUSH / POP |
保留所有项 | 用元素 ID 标识,合并时保留各区域插入的所有项。 |
强最终一致性与 Syncer
Active-Active 采用强最终一致性:短时间内各区域的本地值可能不同,但最终都会收敛到同一状态。底层用向量时钟 + CRDT 判定合并;还可选开启因果一致性,在同步时保持操作的因果顺序。
跨区域同步靠 Syncer 进程:它维护一份复制积压(backlog),把变更发给其它区域。平时做增量同步,当某个副本或主库丢失时,做一次全量同步补齐。
这不是强一致(线性一致)。 本地读到的可能是「还没同步完的旧值」,通常几秒内收敛。如果业务需要读到全局最新的唯一真相(如库存扣减防超卖),Active-Active 不是合适工具——那是另一种取舍。
创建一个多活数据库
建库时选 Active-Active 类型
在控制台点 Create Database,Type 选 Active-Active。
选择 2 个及以上区域
例如 us-east-1 与 eu-west-1,分别设置内存大小与区域内复制。每个区域会拿到自己的 endpoint。
应用就近连接、本地读写
应用连接最近区域的 endpoint 即可,读写都在本地完成,跨区同步由 Redis 自动处理。
几个要记住的边界:计数器是 59 位(比 64 位有符号少 5 位,上限约 2.88×10¹⁷);Active-Active 数据库默认驱逐策略是 noeviction,且驱逐在分片达 80% 内存时就更早触发;跨区只同步数据,配置与脚本各区自理。
用多活前,先想清楚这些
把抢占,换成合并
Active-Active 让每个区域都能写,用 CRDT 把并发冲突变成一道确定的合并题,最终所有区域收敛到同一状态。它用最终一致,换来了全球低延迟与区域级容灾。


