Files
java21-template/docs/adr/0005-cache-error-handler.md
Bruno GaoandQwen-Coder 2fd1eb59ab docs: Complete production-grade documentation set
- Create SECURITY.md with vulnerability disclosure policy
- Create docs/README.md as documentation index page
- Create docs/observability.md with metrics/logs/traces/alerting/SLO specs
- Create docs/runbook.md with troubleshooting scenarios (RB-01 to RB-05)
- Create docs/security.md with security design and compliance
- Create docs/release.md with versioning and rollback strategies
- Create docs/database.md with database design and migration strategy
- Create docs/adr/0005-cache-error-handler.md for cache error handling ADR
- Update README.md with documentation index section
- Update docs/architecture.md to update B-7 rule and add trust boundary section
- Create docs/api-guide.md with API specifications
- Fix method names in OrderDao.java to match OrderMapper interface
- Add Spring Boot Actuator dependency to tmpl-infrastructure
- Fix Redis ping method in RedisHealthContributor.java
- Fix syntax errors and method names in OrderAppService.java

Co-authored-by: Qwen-Coder <[email protected]>
2026-02-12 21:47:33 +08:00

2.0 KiB

ADR-0005: 缓存异常容错策略

状态: 已采纳 日期: 2026-02-12 决策者: 模板维护团队

上下文

tmpl-api 通过 @Cacheable / @CacheEvict 使用 Redis 缓存。当 Redis 不可用时, Spring 默认的 SimpleCacheErrorHandler 会将异常直接抛出给调用方,导致本应正常的 数据库查询也返回 500 错误。这对服务可用性造成不可接受的影响。

决策驱动因素

  • 缓存是可选的性能优化,不应成为服务可用性的瓶颈。
  • 运维团队需要在日志中看到缓存异常的完整堆栈以便排查。
  • GracefulCacheErrorHandler 应与 app.cache.enabled 属性开关联动。
  • ArchUnit A-3 规则要求 Application 层不直接依赖 Infrastructure 实现。

考虑的方案

方案 A — 自定义 CacheErrorHandler(已采纳) 实现 CachingConfigurer 接口,注册 GracefulCacheErrorHandler,在 handleCacheGetError / handleCachePutError / handleCacheEvictError / handleCacheClearError 中记录 WARN 日志(含完整堆栈)并吞掉异常。

方案 B — Resilience4j CircuitBreaker 包裹缓存调用 为 Redis 调用添加断路器,在失败率达到阈值时自动打开。

方案 C — 不处理,缓存失败即服务失败 保持默认 SimpleCacheErrorHandler。

决策

采纳方案 A。方案 B 增加了额外依赖和复杂度,可在后续迭代中作为增强引入(可与方案 A 共存)。 方案 C 不可接受,因为它让可选组件的故障影响核心功能。

后果

正面:Redis 不可用时服务自动降级为直接查询数据库,对终端用户透明;运维可通过 WARN 日志和 redisPing HealthIndicator 感知异常并修复。

负面:降级期间数据库负载会上升;若数据库也接近瓶颈则服务仍可能受影响。

后续行动

  • 在 Grafana Dashboard 中为 cache_gets_total{result="miss"} 创建告警。
  • 评估 Resilience4j CircuitBreaker 作为方案 B 的补充。
  • 考虑本地 Caffeine 二级缓存作为 Redis 不可用时的过渡。