6、Redis高并发缓存方案和性能优化

一、主从节点失效问题及解决方案

1. 主从失效问题本质

ClientA Master Slave ClientB SET lock_key clientA_id EX 30 (加锁成功) 同步失败(网络问题) Master宕机 选举为新Master SET lock_key clientB_id EX 30 (加锁成功) ClientA Master Slave ClientB

2. 解决方案对比

方案 原理 优点 缺点 适用场景
min-replicas-to-write 要求写入N个从节点才算成功 保证数据同步性 增加写入延迟 对一致性要求高的场景
Redlock算法 需要半数以上节点写入成功 更高的可靠性 性能损耗大 极端一致性要求的场景
混合持久化 AOF+RDB混合持久化策略 平衡性能与可靠性 仍有数据丢失窗口 通用场景

二、分布式锁优化方案

1. 分段锁设计

比如商品a的id为product_1001_bike,库存有1000个,普通思路是对这个key加锁,key是product_1001_bike,每次请求只能有一个请求同时操作库存。

可以拆分key为product_1001_bike_1、product_1001_bike_2...product_1001_bike_10,每个key的库存是100,每个key就是一把锁,那么这个时候高并发下,可以最多10个请求同时操作库存。

每次选哪个锁呢?每个key放到一个数组里,随机选,或者轮询

java 复制代码
// 传统锁
RLock lock = redisson.getLock("product_1001");

// 分段锁优化(10个分段)
String[] segmentKeys = {
    "product_1001_seg1", 
    "product_1001_seg2",
    ...
    "product_1001_seg10"
};

// 随机选择分段
Random rand = new Random();
RLock segmentLock = redisson.getLock(segmentKeys[rand.nextInt(10)]);

2. 读写锁优化

java 复制代码
// 写操作(独占锁)
RReadWriteLock rwLock = redisson.getReadWriteLock("product_lock");
rwLock.writeLock().lock();
try {
    // 更新操作
} finally {
    rwLock.writeLock().unlock();
}

// 读操作(共享锁)
rwLock.readLock().lock();
try {
    // 查询操作
} finally {
    rwLock.readLock().unlock();
}

三、缓存问题综合解决方案

1. 缓存问题矩阵

问题类型 现象 解决方案 补充策略
缓存击穿 热点key失效瞬间高并发,大量请求打到数据库 互斥锁重建 永不过期+后台更新
缓存穿透 透(与缓存击穿作区分),查询不存在的数据,即缓存和数据库都没有, 重复请求可能还会消耗缓存和数据库性能 布隆过滤器 缓存空对象 空对象短过期时间
缓存雪崩 大量key同时失效,大量请求打到数据库和后端, 逐渐导致数据库崩溃,后端服务崩溃,甚至整个服务不可用 随机过期时间 多级缓存 熔断降级机制

2. 热点key重建优化流程

是 否 获取成功 获取失败 请求到达 缓存是否存在? 返回缓存数据 尝试获取分布式锁 查询DB并重建缓存 短暂等待后重试 释放锁

3. 热数据,读延期

每天都有访问的key,就是热数据,可以做读延期:

java 复制代码
// 有数据直接延期 防止key过期访问数据库
String productStr = redisUtil.get(productCacheKey);
if (!StringUtils.isEmpty(productStr)) {
    product = JSON.parse0bject(productStr, Product.class);
    //读延期
    redisUtil.expire(productCacheKey, PRODUCT_CACHE_TIMEOUT, TimeUnit.SECONDS);
    return product;
}

4. 多级缓存架构

复制代码
客户端请求
↓
CDN缓存 → 命中则返回
↓
Nginx本地缓存 → 命中则返回
↓
Redis集群缓存 → 命中则返回
↓
DB查询 + 回填缓存

四、开发规范与性能优化

1. Key设计规范

  • 命名规则业务:子业务:ID (如 trade:order:123)
  • 长度控制:不超过44字节(Redis优化阈值)
  • 特殊字符:禁止包含空格、换行符等

2. BigKey规避策略

数据类型 危险阈值 优化方案
String >10KB 压缩/分片
Hash/Set >1000元素 拆分为多个key
List/ZSet >5000元素 分页存储

3. 缓存双写一致性方案对比

方案 一致性 复杂度 性能影响
分布式锁 强一致 较大
延迟双删 最终一致 中等
监听binlog 最终一致
设置过期时间 弱一致

五、高级场景解决方案

1. 突发流量处理

java 复制代码
// 使用Redisson的tryLock优化热点重建
RLock hotLock = redisson.getLock("hot:"+productId);
if (hotLock.tryLock(0, 30, TimeUnit.SECONDS)) {
    try {
        // 双重检查
        String cache = redis.get(productKey);
        if (cache == null) {
            Product p = db.get(productId);
            redis.setex(productKey, 3600, p);
        }
    } finally {
        hotLock.unlock();
    }
} else {
    // 快速失败或降级处理
    return fallbackProduct;
}

2. 多级缓存实现示例

java 复制代码
public Product getProduct(Long id) {
    // 1. 检查本地缓存
    Product product = localCache.get(id);
    if (product != null) return product;
    
    // 2. 检查Redis缓存
    String redisKey = "product:" + id;
    product = redisTemplate.opsForValue().get(redisKey);
    if (product != null) {
        localCache.put(id, product); // 回填本地缓存
        return product;
    }
    
    // 3. 数据库查询
    return getProductFromDBWithLock(id);
}

六、监控与应急方案

1. 关键监控指标

  • 缓存命中率keyspace_hits/(keyspace_hits+keyspace_misses)
  • 大Key扫描 :定期执行redis-cli --bigkeys
  • 慢查询 :配置slowlog-log-slower-than 10ms

2. 应急预案

  1. 热点Key:提前预热+本地缓存
  2. 缓存雪崩:差异化过期时间+熔断降级
  3. 集群故障:手动切换+只读模式
相关推荐
我科绝伦(Huanhuan Zhou)7 分钟前
【故障案例】Redis缓存三大难题:雪崩、击穿、穿透解析与实战解决方案
redis·缓存·mybatis
柏木乃一1 小时前
Linux初步认识与指令与权限
linux·运维·服务器·shell·权限
Joemt1 小时前
ubuntu源码编译安装cmake高版本、pybind11安装、crow使用
linux·运维·ubuntu
真智AI2 小时前
打破数据质量瓶颈:用n8n实现30秒专业数据质量报告自动化
大数据·运维·人工智能·python·自动化
nightunderblackcat2 小时前
进阶向:自动化天气查询工具(API调用)
运维·自动化
企鹅侠客2 小时前
3 使用 Jenkins 构建镜像:将你的应用打包成镜像
运维·jenkins·jenkins构建镜像
bigcarp2 小时前
linux + 宝塔面板 部署 django网站 启动方式:uwsgi 和gunicorn如何选择 ?
linux·运维·django
元亓亓亓4 小时前
Redis--day1--初识Redis
数据库·redis·缓存
每天敲200行代码4 小时前
Redis 初识Redis
数据库·redis·github