高并发架构下的分布式缓存知识点

一  本文目的

总结在高并发情况下,使用分布式缓存时需要了解的知识点:缓存穿透,缓存雪崩,缓存热点,缓存预热,缓存监控等,本文

不涉及本地缓存,浏览器缓存等其他缓存概念

以下文章阅读约需10min

二 知识点梳理

引子: 缓存作为高频访问且对时效性要求不高的数据访问需求的一种解决方案,在生产中被大量使用,下面总结了一些常见的知识点

1  缓存常见更新策略

数据库和缓存的内容应尽量保持一致,常见的缓存更新策略如下:

  • Lazy模式,只保存一份缓存,获取时优先取缓存,如果获取不到,则从数据库查询, 查询时为避免产生雪崩问题,负责从数据库更新的程序先获取一个分布式锁,并发的其他程序

获取不到锁,可以等待一段时间,或者直接返回空; 这种方式是最常见的使用方式,不过高并发的时候,等待或者返空毕竟不是好的体验,所以有了下面双缓存模式;

  • 双缓存模式,用空间换时间,保留2份缓存,一份永不过期,一份正常的过期时间,当获取正常缓存为空时,则返回永久缓存,同时发起请求db(一样加锁请求),成功后

更新正常的和永久的缓存,这个和Lazy模式相比,在体验上会好一些,但增加了缓存空间的使用量;

  • 定时更新模式, 在前端使用缓存的应用上,根据缓存的过期时间,提前定期更新缓存;这种模式由于定期更新,所以数据即时性上相对差点,为了提高即时性,有了通知模式的改进;
  • 通知模式,当缓存数据发生变化时,同时通过消息中间件,发送通知,通知前端应用进行更新,稍微需要注意的是为保证分区容错性,通常会发送多条通知消息;
  • 双写模式,数据库发生变化时,也同步更新缓存,但由于缓存可能过期(包括cache服务器宕机)所以依然需要配合Lazy模式或者其他缓存丢失时策略一起使用;

2   分布式事务

如果缓存采用双写方式更新,则涉及分布式事务,通常做法是更新数据库时先删除缓存,等更新db成功后,再同步更新新的缓存,这样

不会因为先更新缓存,后更新db失败,导致一致性问题;虽然缓存先被删除,但是因为有其他策略,在访问数据时进行缓存恢复,所以也不用担心影响应用访问;

3  穿透问题

穿透问题指 大量的请求透过缓存,直接访问db,导致db压力变大; 产生的原因和应对策略如下:

a)  由于缓存同时过期导致(生产场景更多的是cache服务器宕机)

可以考虑,对同类的缓存在过期时间上设计为不同的固定过期时间 + 随机时间(一定范围内);

b)  由于缓存未命中导致

应对方案:

  • 缓存key的合法性检查; 比如在服务器被刷时,可能会被攻击而请求一些无效的key,这时候可以做一些key的合法性验证进行过滤;
  • 枚举合法的key; 推荐使用布隆过滤器(Bloomfilter),枚举出常用的合法key,进行校验; 不过通常业务中很难把合理的缓存key都枚举出来;
  • 缓存空值;由于从db中反馈是空值,这时候可以考虑在缓存中保存一些空值,比如空对象,或者空集合,但要根据实际的一致性需求控制好过期时间;

4 雪崩问题

   缓存雪崩指当缓存过期时,由于高并发访问,大量的请求访问到后台数据库查询,导致db系统性能下降,进而导致雪崩的情况;

         避免雪崩问题,其实更多的还是考量缓存的更新策略, 通过分布式锁的方式,来避免并发请求同时请求db生成缓存;

5 缓存预热

缓存预热通常指新系统刚上线,由于缓存中无值,可能导致大量的查询穿透到db,可根据实际业务,考虑是否预加载一部分内容到缓存中;

6 热点问题

比较常见的是热点key触发单点限流,具体指当某个缓存key访问量比较高时,很可能会触发单台或某几台缓存服务器网络流量限流(可监控缓存集群不同服务器的流量来观察),限流导致获取不到缓存

从而请求穿透到db,进而可能引起雪崩;

应对方案: 可考虑用空间换时间, 通过为热点key维护多份相同的缓存, 请求缓存时通过轮询,hash等路由算法,分散请求到不同的缓存服务器;

三  监控指标和告警

上面主要介绍了一些高性能情况下缓存的设计实践,除此之外,我们还需要关注一些缓存的监控指标;

1 缓存的命中率

命中率=命中数/(命中数+没有命中数), 是判断缓存效果好坏的重要指标之一;如命中率过低,则需要考虑 缩短命中率低的缓存的过期时间,减少空间浪费;

2 网络流量

流出流量 = Sum (key1的value值 * QPS + … + keyn的value值 * QPS) ;网络流出量考量的是机房网络环境,交换机上限,如发现流出流量达到瓶颈,应考虑进行

缓存扩容,或者拆分部分到该节点的缓存到其他节点;

3  缓存内存,Swap使用率

监控单台缓存服务器的内存使用量; 内存使用量达到一定告警阀值应提前扩容,同时review代码看是否有,对缓存使用不当的程序,造成了空间使用量激增;

4  QPS

连接数; 连接数和网络流量类似,考量的是单机瓶颈;

5  慢查询

由于Redis中慢查询是阻塞其他访问的,所以定期查看慢查询日志,避免突发的QPS下降;  由大key引起的慢查询,常见的解决方案是,拆分大key,或者为大Key

单独开独立缓存节点,主要思路还是隔离这种访问,避免影响到主业务;

总结,本文介绍了高并发场景下,缓存的常见知识点,希望能为大家在设计解决方案时提供参考;