2021-11-13 10:40:16
缓存穿透
定义:当大量请求查询的key在缓存和数据库中均不存在时,这些请求会直接穿透缓存层,全部落到数据库上,可能导致数据库压力骤增甚至崩溃。
典型场景:黑客恶意构造不存在的key(如负数ID)发起攻击,或业务中存在大量冷门数据查询。
解决方案:
1. 参数校验:对请求参数进行合法性校验(如ID不能为负数、邮箱格式验证),直接拦截非法请求。
2. 空值缓存:若缓存和数据库均未命中,将key写入缓存并设置value为null,同时设置较短过期时间,避免重复查询数据库。
3. 布隆过滤器:将所有可能存在的key预先存入布隆过滤器,请求到来时先判断key是否存在于过滤器中,不存在则直接拦截。布隆过滤器通过哈希函数和位图实现高效查询,但存在一定误判率(需权衡性能与准确性)。
缓存雪崩
定义:大量缓存key在同一时间失效,导致后续请求全部落到数据库,引发数据库瞬间过载甚至崩溃。
典型场景:缓存设置相同的过期时间(如电商首页所有key在零点同时失效),或Redis集群宕机导致缓存不可用。
解决方案:
1. 随机化过期时间:为每个key设置不同的过期时间(如基础时间+随机值),避免集中失效。
2. 热点数据分散:在Redis集群中,将热点数据均匀分布到不同节点,降低单点压力。
3. 高可用与降级:
事前:确保Redis集群高可用(如哨兵模式、集群模式),选择合适的内存淘汰策略(如LRU)。
事中:引入本地缓存(如Ehcache)和限流组件(如Hystrix),避免数据库崩溃。
事后:利用Redis持久化机制(RDB/AOF)快速恢复数据。
缓存击穿
定义:单个热点key在失效瞬间,大量并发请求直接穿透缓存,全部落到数据库上。
典型场景:明星新闻、秒杀活动等高并发场景下,某个key被频繁访问,但因过期或更新导致缓存失效。
解决方案:
1. 互斥锁:在更新缓存前加锁,确保同一时间只有一个请求能操作数据库和缓存,但会降低吞吐量。
2. 逻辑过期:缓存中存储数据的过期时间(而非直接删除),查询时若发现过期,则异步更新缓存,避免阻塞主线程。
缓存一致性
定义:缓存与数据库中的数据在更新时保持一致,避免因操作顺序或并发导致数据不一致。
解决方案:
1. 最终一致性策略:
先删缓存再更新数据库:若数据库更新失败,缓存为空,后续请求会从数据库重新加载数据。
2. 串行化操作:通过消息队列(如Kafka)将更新操作串行化,确保删除缓存和更新数据库的顺序性,但会降低性能。
3. 避免强一致性:若业务要求强一致性,建议直接操作数据库,不使用缓存,因缓存的分布式特性难以保证强一致性。