多键操作
提示
来自deepseek解释
原文链接:https://redis.io/docs/latest/develop/using-commands/multi-key-operations/
Redis 中的多键操作允许您在单个命令中处理多个键,但其行为会根据您的 Redis 配置和集群设置而有显著差异。本页面为开发者在不同 Redis 配置下处理多键操作提供了快速参考。
配置
Redis 支持五种不同的配置,每种配置具有不同的多键命令行为:
- ROS/RS 集群禁用 - 单 Redis 实例
- ROS,集群启用 - Redis Open Source 集群
- RS,集群启用,OSS Cluster API 启用 - 具有 ROS 集群兼容性的 Redis Software
- RS,集群启用,OSS Cluster API 禁用 - Redis Software 专有集群
- RS,Active-Active - Redis Software Active-Active(即使只有单个分片也视为集群)
ROS 代表 Redis Open Source,RS 代表 Redis Software。
命令行为
对于每种配置,命令表现为三种行为之一:
- single-slot:命令必须操作同一哈希槽内的键
- cross-slot (all shards):命令可以操作集群中所有分片
- cross-slot (within a single shard):命令可以跨槽操作,但仅限于单个分片内
只读命令
| 行为 | 命令 |
|---|---|
| ROS/RS 集群禁用: – 整个数据库(单分片) ROS 集群启用,RS 集群启用(OSS Cluster API 启用): – 当前分片 RS 集群启用(OSS Cluster API 禁用): – 所有分片 | DBSIZE, KEYS, SCAN |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用): – single-slot RS 集群启用(OSS Cluster API 禁用): – 跨槽(所有分片) | EXISTS, MGET |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用),RS 集群启用(OSS Cluster API 禁用): – single-slot | PFCOUNT, SDIFF, SINTER, SINTERCARD, SUNION, WATCH, XREAD, XREADGROUP, ZDIFF, ZINTER, ZINTERCARD, ZUNION |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用),RS 集群启用(OSS Cluster API 禁用): – 单分片 | JSON.MGET 用户不会收到 CROSSSLOT 错误。但是,当集群启用且并非所有指定键都在同一槽时,用户将获得当前分片上所有槽的部分结果。 |
| ROS/RS 集群禁用: – 跨槽(所有分片) ROS 集群启用,RS 集群启用(OSS Cluster API 启用),RS 集群启用(OSS Cluster API 禁用): – 跨槽(所有分片),不能作为事务的一部分 | TS.MGET, TS.MRANGE, TS.MREVRANGE, TS.QUERYINDEX |
读写命令
| 行为 | 命令 |
|---|---|
| ROS/RS 集群禁用: – 整个数据库(单分片) ROS 集群启用,RS 集群启用(OSS Cluster API 启用): – 当前分片 RS 集群启用(OSS Cluster API 禁用): – 所有分片 | FLUSHALL, FLUSHDB |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用): – single-slot RS 集群启用(OSS Cluster API 禁用): – 跨槽(所有分片) | DEL, MSET, TOUCH, UNLINK 注意:在 Active-Active 上,DEL、MSET 和 UNLINK 是 single-slot |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用),RS 集群启用(OSS Cluster API 禁用): – single-slot | BITOP, BLMOVE, BLMPOP, BLPOP, BRPOP, BRPOPLPUSH, BZMPOP, BZPOPMAX, BZPOPMIN, CMS.MERGE, COPY, GEORADIUS 或 GEORADIUSBYMEMBER(带 STORE 或 STOREDIST),GEOSEARCHSTORE, JSON.MSET, LMOVE, LMPOP, MSETNX, PFMERGE, RENAME, RENAMENX, RPOPLPUSH, SDIFFSTORE, SINTERSTORE, SMOVE, SUNIONSTORE, TDIGEST.MERGE, TS.MADD, ZDIFFSTORE, ZINTERSTORE, ZMPOP, ZRANGESTORE, ZUNIONSTORE |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用),RS 集群启用(OSS Cluster API 禁用): – 单分片 | TS.CREATERULE, TS.DELETERULE 用户不会收到 CROSSSLOT 错误。但是,当集群启用且两个指定键不在同一槽时,用户将收到 (error) ERR TSDB: the key does not exist。 |
管道、事务和脚本
| 行为 | 操作 |
|---|---|
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用): – single-slot RS 集群启用(OSS Cluster API 禁用): – 跨槽(所有分片) | 管道 |
| ROS/RS 集群禁用: – 跨槽 ROS 集群启用,RS 集群启用(OSS Cluster API 启用),RS 集群启用(OSS Cluster API 禁用): – single-slot | MULTI/EXEC 事务中的键使用 EVAL 或 EVALSHA 执行的 Lua 脚本中的键 |
按配置分类的示例
单实例(无集群)
在单个 Redis 实例中,所有多键操作均无限制地工作:
redis
# 管道操作可以跨任意键工作
PIPELINE
SET user:1 "Alice"
SET product:100 "Widget"
GET user:1
GET product:100
EXEC
# 事务可以处理任意键
MULTI
SET counter:a 1
SET counter:b 2
INCR counter:a
INCR counter:b
EXEC集群环境
在集群设置中,您需要考虑槽分布:
redis
# 如果键在不同槽中,此操作可能失败
MSET user:1 "Alice" user:2 "Bob"
# 使用哈希标签确保相同槽
MSET {users}:1 "Alice" {users}:2 "Bob"
# 检查键属于哪个槽
CLUSTER KEYSLOT user:1
CLUSTER KEYSLOT {users}:1Active-Active 数据库
Active-Active 数据库对写操作有额外限制:
redis
# 读操作可以跨槽工作
MGET user:1 user:2 product:100
# 写操作必须在同一槽中
MSET {data}:user:1 "Alice" {data}:user:2 "Bob"多键操作故障排除
常见错误消息
- CROSSSLOT:请求中的键哈希到不同的槽
- MOVED:键已移动到另一个节点(在重新分片期间)
- TRYAGAIN:操作暂时不可用(在迁移期间)
解决方案
- 使用哈希标签 对相关键进行分组
- 重新设计数据模型 以最小化跨槽操作
- 在错误期间检查集群状态
- 为临时故障实现重试逻辑
性能考虑
- 单槽操作 最快,因为它们不需要协调
- 跨槽操作 可能因内部路由而有更高的延迟
- 模式命令(KEYS、FLUSHALL)扫描所有分片,开销可能很大
- 模块操作 可能有优化的跨槽实现
根据您的多键操作需求选择合适的 Redis 配置并设计您的数据模型。