为什么缓存会出现「只读 L1、不读写 Redis」的情况
读 MultiLevelCache#isL1Only 源码时容易疑惑:普通缓存只有「L1+L2 双层」和「仅 L2」(纯 Redis 模式)两种形态,为什么还存在「仅 L1」?
这不是普通缓存的常规形态,而是敏感缓存的安全降级保护。当缓存名命中敏感名单(secure: 前缀或 secureNames 配置)、且平台数据加密未启用时,敏感数据被禁止明文写入 Redis,此时:
- 写侧:仅写 L1 本机内存,不写 Redis;
- 读侧:连 L2 也不查,直接穿透到方法重新加载。
读侧跳过 L2 是 fail-safe 设计——Redis 里可能存在三类脏数据:①曾启用加密后关闭残留的密文(当前无法解密);②加密启用前明文写入的历史数据(无保护);③多节点密钥版本不一致的密文(解密失败)。宁可穿透重查,也不能把不对的数据当缓存值返回。
完整的缓存行为矩阵:
| 缓存类型 | 条件 | 读行为 |
|---|---|---|
| 普通缓存 | enabled=true, l1.enabled=true | L1 → L2 |
| 普通缓存 | enabled=true, l1.enabled=false | 仅 L2(纯 Redis 模式) |
| 普通缓存 | enabled=false | NoOp 穿透 |
| 敏感缓存 | 数据加密已启用 | L1 → L2(L2 整包 AES-GCM 加密) |
| 敏感缓存 | 数据加密未启用 | 仅 L1(本条目,安全降级) |
| 敏感缓存 | 加密未启用 + l1.enabled=false | 完全穿透(实质不缓存) |
一旦启用数据加密,敏感缓存即自动恢复 L1+L2 双层形态(仅 L2 value 为密文)。应用启动时若命中该降级分支,日志会输出 WARN「敏感缓存因未启用数据加密,仅使用 L1 本地缓存,不写 Redis」提示。
敏感缓存名单与数据加密的配置方式见配置说明 - 缓存配置与数据加密。