- 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]>
49 lines
2.0 KiB
Markdown
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 不可用时的过渡。 |