# 缓存架构设计 **本文引用的文件** - [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) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [ApiPermissionInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java) - [ApiPermissionRule.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionRule.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [application.yml(应用配置)](file://crm-app/src/main/resources/application.yml) - [application.yml(认证模块配置)](file://crm-auth/src/main/resources/application.yml) ## 更新摘要 **所做更改** - 新增Caffeine进程内缓存层,用于API权限规则的高效访问 - 集成ApiPermissionCache组件,支持懒加载和手动失效机制 - 更新缓存架构图,展示多级缓存策略(进程内 + 分布式) - 增强性能优化章节,包含本地缓存与分布式缓存的协同策略 ## 目录 1. [引言](#引言) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量与调优](#性能考量与调优) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 引言 本文件面向CRM系统的缓存架构设计与优化,聚焦以下目标: - 基于Redis的分布式缓存策略与会话管理 - Caffeine进程内缓存与多级缓存架构 - 部门树缓存与API权限规则的缓存实现 - Redis连接池、序列化策略与过期时间管理 - 令牌存储方案与数据一致性保障 - 缓存穿透防护、热点数据优化与监控指标 - 为性能优化工程师与系统管理员提供调优与排障指南 ## 项目结构 本项目采用多模块组织,缓存相关能力分布在基础模块与认证模块: - crm-base:通用基础设施,包含Redis配置、工具类、异常处理等 - crm-auth:认证与权限域,包含令牌服务、部门树缓存、API权限缓存、安全过滤器等 - crm-app:应用入口与全局配置 - crm-file:文件服务(与缓存主题关联度较低) ```mermaid graph TB subgraph "应用层" APP["crm-app
应用启动与全局配置"] end subgraph "业务域" AUTH["crm-auth
认证与权限
TokenService / DeptTreeCache / ApiPermissionCache"] FILE["crm-file
文件服务"] end subgraph "基础能力" BASE["crm-base
RedisConfig / 工具 / 异常"] end subgraph "外部依赖" REDIS["Redis 集群/单机"] DB["MySQL 数据库"] CAFFEINE["Caffeine 进程内缓存"] end APP --> AUTH APP --> FILE AUTH --> BASE FILE --> BASE AUTH --> REDIS AUTH --> CAFFEINE AUTH --> DB FILE --> 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) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) ## 核心组件 - **RedisConfig**:统一配置Redis连接池、序列化器、Key/Value序列化策略、默认过期时间、是否启用缓存开关等 - **DeptTreeCache**:部门树结构的Caffeine进程内缓存封装,提供读取、构建、刷新、失效等操作 - **ApiPermissionCache**:API权限规则的Caffeine进程内缓存,支持懒加载和手动失效机制 - **TokenService**:用户登录态与令牌生命周期管理,结合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) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) ## 架构总览 整体缓存架构围绕"多级缓存 + 分布式缓存 + 令牌服务"展开,形成进程内缓存优先、分布式缓存兜底的多级缓存体系。 ```mermaid graph TB Client["客户端/网关"] --> API["API 控制器"] API --> AuthSvc["认证服务/权限校验"] AuthSvc --> ApiPermCache["ApiPermissionCache
Caffeine进程内缓存"] AuthSvc --> DeptCache["DeptTreeCache
Caffeine进程内缓存"] AuthSvc --> TokenSrv["TokenService
令牌存取/续期/注销"] ApiPermCache --> DB["MySQL数据库"] DeptCache --> DB TokenSrv --> Redis["Redis"] API --> BaseCfg["RedisConfig
连接池/序列化/TTL"] ``` **图表来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [DeptTreeCache.java](file://crm-auth/src/main/java/com/crm/auth/service/DeptTreeCache.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) ## 详细组件分析 ### RedisConfig:连接池、序列化与过期时间 职责与要点 - 连接池参数:最大连接数、最小空闲、最大等待时间、超时等,影响吞吐与延迟 - 序列化策略:Key/Value序列化器选择,避免跨语言或版本兼容问题 - 默认过期时间:为无明确TTL的键设置保护性过期,降低内存泄漏风险 - 缓存开关:便于灰度与回滚控制 关键配置项建议 - 连接池:根据实例规格与QPS预估调整maxTotal/maxIdle/minIdle - 序列化:优先使用JSON或Kryo;Key需短小稳定,避免大对象 - 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) ### DeptTreeCache:部门树进程内缓存与更新机制 职责与要点 - 读路径:优先从Caffeine缓存获取部门树邻接表,未命中则回源数据库并回填缓存 - 写路径:部门变更时主动失效对应缓存,保证后续读取一致性 - 数据结构:以Map>形式存储父部门到子部门的映射关系 - 并发安全:Caffeine内部保证线程安全的懒加载 更新流程图 ```mermaid flowchart TD Start(["请求进入"]) --> CheckCache["检查Caffeine中是否存在部门树"] CheckCache --> |存在| ReturnCache["返回缓存结果"] CheckCache --> |不存在| BuildTree["构建部门树邻接表"] BuildTree --> SaveCache["写入Caffeine缓存"] SaveCache --> ReturnCache ReturnCache --> 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) ### ApiPermissionCache:API权限规则进程内缓存 **新增** Caffeine-based的API权限规则缓存组件,提供高性能的动态权限匹配能力。 职责与要点 - 懒加载机制:首次访问时从数据库加载所有启用的API权限规则 - 全量缓存:单key缓存整个规则列表,避免频繁查询 - 手动失效:资源树变更时主动调用invalidate()方法清空缓存 - 规则格式:将SysMenu中的button节点转换为ApiPermissionRule记录 核心特性 - **懒加载**:通过Caffeine的get(key, mappingFunction)实现按需加载 - **线程安全**:Caffeine内部保证并发访问的安全性 - **低开销**:进程内缓存,无网络IO开销 - **易失效**:提供简单的invalidate()方法进行缓存清理 ```mermaid sequenceDiagram participant Client as "客户端" participant Interceptor as "ApiPermissionInterceptor" participant Cache as "ApiPermissionCache" participant DB as "MySQL" Client->>Interceptor : "HTTP请求" Interceptor->>Cache : "getRules()" Cache->>Cache : "检查Caffeine缓存" alt 缓存命中 Cache-->>Interceptor : "返回规则列表" else 缓存未命中 Cache->>DB : "查询启用的API权限规则" DB-->>Cache : "返回规则数据" Cache->>Cache : "构建规则列表并缓存" Cache-->>Interceptor : "返回规则列表" end Interceptor->>Interceptor : "匹配URL并校验权限" Interceptor-->>Client : "返回响应" ``` **图表来源** - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [ApiPermissionInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java) **章节来源** - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [ApiPermissionRule.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionRule.java) ### TokenService:令牌存储与分布式会话 职责与要点 - 令牌生成:唯一ID、签发时间、过期时间、用户标识、设备信息等 - 存储结构:以Hash或String形式存储用户会话,支持快速查询与续期 - 过期策略:滑动过期或固定过期,结合定时任务清理过期会话 - 注销与黑名单:登出时删除或加入黑名单,防止重放攻击 序列图(登录到鉴权) ```mermaid sequenceDiagram participant C as "客户端" participant A as "认证控制器" participant T as "TokenService" participant R as "Redis" C->>A : "提交用户名/密码" A->>T : "验证并签发令牌" T->>R : "存储会话(含TTL)" R-->>T : "写入成功" T-->>A : "返回令牌" A-->>C : "响应令牌" Note over C,R : "后续请求携带令牌,服务端校验并续期" ``` **图表来源** - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) **章节来源** - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) ## 依赖关系分析 - RedisConfig被各模块共享,作为统一的Redis接入点 - DeptTreeCache和ApiPermissionCache都依赖Caffeine进行进程内缓存 - ResourceServiceImpl在资源树变更时触发ApiPermissionCache失效 - TokenService依赖Redis进行会话与令牌管理 - 认证流程同时依赖多种缓存,形成"进程内缓存 + 分布式缓存"的双通道 ```mermaid classDiagram class RedisConfig { +连接池配置 +序列化器配置 +默认TTL +缓存开关 } class DeptTreeCache { +expandWithChildren(deptIds) +invalidate() } class ApiPermissionCache { +getRules() +invalidate() } class ApiPermissionInterceptor { +preHandle(request, response, handler) } class TokenService { +createToken(user) +validateToken(token) +refreshToken(token) +logout(token) } class ResourceServiceImpl { +save(node) +delete(id) } DeptTreeCache --> RedisConfig : "使用" ApiPermissionCache --> RedisConfig : "使用" ApiPermissionInterceptor --> ApiPermissionCache : "依赖" TokenService --> RedisConfig : "使用" ResourceServiceImpl --> ApiPermissionCache : "触发失效" ``` **图表来源** - [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) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [ApiPermissionInterceptor.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionInterceptor.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) **章节来源** - [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) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) ## 性能考量与调优 - **多级缓存策略** - 第一级:Caffeine进程内缓存,零网络开销,适合高频访问的规则数据 - 第二级:Redis分布式缓存,适合会话管理和部门树等大对象 - 第三级:MySQL数据库,最终数据源 - **连接池调优** - maxTotal:根据CPU核数与网络带宽估算,通常不超过线程池上限 - minIdle:保持一定空闲连接,减少冷启动抖动 - maxWaitMillis:避免排队过长导致超时 - **Caffeine缓存优化** - 配置合适的最大容量和过期策略 - 利用懒加载机制减少不必要的初始化开销 - 合理使用invalidate()方法确保数据一致性 - **序列化优化** - Key尽量短且稳定,避免拼接过长字符串 - Value避免大对象,必要时分片或压缩 - 选择合适的序列化器,权衡CPU与体积 - **TTL与过期** - 热点数据设置较长TTL,配合逻辑过期与后台刷新 - 非热点数据设置较短TTL,降低内存占用 - 进程内缓存无需TTL,通过手动失效控制 - **热点数据优化** - 本地缓存(如Caffeine)+ 二级缓存(Redis) - 预加载与预热,避免突发流量击穿 - 异步加载与降级策略 - **监控指标** - 命中率、平均延迟、P99/P999延迟、错误率 - Redis连接池使用率、活跃连接数、阻塞队列长度 - Caffeine缓存命中率、内存使用情况 - 内存使用量、碎片率、慢查询数量 ## 故障排查指南 常见问题与定位步骤 - **连接池耗尽** - 现象:大量超时、连接拒绝 - 排查:查看连接池指标、慢查询、长事务 - 处置:扩容连接池、缩短请求耗时、增加重试退避 - **Caffeine缓存问题** - 现象:权限规则不生效、缓存不一致 - 排查:检查invalidate()调用时机、缓存容量限制 - 处置:确认资源树变更时正确触发失效、调整缓存配置 - **序列化异常** - 现象:反序列化失败、类型不匹配 - 排查:检查Key/Value格式、版本兼容性 - 处置:统一序列化器、迁移历史数据 - **缓存不一致** - 现象:读不到最新数据、脏读 - 排查:确认写后失效策略、分布式锁是否生效 - 处置:加强失效粒度、引入版本号或双写校验 - **令牌失效异常** - 现象:频繁登出、会话丢失 - 排查:检查TTL、续期逻辑、时钟同步 - 处置:修正TTL、完善续期策略、对齐服务器时间 **章节来源** - [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) - [ApiPermissionCache.java](file://crm-auth/src/main/java/com/crm/auth/security/ApiPermissionCache.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) ## 结论 本缓存架构以多级缓存为核心,通过Caffeine进程内缓存和Redis分布式缓存协同工作,满足高并发与一致性的基本要求。新增的ApiPermissionCache组件显著提升了API权限校验的性能,减少了数据库访问压力。建议在上线前完成容量规划与压测,建立完善的监控告警体系,并在变更时遵循"先扩后缩、灰度发布"的原则,确保稳定性与可观测性。 ## 附录 - **术语说明** - TTL:生存时间(Time To Live) - P99/P999:延迟分布的分位指标 - 击穿/穿透/雪崩:缓存常见异常模式 - Caffeine:高性能Java缓存库 - 懒加载:按需加载数据的策略 - **参考实践** - 热点数据多级缓存 - 分布式锁与防抖 - 令牌滑动续期与黑名单 - 进程内缓存与分布式缓存协同 - **技术栈** - Caffeine:进程内缓存,支持懒加载和自动淘汰 - Redis:分布式缓存,支持持久化和集群 - Spring Security:权限框架,与拦截器集成 - MyBatis Plus:ORM框架,提供高效的数据库操作