Redis pipeline
和 MGET
的异常机制
当 Redis pipeline
和 MGET
在执行过程中遇到错误时,它们的错误处理机制有所不同,具体如下:
1. MGET
的异常机制
情况 1:某个 Key 不存在
MGET
对于不存在的 key,不会报错,而是返回nil
(Python 中是None
)。示例:
redis> MGET key1 key2 key3 1) "value1" 2) nil 3) "value3"
key2
不存在,但MGET
不会抛出异常,只是返回nil
。
情况 2:Redis 服务器崩溃
如果 Redis 服务器 不可用(down),
MGET
调用会失败,返回 连接异常。Python 示例:
import redis r = redis.StrictRedis(host="127.0.0.1", port=6379, decode_responses=True) try: result = r.mget(["key1", "key2"]) print(result) except redis.exceptions.ConnectionError as e: print(f"Redis 连接失败: {e}")
当 Redis 宕机 时,会抛出
redis.exceptions.ConnectionError
。
情况 3:跨分片查询(Redis Cluster 模式)
MGET
不能跨分片,如果 keys 在不同分片,会报CROSSSLOT
错误:(error) CROSSSLOT Keys in request don't hash to the same slot
解决方案:
确保 keys 在同一槽位,使用 哈希标签
{}
:MGET {user}:1 {user}:2
2. pipeline
的异常机制
情况 1:某个命令失败
pipeline
不会影响整个批次,即使其中某个命令失败,Redis 仍然会继续执行其他命令。示例:
import redis r = redis.StrictRedis(host="127.0.0.1", port=6379, decode_responses=True) pipe = r.pipeline() pipe.set("key1", "value1") pipe.get("non_existing_key") # 不存在的 key,不会报错,只返回 None pipe.lpush("key1", "value2") # 错误:尝试对字符串执行列表操作 pipe.get("key1") try: results = pipe.execute() print(results) except redis.exceptions.RedisError as e: print(f"Redis 命令失败: {e}")
如果
LPUSH key1 value2
失败,它 不会影响get key1
的执行,Redis 仍然返回部分成功的结果:['OK', None, ResponseError('WRONGTYPE Operation against a key holding the wrong kind of value'), 'value1']
情况 2:Redis 服务器崩溃
如果 Redis 服务器宕机或连接断开:
try: pipe = r.pipeline() pipe.set("key1", "value1") pipe.execute() except redis.exceptions.ConnectionError as e: print(f"Redis 连接失败: {e}")
所有 pipeline 命令都会失败,返回
redis.exceptions.ConnectionError
。
情况 3:跨分片查询(Redis Cluster 模式)
pipeline
可以跨分片执行,但 Redis 会自动拆分请求 并分别发送到不同分片,不会报CROSSSLOT
错误。但如果 某个分片发生错误,会导致部分请求失败:
import rediscluster startup_nodes = [{"host": "127.0.0.1", "port": 6379}] rc = rediscluster.RedisCluster(startup_nodes=startup_nodes, decode_responses=True) pipe = rc.pipeline() pipe.get("user:1") # 可能在 shard1 pipe.get("order:123") # 可能在 shard2 try: results = pipe.execute() print(results) except redis.exceptions.RedisClusterException as e: print(f"Redis Cluster 失败: {e}")
部分 key 可能成功,部分失败,需要在应用层检查返回值。
3. pipeline
vs MGET
异常处理对比
4. 结论
如果 key 可能不存在:
MGET
只会返回nil
,不会报错。pipeline
返回None
,但仍然继续执行后续命令。
如果 Redis 宕机:
MGET
和pipeline
都会失败,但pipeline
影响范围更大。
如果 Redis Cluster 跨分片:
MGET
不支持,报CROSSSLOT
错误。pipeline
支持,但部分 key 可能失败。
如果某个命令失败:
pipeline
不会影响其他命令,但需要在代码中手动处理ResponseError
。
总结
批量读取推荐
MGET
,如果 key 都在一个分片。批量操作(读写混合)用
pipeline
,但要注意部分失败情况。分布式 Redis(Cluster 模式)推荐
pipeline
,但要处理可能的部分失败情况。