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

49 lines
2.0 KiB
Markdown

# 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 不可用时的过渡。