分布式系统架构8:分布式缓存

这是小卷对分布式系统架构学习的第11篇文章,今天了解分布式缓存的理论知识以及Redis集群。

分布式缓存也是面试常见的问题,通常面试官会问为什么要用缓存,以及用的Redis是哪种模式,用的过程中遇到哪些问题这些

1. AP还是CP

Redis 集群就是典型的 AP 式,它具有高性能、高可用等特点,但它却并不保证强一致性。

而能够保证强一致性的 ZooKeeper、Doozerd、Etcd 等框架,吞吐量比不过Redis,通常不会用作"缓存框架",而是作为通知、协调、队列、分布式锁等使用

2.透明多级缓存TMC

实际开发中,同时搭配进程内缓存和分布式缓存,来构成透明多级缓存(Transparent Multilevel Cache,TMC)

多级缓存的查询过程如下图:

缺点:代码侵入性大,由开发人员维护管理

一、二级缓存数据不一致问题解决:

  • 设计原则:变更以分布式缓存中的数据为准,查询以进程内缓存数据优先

3.实现方案

3.1 memcached缓存

在服务端,memcached集群环境实际就是一个个memcached服务器的堆积

cache的分布式主要是在客户端实现,通过客户端的路由处理来达到分布式解决方案的目的。客户端做路由的原理,是在每次存取某key的value时,通过一致性哈希算法把key映射到某台memcached服务器node上。

如下是memcached客户端路由过程:

3.2 Redis缓存

与memcached客户端支持分布式方案不同,Redis更倾向于在服务端构建分布式存储

  • 以Redis集群模式为例,它没有中心节点,具有线性可伸缩的功能。

  • 节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信

  • 在数据的放置策略上,Redis Cluster将整个key的数值域分成2的14次方16384个hash槽,每个节点上可以存储一个或多个hash槽,也就是说当前Redis Cluster支持的最大节点数就是16384

  • 总结下:数据hash分布在不同redis节点实例,主/从切换采用Sentinel

  • 写:只会写master Instance,从sentinel获取当前的master instance;

  • 读:从redis node中基于权重选取一个实例读取,失败/超时则轮询其他实例;

要想详细了解redis的面试过程中的问题,可以参考下面的思维导图自行整理:

4. 缓存风险

4.1 缓存穿透

缓存风险问题也是面试常考的八股文题目,这里还是简单说明下

缓存穿透 :查询的数据在数据库里根本不存在,缓存里也不会有,这样的请求每次都不会命中缓存,会请求到末端数据库。这种查询不存在数据的现象就是缓存穿透

解决办法:

  • 对业务逻辑本身不能避免的缓存穿透:对返回为空的Key值进行缓存,如果数据库中对该key插入新记录,就需要主动清理缓存的key值。
  • 恶意攻击导致的缓存穿透:缓存之前设置一个布隆过滤器来解决,思路就是判断请求的数据是否存在,布隆过滤器可以判断某个元素是否在集合中

4.2 缓存击穿

概念:单个热点key失效,在失效的那一刻,同时有大量请求打到DB上,造成数据库压力剧增的情况

解决办法:

  • 设置热点key不过期定时任务更新缓存 或者设置互斥锁,当请求过来时,发现缓存不存在数据时,就给当前请求加锁,后面的请求等待或者返回,当从数据库中拿出来放到缓存中时,就可以释放锁资源。

4.3 缓存雪崩

概念:多个热点key缓存失效,大量的key设置了相同的过期时间、导致缓存在同一时间全部失效,造成瞬时DB请求量大、压力剧增。

解决办法:

  • 存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
  • 启用透明多级缓存,多个服务节点因为加载一级缓存的时间不一样,也能分散过期时间

4.4 缓存污染

概念:缓存中的数据与真实数据源中的数据不一致的现象

解决办法:

使用更新缓存时遵循的设计模式,如:Cache Aside,Read/Write Through,Write Behind Caching这些

Cache Aside模式的工作方式:

  • 读数据时,先读缓存,如缓存中没有,则读数据库,再将数据写入缓存中;
  • 写数据时,先写数据库,然后失效缓存(删除缓存数据);

面试可能遇到的两个关于Cache Aside的问题:

1.更新先后顺序,为什么先更新数据库再删除缓存?

  • 假设先删除缓存再更新数据库,会有一段时间是缓存已删除,数据库未更新的情况。这时如果有请求进来,缓存中没查到,就会查数据库中旧的数据,再放到缓存里。造成问题就是:数据库已经是最新数据,缓存中还是旧的,不一致的问题;

2.为什么是删除缓存,而不是更新缓存?

  • 和上面一样,更新过程中,如果有其他更新请求进来更新数据库,缓存就会面临多次修改赋值的复杂时序问题。所以直接删除缓存就行。

总结:本文只写了一些关于分布式缓存的简单理论内容,实际面试时大多围绕redis进行提问,下次再写关于redis的相关内容