Skip to content

一、单节点 Redis 与集群架构本质区别 ​

在单机模式下,Redis 提供了 0 ~ 15 共 16 个默认的逻辑数据库(Database),客户端可以通过 SELECT <db_index> 在不同库之间任意切换。

但在分布式 Redis Cluster 环境中,这种机制被彻底改变了:

Redis 集群模式下严禁使用 db 参数切换数据库(只支持 db 0)!

为什么集群不支持多数据库? ​

Redis Cluster 采用无中心化的分布式分片架构,将整个数据空间划分为 16384 个固定的哈希槽(Hash Slot)。

  • 每一个键(Key)通过 CRC16 算法计算哈希值:slot = CRC16(key) % 16384;
  • 16384 个槽位被平均分配到集群中的各个 Master 物理节点上;
  • 数据根据哈希槽由客户端或网关自动重定向(MOVED / ASK)路由到对应的物理机器,不再存在传统多 DB 的逻辑隔离。

二、Python 客户端连接与初始化 ​

在 Python 自动化测试或工程脚本中,使用 redis-py(4.x+ 内置 Cluster 模式)或 rediscluster 连接多节点集群:

python
from redis.cluster import RedisCluster
from redis.cluster import ClusterNode

# 配置集群种子节点(至少提供 3 个以上,驱动会自动握手发现全集群拓扑)
startup_nodes = [
    ClusterNode("10.0.1.11", 6379),
    ClusterNode("10.0.1.12", 6379),
    ClusterNode("10.0.1.13", 6379)
]

# 实例化集群客户端(密码及连接参数已脱敏)
r = RedisCluster(
    startup_nodes=startup_nodes,
    password="secure_redis_auth_token",
    decode_responses=True, # 自动将 bytes 转换为 Python str
    skip_full_coverage_check=True, # 允许节点临时抖动
    socket_timeout=5
)

三、五大核心数据结构实战操作 ​

1. 字符串(String):缓存与状态标记 ​

python
# 写入带过期时间的字符串(单位:秒)
r.set("device_status:1001", "ONLINE", ex=300)
status = r.get("device_status:1001")
print(f"当前设备状态: {status}")

2. 哈希(Hash):复杂对象与元数据存储 ​

python
# 批量写入与获取哈希字段
r.hset("device_meta:1001", mapping={"ip": "10.0.2.55", "fw_version": "v3.2.1", "retry_count": 0})

device_ip = r.hget("device_meta:1001", "ip")
all_meta = r.hgetall("device_meta:1001")
print("设备元数据字典:", all_meta)

3. 列表(List):任务排队与流式消费 ​

python
# 从右侧入队,左侧阻塞弹出(经典队列模式)
r.rpush("task_queue:inspection", "task_uuid_001", "task_uuid_002")
queue_length = r.llen("task_queue:inspection")
print(f"队列积压深度: {queue_length}")

# 获取前 10 条任务预览
tasks = r.lrange("task_queue:inspection", 0, 9)

4. 集合(Set):标签与去重集合 ​

python
# 维护不重复的标签池
r.sadd("supported_protocols", "MQTT", "HTTP", "MODBUS", "MQTT")
all_protocols = r.smembers("supported_protocols")
print("支持的协议集合:", all_protocols)

5. 有序集合(ZSet):时序排行榜与延迟队列 ​

python
# 以 Unix 时间戳作为分数(Score)实现时序排序
r.zadd("event_timeline:1001", {
    "ALERT_LOW_TEMP": 1725400000,
    "ALERT_HIGH_VIBRATION": 1725400300
})

# 按时间范围获取最新的前 5 个事件(带分数输出)
recent_events = r.zrevrange("event_timeline:1001", 0, 4, withscores=True)
for event_name, ts in recent_events:
    print(f"事件: {event_name}, 触发时间: {ts}")

四、集群环境核心避坑指南 ​

  1. 跨槽多键操作(Multi-key Operations)限制: 在集群模式下,像 MGET, MSET 或事务(MULTI/EXEC)如果涉及的多个 Key 分布在不同的哈希槽上,会直接报错 CROSSSLOT Keys in request don't hash to the same slot。
    • 解法(Hash Tag 机制):使用大括号 {} 强制让多个 Key 计算相同的哈希槽:
      python
      # 包含相同的 {user_1001} 前缀,确保它们绝对落在同一个 slot
      r.set("{user_1001}:name", "Alex")
      r.set("{user_1001}:role", "Admin")
  2. 连接池资源释放:长生命周期的脚本中,退出时应显式调用 r.close() 释放连接池的底层 Socket 描述符。

测试开发工程师 · 专注自动化与系统架构 | 邮箱: hansblog@atumsoul.win