Redis Cluster集群部署与缓存一致性方案实战配置

Redis Cluster集群架构与数据分片原理

Redis Cluster是Redis官方提供的分布式集群方案,通过数据分片实现水平扩展。在数据库运维中,当单节点Redis的内存容量或吞吐量达到瓶颈时,Cluster模式将数据分布在多个节点上,每个节点负责部分数据子集。Cluster采用无中心架构,所有节点通过Gossip协议互相通信,不存在单点故障。

Redis Cluster使用16384个哈希槽(Hash Slot)进行数据分片。每个键通过CRC16算法计算哈希值后对16384取模,确定所属槽位。集群中的每个节点负责一部分槽位,例如3节点集群中节点A负责0-5460,节点B负责5461-10922,节点C负责10923-16383。

Key与槽位的映射关系可以通过hash tag控制。当键名中包含{…}时,仅大括号内的部分参与哈希计算,确保相关键分配到同一槽位,支持在同一节点上执行多键操作和事务。

# hash tag示例 - user相关的键都在同一槽位
SET user:{1001}:profile "alice"
SET user:{1001}:orders "order_list"
# 两个键的hash tag都是"1001",分配到同一槽位

Cluster集群搭建与节点配置

最小Cluster集群需要6个节点:3主3从。以下是基于Docker的搭建流程:

# 创建Docker网络
docker network create redis-cluster

# 启动6个Redis节点
for i in $(seq 1 6); do
  docker run -d --name redis-$i --net redis-cluster \
    -v redis-$i-data:/data \
    redis:7 redis-server \
    --port 6379 \
    --cluster-enabled yes \
    --cluster-config-file nodes.conf \
    --cluster-node-timeout 5000 \
    --appendonly yes \
    --appendfsync everysec
done

# 创建集群(3主3从)
docker exec -it redis-1 redis-cli --cluster create \
  redis-1:6379 redis-2:6379 redis-3:6379 \
  redis-4:6379 redis-5:6379 redis-6:6379 \
  --cluster-replicas 1

# 查看集群状态
docker exec -it redis-1 redis-cli -c cluster info
docker exec -it redis-1 redis-cli -c cluster nodes

cluster-enabled yes启用集群模式,cluster-node-timeout设置节点超时时间(毫秒),超过此时间无响应的节点被标记为PFAIL状态。cluster-replicas 1表示每个主节点配备1个从节点。

读写分离与故障转移机制

Redis Cluster的读写策略:默认情况下,读请求路由到键所在的主节点。通过READONLY命令可以让从节点处理读请求,实现读写分离。但需要注意,Redis的复制是异步的,从节点可能存在数据延迟,对一致性要求高的读操作仍应路由到主节点。

# 连接集群并启用从节点读
redis-cli -c -h redis-1 -p 6379
127.0.0.1:6379> READONLY
OK
127.0.0.1:6379> GET user:1001
# 如果该键不在当前节点,集群会返回MOVED重定向

故障转移是Cluster的高可用核心机制。当主节点宕机时,其从节点发起选举成为新主节点。选举流程:从节点检测到主节点超时后,向其他主节点发送投票请求,获得多数派投票后升级为主节点,接管原主节点的槽位。

# 手动故障转移(计划内切换)
redis-cli -c -h slave-node -p 6379 cluster failover

# 强制故障转移
redis-cli -c -h slave-node -p 6379 cluster failover TAKEOVER

# 查看集群槽位分布
redis-cli -c cluster slots

缓存穿透与布隆过滤器方案

缓存穿透是指大量请求查询不存在的数据,Redis中无缓存,请求穿透到数据库。布隆过滤器(Bloom Filter)在Redis层之前拦截对不存在数据的查询,通过概率数据结构判断数据是否可能存在。

# RedisBloom模块 - 添加布隆过滤器
# 需要安装RedisBloom模块
docker run -d --name redis-bloom -p 6380:6379 \
  redislabs/rebloom:latest

# 创建布隆过滤器并添加元素
127.0.0.1:6380> BF.RESERVE user_exists 0.001 1000000
OK
127.0.0.1:6380> BF.ADD user_exists "user:1001"
(integer) 1
127.0.0.1:6380> BF.EXISTS user_exists "user:1001"
(integer) 1
127.0.0.1:6380> BF.EXISTS user_exists "user:9999"
(integer) 0

# Java集成示例
import io.rebloom.client.Client;

Client bloomClient = new Client("localhost", 6380);
bloomClient.createFilter("user_exists", 1000000, 0.001);

public User getUser(String userId) {
    // 先查布隆过滤器
    if (!bloomClient.exists("user_exists", "user:" + userId)) {
        return null; // 数据一定不存在
    }
    // 查Redis缓存
    String cached = redis.get("user:" + userId);
    if (cached != null) {
        return deserialize(cached);
    }
    // 查数据库
    User user = db.findById(userId);
    if (user != null) {
        redis.setex("user:" + userId, 3600, serialize(user));
    }
    return user;
}

布隆过滤器的误判率(false positive rate)参数需要权衡:误判率越低,内存占用越大。0.001的误判率意味着每1000次查询最多1次误判,对于百万级数据集需要约1.7MB内存。

缓存雪崩与热点Key治理

缓存雪崩是指大量缓存同时过期,请求全部打到数据库导致数据库过载。解决方案是给缓存过期时间添加随机偏移,避免同时失效:

# Python实现 - 随机过期时间
import redis
import random
import json

r = redis.RedisCluster(host='redis-cluster', port=6379)

def cache_set(key, value, base_ttl=3600):
    # 基础TTL + 随机偏移(300-600秒)
    ttl = base_ttl + random.randint(300, 600)
    r.setex(key, ttl, json.dumps(value))

def cache_get_or_load(key, loader_func, base_ttl=3600):
    # 双重检查锁定模式
    val = r.get(key)
    if val is not None:
        return json.loads(val)

    # 加锁防止缓存击穿(大量并发同时加载同一key)
    lock_key = f"lock:{key}"
    acquired = r.set(lock_key, "1", nx=True, ex=10)
    if not acquired:
        # 等待其他线程加载缓存
        time.sleep(0.1)
        val = r.get(key)
        if val is not None:
            return json.loads(val)
        return loader_func()

    try:
        val = loader_func()
        cache_set(key, val, base_ttl)
        return val
    finally:
        r.delete(lock_key)

热点Key问题是指某个Key的访问量远超其他Key,导致所在节点负载不均。Redis Cluster不支持在集群内自动均衡热点Key的读流量。解决方案包括:使用本地缓存(Caffeine/Guava)拦截热点读请求、在应用层将热点Key复制为多个副本(key:1, key:2…)分散到不同节点、使用读写分离将读流量分散到从节点。

Redis Cluster的运维监控需要关注以下指标:cluster_state(集群状态应为ok)、cluster_slots_assigned(已分配槽数应为16384)、cluster_slots_ok(正常槽数)、connected_clients(连接数)、used_memory(内存使用量)。通过Redis Exporter可以将这些指标接入Prometheus+Grafana监控体系,实现集群状态的实时可视化与告警。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rediscluster-ji-qun-bu-shu-yu-huan-cun-yi-zhi-xing-fang-an/

(0)
小编小编
上一篇 2小时前
下一篇 2小时前

相关推荐