Redis集群模式选型与架构设计要点
Redis提供三种集群模式:主从复制(读写分离)、哨兵模式(自动故障转移)和Cluster模式(数据分片+高可用)。生产环境数据量超过单机内存或QPS超过单节点承载能力时,必须使用Cluster模式。Redis Cluster将16384个哈希槽分配到多个主节点,每个key通过CRC16(key)%16384确定所属槽位。
架构设计核心要点:主节点至少3个(每个负责约5461个槽),每个主节点配1个从节点;客户端使用Smart Client(Jedis Cluster / Lettuce)缓存槽位映射,避免MOVED重定向开销;跨机房部署时同主从放在同机房减少网络延迟。
Redis Cluster部署与配置实战
# redis.conf 集群配置
port 6379
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
cluster-announce-ip 10.0.1.11
cluster-announce-port 6379
cluster-announce-bus-port 16379
# 内存与持久化配置
maxmemory 16gb
maxmemory-policy allkeys-lru
appendonly yes
appendfsync everysec
# 启动6个节点(3主3从)后创建集群
redis-cli --cluster create \
10.0.1.11:6379 10.0.1.12:6379 10.0.1.13:6379 \
10.0.1.14:6379 10.0.1.15:6379 10.0.1.16:6379 \
--cluster-replicas 1
# 验证集群状态
redis-cli cluster info
缓存穿透防护:布隆过滤器与空值缓存策略
缓存穿透指大量请求查询数据库中根本不存在的数据,请求绕过缓存直接打到数据库。典型场景:恶意攻击请求随机ID、爬虫遍历不存在的URL。
// 布隆过滤器方案(Java + RedisBloom)
// 1. 服务启动时将所有合法ID加载到布隆过滤器
BloomFilter<String> bloomFilter = bloomFilterOps.createFilter(
"valid_ids", 10000000L, 0.01); // 1000万ID,1%误判率
// 全量加载合法ID
List<String> allIds = productMapper.selectAllIds();
allIds.forEach(id -> bloomFilterOps.add("valid_ids", id));
// 2. 查询时先校验布隆过滤器
public Product getProduct(String id) {
if (!bloomFilterOps.contains("valid_ids", id)) {
return null;
}
String cacheKey = "product:" + id;
String cached = jedis.get(cacheKey);
if (cached != null) {
if ("NULL".equals(cached)) return null;
return JSON.parseObject(cached, Product.class);
}
Product product = productMapper.selectById(id);
if (product == null) {
jedis.setex(cacheKey, 60, "NULL");
return null;
}
jedis.setex(cacheKey, 3600, JSON.toJSONString(product));
return product;
}
缓存雪崩防护:随机过期与熔断降级方案
缓存雪崩指大量key同一时刻过期,请求瞬间全部打到数据库。常见原因:批量设置相同TTL、缓存服务整体宕机。
// 随机TTL防批量过期
public void setWithRandomTTL(String key, String value, int baseSeconds) {
int randomOffset = ThreadLocalRandom.current().nextInt(baseSeconds / 10);
jedis.setex(key, baseSeconds + randomOffset, value);
}
// 批量预热数据时分散TTL
public void warmUpCache(List<Product> products) {
Pipeline pipeline = jedis.pipelined();
for (Product p : products) {
String key = "product:" + p.getId();
int ttl = 3600 + ThreadLocalRandom.current().nextInt(360);
pipeline.setex(key, ttl, JSON.toJSONString(p));
}
pipeline.sync();
}
// Hystrix熔断降级保护数据库
@HystrixCommand(
fallbackMethod = "getProductFallback",
commandProperties = {
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="20"),
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="50"),
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="5000")
}
)
public Product getProductWithCircuitBreaker(String id) {
return getProduct(id);
}
public Product getProductFallback(String id) {
return Product.defaultProduct(id);
}
缓存击穿防护:互斥锁与逻辑过期方案
缓存击穿指热点key过期的瞬间,大量并发请求同时打到数据库重建缓存。与雪崩不同,击穿是单个key的问题,但该key是热点数据。
// 方案1:互斥锁(Redis SETNX实现)
public Product getProductWithMutex(String id) {
String cacheKey = "product:" + id;
String lockKey = "lock:product:" + id;
String cached = jedis.get(cacheKey);
if (cached != null) {
return "NULL".equals(cached) ? null : JSON.parseObject(cached, Product.class);
}
if ("OK".equals(jedis.set(lockKey, "1", "NX", "EX", 10))) {
try {
cached = jedis.get(cacheKey);
if (cached != null) return JSON.parseObject(cached, Product.class);
Product product = productMapper.selectById(id);
int ttl = product != null ? 3600 : 60;
String val = product != null ? JSON.toJSONString(product) : "NULL";
jedis.setex(cacheKey, ttl, val);
return product;
} finally {
jedis.del(lockKey);
}
} else {
Thread.sleep(50);
return getProductWithMutex(id);
}
}
// 方案2:逻辑过期(不设TTL,数据内嵌过期时间)
public Product getProductWithLogicalExpire(String id) {
String cacheKey = "product:logic:" + id;
String cached = jedis.get(cacheKey);
if (cached == null) return rebuildCache(id);
CacheData cacheData = JSON.parseObject(cached, CacheData.class);
if (cacheData.getExpireTime().isAfter(LocalDateTime.now())) {
return cacheData.getProduct();
}
if ("OK".equals(jedis.set("lock:rebuild:" + id, "1", "NX", "EX", 10))) {
CompletableFuture.runAsync(() -> rebuildCache(id));
}
return cacheData.getProduct();
}
三种缓存问题的防护策略总结:穿透用布隆过滤器+空值缓存、雪崩用随机TTL+熔断降级、击穿用互斥锁+逻辑过期。生产环境应同时部署三种防护机制,Redis Cluster配合多级缓存(L1本地Caffeine + L2 Redis)是高并发场景的标准架构方案。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/redis-ji-qun-jia-gou-she-ji-yu-huan-cun-chuan-tou-xue-beng/