背景
系统上发现有的业务场景,访问了几百次 redis。
虽然每一次速度不算慢,但是性能多次访问叠加,就有些慢了。
一些方式:
关于 redis 访问次数的一些优化思考。
mget, 优化为1次,pipeline、多线程并发。
jvm 本地缓存,使用 cache 避免内存过大,类似于布隆过滤器,set 之类的,先访问本地,然后才访问 redis。
chat
redis 访问优化的一些技巧
你提到的这些优化方向,基本覆盖了 Redis访问性能优化 的主线逻辑。
我帮你系统性地梳理、分层分类一下,并补充常见的高级优化策略,方便你在工程中形成体系化设计思考。
🧩 一、Redis 访问优化的总体目标
目标:
减少 Redis 的访问次数、降低单次访问延迟、提高整体吞吐。
可以从三个角度分类来看:
- 访问次数优化(减少请求数)
- 访问并发与批量优化(提升单次吞吐)
- 访问路径优化(减少远程依赖)
🧠 二、访问次数优化(减少 Redis I/O 请求)
核心思路:一次性取更多、减少往返次数
1️⃣ MGET / 批量操作
- 将多个 key 的 GET合并为一次MGET,避免多次 round-trip。
- 
    注意: - MGET适合 key 分布在 同一个节点(单机或同 slot)的情况。
- 在 Cluster 模式 下,如果 key 不同 slot,会拆成多次请求。
 
📈 可优化方向:
- 对 key 做 slot 一致性设计(通过 hash tag:{xxx})。
- 或者使用 multiGet并在底层聚合结果(如 Spring Data Redis 中RedisClusterConnection的实现)。
⚙️ 三、访问并发与批量优化(提升单次吞吐)
核心思路:同一次 I/O 尽量多带数据,或并行请求
2️⃣ Pipeline
- 典型异步批量发送优化: 客户端一次性发送多条命令,不等待每条返回。
- Redis 一次性返回所有结果,极大减少 RTT。
🧩 优缺点:
- 优:高吞吐、批量优化好。
- 缺:结果乱序、编程复杂;每次 pipeline 太大会占内存。
📘 最佳实践:
- 按批次(如每 100~500 条命令)pipeline。
- 结合连接池复用。
3️⃣ 多线程并发请求
- 如果 key 分布在多个 slot,可将不同 slot 的 key 拆分为多个并行任务。
- 在 Cluster 模式下尤其有效。
📘 最佳实践:
- 使用线程池(如 Java 的 CompletableFuture+RedisTemplate)。
- 控制并发数量,避免连接数暴涨。
🧱 四、访问路径优化(本地缓存 / 降级 Redis 依赖)
核心思路:尽量不访问 Redis
4️⃣ JVM 本地缓存
在 Redis 前增加本地缓存层,避免高频访问 Redis。
常见方案:
| 方案 | 说明 | 特点 | 
|---|---|---|
| Guava Cache / Caffeine | 基于内存的本地缓存 | 简单、可控、支持 TTL/LRU | 
| Ehcache / ConcurrentHashMap + TTL | 轻量级内存缓存 | 可定制、线程安全 | 
| 多级缓存架构 | 先本地再 Redis | 减少 Redis QPS,热点保护 | 
📘 设计建议:
- 热点数据(如配置项、权限、热门商品)优先本地缓存。
- 结合 失效同步机制(Redis Pub/Sub、消息队列、版本号)。
5️⃣ 布隆过滤器 / 本地存在性过滤
用于避免访问根本不存在的 key。
📘 常见用途:
- 避免缓存穿透(无效 key 请求直击数据库)
- 可在本地(Guava BloomFilter)或 Redis 层维护(RedisBloom 模块)
⚙️ 本地层策略:
- 请求前先查布隆过滤器或本地 set,过滤不存在 key。
- 如果命中 BloomFilter=false,直接返回,不查 Redis。
6️⃣ KeySet / 热点数据分层缓存
- 将热点 key 缓存在本地 Set / Map。
- 本地缓存维护热 key 状态,冷 key 才访问 Redis。
- 可配合访问计数器做 LRU 热点提升机制。
🔁 五、访问结果的结构化优化(避免重复存取)
核心思路:减少无意义的重复访问
7️⃣ 批量结构化缓存
- 
    将一组逻辑关联的数据合并成一个缓存结构,如: - 用户信息、权限、偏好 → user:{id}:profile
- 热门榜单一页 → 缓存在 top:page:1
 
- 用户信息、权限、偏好 → 
8️⃣ 局部更新策略
- 对于结构化对象,避免整体更新。 通过 hash field 或 json path 更新局部字段。
🪄 六、其他补充优化方向
| 类别 | 优化策略 | 说明 | 
|---|---|---|
| 连接优化 | 连接池(Lettuce / Jedis Pool) | 保持连接复用,避免频繁创建销毁 | 
| 压缩与序列化优化 | 使用 Kryo/FST替代JDK序列化 | 减少网络字节量 | 
| 过期策略 | 统一 TTL + 随机抖动 | 避免缓存雪崩 | 
| 延迟双删 | 更新数据库后延迟删除缓存 | 确保一致性 | 
| 异步预热 | 在应用启动或任务调度中主动加载热点数据 | 提前填充缓存层 | 
| 热点 Key 拆分 | 大流量 key 使用分片前缀(如 rank:1 → rank:1:{a,b,c}) | 降低 Redis 单点压力 | 
🧭 七、体系化架构总结
| 层级 | 目标 | 典型手段 | 
|---|---|---|
| 🧠 应用层 | 减少访问 | 本地缓存、BloomFilter、多级缓存 | 
| ⚙️ 客户端层 | 提升吞吐 | MGET、Pipeline、多线程并发 | 
| 🧱 Redis 结构层 | 提高数据聚合效率 | Hash / ZSet / JSON 结构化 | 
| 📡 网络层 | 减少 RTT | 连接池、异步 I/O | 
| 🔄 数据层 | 保持一致性 | 延迟双删、订阅失效同步 | 
✅ 典型组合方案举例
🧩 场景:高并发读取热点配置项
- 本地缓存(Caffeine)→ 命中率 90%+
- 缺失则走 Redis MGET / Pipeline
- Redis 更新时发布 Pub/Sub 通知客户端清除本地缓存
- 布隆过滤器预防缓存穿透
- Redis 冷热分层(热点 key 提前加载)
