命令支持
哪些 Redis 命令会跨数据中心复制,哪些命令仅在本地执行且不会离开数据中心,以及哪些命令会因错误而被拒绝。
在 Redis 7.2 上,同一复制模块同时为灾难恢复(peerof)和 Active-Active(mesh)提供服务,并在两种模式下以完全相同的方式对每个命令进行分类。模式改变的是哪些成员接受应用写入,因此也决定了下文所述冲突解决行为实际发生的频率。
Redis 6.0 运行旧版模块,该模块仅支持灾难恢复,复制的命令集较小,并且不执行任何防护措施。请参阅Redis 6.0 — 旧版模块。
目录
按模式汇总因错误而被拒绝在本地执行,永不复制复制的写入命令StringsHashesSetsSorted setsListsKeyspace位图、HyperLogLog 和地理空间脚本和函数与独立 Redis 不同的行为至少一次弹出不具备跨数据中心的原子性对一个键执行不同类型的写入会静默解决已删除的数据会一直占用内存,直到每个成员都确认收到模块的簿记键可见Redis 6.0 — 旧版模块相关页面按模式汇总
这些拒绝规则由模块的命令过滤器执行;在 Redis 7.2 上启用跨数据中心复制时,该过滤器始终会安装。因此,即使灾难恢复实例只有一个写入方,MOVE、SWAPDB 或 RESTORE 在灾难恢复实例上的执行也会像在 Active-Active 成员上一样失败。依赖这些命令的应用必须在实例加入复制组之前完成修改。
因错误而被拒绝
这些命令在 Redis 7.2 上完全不会执行。客户端会收到错误,并且不会在本地或复制端写入任何内容。
错误分别为:
要清空复制组,请移除连接(或移除 ActiveRedisMesh 资源),在每个已隔离的实例上执行清空操作,然后重新创建它们。或者,重新创建这些实例。
FUNCTION RESTORE 不在此列表中——它受支持。只有键级别的 RESTORE 会被拒绝。
在本地执行,永不复制
这些命令的运行方式与未修改的 Redis 完全相同。它们不会报错,也不会被拒绝——只是不会产生跨数据中心的影响,因此每个数据中心中与之相关的状态都是独立的。
由于对等成员中同名的键是彼此无关的本地 stream,当通用键命令作用于 stream 键时,这些命令不会跨数据中心:
- 为 stream 键设置 TTL 会被拒绝——复制的过期操作会删除对等成员中无关的本地 stream。
- 对 stream 键执行
PERSIST会在本地执行,但不会复制。 - 涉及 stream 键的
DEL、RENAME和COPY不会复制。
复制的写入命令
此处列出的所有命令都会复制到复制组中的每个其他成员。冲突行为列描述了两个成员同时写入同一个键时如何进行协调。在灾难恢复模式下,只有上游成员接收应用写入,因此这些规则适用,但很少会被触发;在 Active-Active 模式下,这些规则会持续被触发。
全文使用以下五种冲突规则:
Strings
Hashes
Sets
Sorted sets
Lists
弹出操作具有至少一次语义:在两个数据中心同步之前,同一个元素可能会在这两个数据中心中分别被弹出。请从单个数据中心消费,或使消费者具备幂等性。
Keyspace
位图、HyperLogLog 和地理空间
脚本和函数
由于脚本执行的每个写入操作都会单独复制,因此脚本遵循与其他客户端相同的按命令处理规则。脚本不会因为是脚本而自动具备幂等性。
与独立 Redis 不同的行为
请围绕这些行为设计应用逻辑。它们是复制模型的结果,而不是缺陷。
至少一次弹出
LPOP、RPOP、SPOP、ZPOPMIN、ZPOPMAX 及其阻塞和多键变体,在单个成员上是恰好一次的,但在整个复制组中至少一次。两个成员在同步前并发弹出时,可能各自消费同一个元素。从单个成员消费,或使消费者具备幂等性。
不具备跨数据中心的原子性
MULTI/EXEC、MSET 和 MSETNX 按键或按命令复制。所有键都会到达,成员也会收敛,但对等成员不会以原子方式应用整个组——对等成员可能会短暂观察到事务的一部分。
对一个键执行不同类型的写入会静默解决
对同一个键执行不同类型的并发写入(一个数据中心中的 SET key,另一个数据中心中的 HSET key)会按时间戳解决;如果时间戳相同,则由较高的 serviceID 获胜。失败方的数据会被丢弃,不会进行合并,也不会产生错误。
已删除的数据会一直占用内存,直到每个成员都确认收到
删除操作会以墓碑的形式保留——用于记录某个键、字段或元素已被删除——这样对等成员的延迟写入就无法使已删除的数据重新出现。只有在每个活动对等成员都确认收到墓碑且其最短存留时间达到五分钟后,墓碑才会释放。因此,长时间无法访问的对等成员会使其他每个成员上的墓碑持续存在——对于永久离线的数据中心,请按照限制和风险中的说明将其退役。较大的时钟偏差会缩小这一保护范围;请参阅时钟同步。
模块的簿记键可见
模块会将部分复制簿记信息作为普通 Redis 键存储在保留的 __arcr_ 前缀下。这些键会被 DBSIZE 计数,并由 SCAN 和 KEYS 返回,直到被回收;它们会在每个成员上独立派生,因此其数量和时间在不同数据中心之间合法地存在差异。任何比较不同数据中心数据集的工具都必须排除整个 __arcr_ 前缀。应用程序不得写入该前缀。
Redis 6.0 — 旧版模块
Redis 6.0 运行冻结的旧版模块,仅支持 Disaster Recovery。其行为与 Redis 7.2 有两点在运维上值得注意的差异。
它复制的命令集合更小。 它复制的命令如下:
Redis 6.0 之后引入的命令,以及在本地执行、从不复制下列出的命令,都不会由旧版模块复制——包括所有流命令、发布/订阅、MIGRATE 以及 MULTI/EXEC 边界。
它没有任何防护机制。 旧版模块不会拒绝任何命令。FLUSHALL、FLUSHDB、MOVE、SWAPDB 和 RESTORE 会被包装并复制到下游,而不是被拒绝。
由于旧版模块会复制这些命令,在 Redis 6.0 上游执行的 FLUSHALL 或 FLUSHDB 也会清空每个下游实例。不会进行确认,也不会报错。在 Redis 6.0 上,应将这两个命令视为会破坏整个复制组的命令,并考虑使用 ACL 限制它们。
在 Redis 7.2 上,只要对等成员已连接,就会拒绝相同的命令——请参阅拒绝并返回错误。
若要将现有的 Redis 6.0 组迁移到新模块,请按照将 Disaster Recovery 组从 Redis 6.0 升级到 Redis 7.2中的说明操作。
相关页面
- 限制和风险 — 拓扑、配置和操作约束
- Disaster Recovery — 热备模式,其中单个成员负责处理写入
- Active-Active — 持续执行这些规则的模式,包括时钟同步要求