缓存组件核心是保证一致性、可控性、可观测性;需以接口抽象行为,组合TTL/TTI/主动失效/刷新机制,并内置穿透、击穿、雪崩防护,暴露统计、手动操作、加载器及序列化扩展能力。
缓存不是简单地把数据存进Map,关键在于**一致性、可控性、可观测性**。Java中封装缓存组件,首先要明确:缓存是业务的加速器,不是数据源。因此组件必须能清晰区分「加载」「命中」「失效」「异常」等状态,避免脏读或雪崩。推荐以接口抽象缓存行为(如Cache),底层可插拔支持Caffeine、Redis或本地ConcurrentHashMap,但对外暴露统一语义。
缓存失效不能只靠过期时间,需组合使用多种策略应对不同业务需求:
expireAfterWrite(10, TimeUnit.MINUTES)即可;注意避免所有缓存同时过期,可加随机偏移(如±30秒)expireAfterAccess(30, TimeUnit.MINUTES),但需警惕“假活跃”导致不释放invalidate(key)或invalidateAll(keys)。这是强一致性的基础,尤其在DB更新后必须同步清理缓存refreshAfterWrite可在后台异步重建值,避免请求阻塞,适合读多写少且允许短暂陈旧的场景(如商品详情页)这三类问题本质都是缓存未起到分流作用,需在组件层内置防护:
一个可维护的缓存组件,至少要提供以下能力供业务方控制和诊断:
getHitCount()、getMissCount()、getLoadExceptionCount(),便于监控命中率与异常趋势put(key, value)、invalidate(key)、cleanAll(),方便测试、灰度或紧急干预CacheLoader统一定义数据来源,支持同步/异步加载,并可透传上下文(如traceId)用于链路追踪