# 缓存策略 **本文引用的文件** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件围绕CRM后端项目的缓存策略进行系统化说明,重点覆盖: - Redis缓存配置与使用(连接池、序列化、集群模式) - 常见缓存设计模式(Cache-Aside、Read-Through、Write-Through)的适用场景与实现要点 - 以 DeptTreeCache 为例,展示树形结构数据的缓存优化方案 - 缓存一致性保障(更新删除、失效时间、分布式锁等) - 缓存监控、性能调优与故障恢复最佳实践 ## 项目结构 本项目采用多模块组织,缓存相关能力主要分布在基础模块与认证模块中: - crm-base:提供通用配置与工具,包含 Redis 配置类 - crm-auth:业务服务,包含部门树缓存实现与调用方 ```mermaid graph TB subgraph "应用层" APP["CrmAppApplication"] AUTH_APP["AuthApplication"] end subgraph "基础模块 crm-base" REDIS_CFG["RedisConfig
Redis连接/序列化/集群配置"] end subgraph "认证模块 crm-auth" DEPT_CACHE["DeptTreeCache
部门树缓存封装"] DEPT_SVC["SysDeptServiceImpl
部门服务实现"] end subgraph "外部依赖" REDIS["Redis 服务器/集群"] DB["数据库(MyBatis-Plus)"] end APP --> AUTH_APP AUTH_APP --> DEPT_SVC DEPT_SVC --> DEPT_CACHE DEPT_CACHE --> REDIS DEPT_SVC --> DB REDIS_CFG -.-> DEPT_CACHE ``` **图示来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml) **章节来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml) ## 核心组件 - RedisConfig:集中管理Redis连接、序列化、超时、集群等关键参数,为上层缓存组件提供统一访问能力。 - DeptTreeCache:面向部门树的专用缓存封装,提供读路径优先、按需加载、批量构建与失效控制。 - SysDeptServiceImpl:部门数据服务,负责在写操作后触发缓存失效或重建,保证读写一致性。 **章节来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) ## 架构总览 下图展示了“服务-缓存-存储”的整体交互流程,以及不同缓存模式下的数据流向。 ```mermaid sequenceDiagram participant Client as "客户端" participant Service as "SysDeptServiceImpl" participant Cache as "DeptTreeCache" participant Redis as "Redis" participant DB as "数据库" Note over Client,Service : "读路径(示例)" Client->>Service : "查询部门树" Service->>Cache : "getTree()" alt "命中缓存" Cache-->>Service : "返回树节点" Service-->>Client : "返回结果" else "未命中" Cache->>DB : "加载根节点/全量数据" DB-->>Cache : "原始数据" Cache->>Redis : "序列化并写入" Redis-->>Cache : "OK" Cache-->>Service : "返回树节点" Service-->>Client : "返回结果" end Note over Client,Service : "写路径(示例)" Client->>Service : "修改部门信息" Service->>DB : "持久化变更" Service->>Cache : "invalidate()/refresh()" Cache->>Redis : "删除/更新键" Redis-->>Cache : "OK" Service-->>Client : "返回成功" ``` **图示来源** - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) ## 详细组件分析 ### Redis 配置与使用 - 连接池与超时:通过连接池参数控制最大连接数、空闲连接、获取超时等,避免连接耗尽与阻塞。 - 序列化策略:建议统一使用JSON序列化,确保跨语言兼容与可读性;对热点对象可考虑二进制压缩以提升吞吐。 - 集群模式:支持单机、哨兵与集群三种部署形态,需根据容量与可用性选择;集群模式下注意Key哈希槽分布与跨槽事务限制。 - Key命名规范:按“模块:实体:维度”分层,便于定位与批量清理;树形结构可采用“dept:tree:root”作为根键。 - 过期与淘汰:设置合理TTL并结合业务生命周期;热点数据可延长TTL,冷数据缩短TTL。 **章节来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [application.yml](file://crm-auth/src/main/resources/application.yml) ### 缓存设计模式 - Cache-Aside(旁路缓存) - 适用场景:读多写少、允许短暂不一致、快速上线 - 实现要点:读时先查缓存,未命中再查库并回填;写时先更新库,再删除缓存 - 风险点:并发写导致脏读,可通过分布式锁或版本号解决 - Read-Through(读穿透) - 适用场景:希望缓存层透明化,简化调用方逻辑 - 实现要点:缓存代理在缺失时自动从数据源加载并回填 - 风险点:数据源异常影响读取链路,需要降级与熔断 - Write-Through(写穿透) - 适用场景:强一致要求高、写路径可控 - 实现要点:写时同步更新缓存与数据源,失败回滚 - 风险点:写延迟增加,需评估吞吐与一致性权衡 [本节为概念性内容,不直接分析具体文件] ### 树形结构缓存优化:DeptTreeCache - 目标:将部门树结构整体缓存,减少重复组装与DB查询压力 - 数据结构:以根节点为键,子节点列表递归构建;必要时拆分“根键+子键集合”提升局部刷新效率 - 读路径:优先命中缓存,未命中则从DB加载并按层级拼装,最后落盘 - 写路径:部门增删改后,删除根键或局部子键,下次读时懒加载重建 - 并发控制:首次加载时使用分布式锁防击穿;热点更新使用短锁或版本号防雪崩 - 失效策略:基于事件驱动(写操作发布失效消息)或定时任务校验一致性 ```mermaid flowchart TD Start(["进入 getTree"]) --> CheckCache["检查根键是否存在"] CheckCache --> |存在| ReturnCache["返回缓存树"] CheckCache --> |不存在| AcquireLock["尝试获取分布式锁"] AcquireLock --> LockOk{"是否获得锁"} LockOk --> |否| Fallback["等待或降级返回空/旧值"] LockOk --> |是| LoadFromDB["从数据库加载部门数据"] LoadFromDB --> BuildTree["构建部门树结构"] BuildTree --> SaveCache["序列化并写入Redis"] SaveCache --> ReleaseLock["释放分布式锁"] ReleaseLock --> ReturnResult["返回树结构"] Fallback --> End(["结束"]) ReturnCache --> End ReturnResult --> End ``` **图示来源** - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) **章节来源** - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) ### 服务层集成:SysDeptServiceImpl - 读接口:委托 DeptTreeCache 获取树结构,屏蔽底层细节 - 写接口:在完成数据库变更后,调用缓存失效或刷新方法,确保后续读路径能拿到最新数据 - 事务边界:写操作与缓存失效在同一事务内协调,避免中间态暴露 ```mermaid sequenceDiagram participant Client as "客户端" participant Service as "SysDeptServiceImpl" participant DB as "数据库" participant Cache as "DeptTreeCache" participant Redis as "Redis" Client->>Service : "更新部门信息" Service->>DB : "执行更新" DB-->>Service : "返回成功" Service->>Cache : "invalidateRoot()" Cache->>Redis : "删除根键" Redis-->>Cache : "OK" Service-->>Client : "返回成功" ``` **图示来源** - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) **章节来源** - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) ## 依赖关系分析 - 模块耦合 - DeptTreeCache 依赖 RedisConfig 提供的RedisTemplate/ConnectionFactory - SysDeptServiceImpl 依赖 DeptTreeCache 与 MyBatis-Plus 数据访问层 - 外部依赖 - Redis:承担热点数据缓存与共享状态 - 数据库:权威数据源,缓存仅作为加速层 ```mermaid graph LR Svc["SysDeptServiceImpl"] --> Cache["DeptTreeCache"] Cache --> RedisCfg["RedisConfig"] Cache --> RedisNode["Redis"] Svc --> DB["数据库"] ``` **图示来源** - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) **章节来源** - [SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) ## 性能考虑 - 连接池调优 - 根据QPS与RT估算连接数,避免过大导致内存占用过高 - 调整获取连接超时,防止线程堆积 - 序列化优化 - 热点对象使用紧凑格式(如Protobuf/Kryo),非热点使用JSON - 大对象分片存储,避免单次序列化开销过大 - 缓存粒度 - 树形结构可按层级拆分键,提高局部更新效率 - 热点键打散,避免单键过大 - 过期与预热 - 启动时预热常用树结构,降低冷启动冲击 - 动态TTL结合访问频率调整 - 集群与分片 - 关注Key哈希分布,避免热点槽 - 跨槽操作尽量规避,必要时拆分为多次请求 [本节为通用指导,不直接分析具体文件] ## 故障排查指南 - 常见问题 - 缓存穿透:空值缓存+布隆过滤器限流 - 缓存击穿:分布式锁保护首次加载 - 缓存雪崩:随机TTL+多级缓存 - 数据不一致:写后删/版本号/双写一致性校验 - 监控指标 - 命中率、平均RT、P99/P95、错误率、连接池使用率 - Redis内存、CPU、网络IO、慢查询日志 - 恢复策略 - 快速降级:关闭缓存直连DB - 灰度发布:逐步放量新缓存策略 - 回滚机制:保留旧版本键与快照 [本节为通用指导,不直接分析具体文件] ## 结论 - 通过统一的Redis配置与规范的Key设计,奠定稳定高效的缓存基础 - 选择合适的缓存模式(Cache-Aside为主,必要时引入Read/Write-Through)平衡一致性与性能 - 针对树形结构采用专用缓存封装,显著提升读性能与可维护性 - 完善的一致性策略与监控体系,保障系统在高可用与高性能之间取得平衡 [本节为总结性内容,不直接分析具体文件] ## 附录 - 配置清单建议 - 连接池:最大连接数、空闲超时、获取超时 - 序列化:默认JSON,热点对象可选二进制 - 集群:节点地址、密码、超时、重试策略 - Key前缀:模块:实体:维度 - TTL:按业务设定,热点适当延长 - 代码片段路径 - Redis配置入口:[RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - 树缓存封装:[DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - 服务集成点:[SysDeptServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/SysDeptServiceImpl.java) - 应用配置:[application.yml](file://crm-app/src/main/resources/application.yml), [application.yml](file://crm-auth/src/main/resources/application.yml)