qinghuan
← 缓存的操作与结果目录

SPRING CACHE / 补充讲义 1 / 7

缓存读取降级与写入失败的分段验收

区分缓存提供者读取、写入和业务加载失败,比较普通与同步模式的错误回调。

缓存读取失败时,先确认失败发生在哪一步:没有条目、缓存服务不可用、业务查询异常,应该对应不同的处理结果。完成缓存键与同键加载后,可以用本节把故障位置与最终响应逐一对应起来。

资料基于 Spring Framework 7.0.10。原始核查:2026 年 10 月 23 日;发布整理复核:2026 年 10 月 30 日 JST。以下是验收设计,尚未运行 Java、Redis 或数据库故障实验。既有配套实验使用 6.2.11;应用到项目之前仍需核对锁定版本。

默认异常处理不会自动降级

CacheErrorHandler 处理缓存提供者在读取、写入、删除和清空等操作中抛出的异常。默认 SimpleCacheErrorHandler 会继续抛出异常。把缓存读取故障当作一次未命中,需要显式选择错误处理策略;它不是缓存注解自动提供的业务兜底。错误处理器契约与默认处理器说明了这一范围。

普通 @Cacheable 的读取与写入是不同步骤。读取异常被处理后,业务方法可能继续执行,随后写缓存仍可能失败,并交给 handleCachePutError。因此,“吸收 get 异常”不能推出“调用一定成功”。

sync=true 使用合并的读取加载步骤。初次缓存访问失败后,即使通过错误处理继续加载,也没有另一轮独立的 put 尝试。两种模式不能套用相同的回调计数预期。这一差别也写在固定版本的 CacheErrorHandler 源码注释中。

练习一:只处理读取异常,调用是否一定成功

建立可分别注入 get 和 put 故障的测试 Cache,包装一个返回虚构商户 1001 的只读方法。方法进入时增加加载计数。通过 Spring 代理调用,每组使用全新缓存与计数。

  1. 保持默认错误处理器,分别注入读取故障、写入故障,记录调用方看到的结果。
  2. 配置仅吸收 get 故障的测试处理器,先让 put 正常,再让 put 失败。
  3. 对每次调用记录故障位置、错误回调顺序、业务加载次数和最终响应。

验收时同时回答两件事:业务方法有没有被调用,调用方有没有成功获得结果。缓存故障不能被翻译为“商户不存在”;业务确实无结果也不能被写成缓存服务异常。

练习二:比较普通模式与合并加载模式

对照 sync=false 与 sync=true,给普通 get(key) 和合并的 get(key, Callable) 路径分别设置访问故障。先根据固定版本契约写出预期,再运行并核对回调序列。

保留两组不同反例:缓存提供者访问抛错,以及业务加载器本身抛错。每组提交缓存提供者与版本、故障注入点、加载次数、错误回调和最终响应;不能只提交“没有异常”的截图。异步返回类型另读本组的完成值与流式边界章节。

降级需要容量与一致性策略

吸收缓存异常会把原本可能命中的请求送往后端,需要考虑数据库容量与请求预算。删除或清空失败可能让旧条目继续存在,也不应直接复用读取降级策略。授权失败、数据库异常和业务不存在不属于缓存错误处理器的统一兜底范围。

本节增加的是缓存提供者故障及处理器分段契约;旧读回填和故障恢复继续使用缓存补充实验。这些设计没有提供吞吐、时延或 Redis 故障恢复的实测结论。

补充来源:缓存注解指南、固定版本默认错误处理器源码。指南为滚动页面;独立发布日期未标明。