高并发系统设计学习笔记(十二) 缓存如何做到高可用

目录

一、重视缓存问题

 二、客户端方案

1.缓存数据如何分片

(1)Hash分片的算法

(2)一致性Hash算法

(3)一致性Hash算法中引入虚拟节点

2.主从机制

3.多副本

三、中间代理层方案

四、服务端方案


一、重视缓存问题

你需要关注缓存命中率这个指标(缓存命中率=命中缓存的请求数/总请求数)。一般来说,在你的电商系统中,核心缓存的命中率需要维持在99%甚至是99.9%哪怕下降1%,系统都会遭受毁灭性的打击

假设系统的QPS是10000/s,每次调用会访问10次缓存或者数据库中的数据,那么当缓存命中率仅仅减少1%,数据库每秒就会增加10000 * 10 * 1% = 1000次请求。而一般来说我们单个MySQL节点的读请求量峰值就在1500/s左右,增加的这1000次请求很可能会给数据库造成极大的冲击。

命中率仅仅下降1%造成的影响就如此可怕,更不要说缓存节点故障了,单点部署的缓存节点就成了整体系统中最大的隐患

分布式缓存的高可用方案

  • 客户端方案 就是在客户端配置多个缓存的节点,通过缓存写入和读取算法策略来实现分布式,从而提高缓存的可用性。
  • 中间代理层方案 是在应用代码和缓存节点之间增加代理层,客户端所有的写入和读取的请求都通过代理层,而代理层中会内置高可用策略,帮助提升缓存系统的高可用
  • 服务端方案 就是Redis 2.4版本后提出的来咯咯;方案。

 二、客户端方案

需要关注缓存的写和读两个方面

  • 写入数据时,需要把被写入缓存的数据分散到多个节点中,即进行数据分片
  • 读数据时,可以利用多组的缓存来做容错,提升缓存系统的可用性。关于读数据,这里可以使用主从多副本两种策略,两种策略是为了解决不同的问题而提出的。

1.缓存数据如何分片

单一的缓存节点受到机器内存、网卡带宽和单节点请求量的限制,不能承担比较高的并发,因此我们考虑将数据分片,依照分片算法将数据打散到多个不同的节点上,每个节点上存储部分数据

分片算法常见的就是Hash分片算法一致性Hash分片算法两种

(1)Hash分片的算法

Hash分片的算法就是对缓存的Key做哈希计算,然后对总的缓存节点个数取余

 缺点是当增加或者减少缓存节点时,缓存总的节点个数变化造成计算出来的节点发生变化,从而造成缓存失效不可用

(2)一致性Hash算法

用一致性Hash算法可以很好地解决增加和删减节点时,命中率下降的问题.

我们将整个Hash值空间组织成一个虚拟的圆环,然后将缓存节点的IP地址或者主机名做Hash取值后,放置在这个圆环上。当我们需要确定某一个Key需要存取到哪个节点上的时候,先对这个Key做同样的Hash取值,确定在环上的位置,然后按照顺时针方向在环上“行走”,遇到的第一个缓存节点就是要访问的节点。比方说下面这张图里面,Key 1和Key 2会落入到Node 1中,Key 3、Key 4会落入到Node 2中,Key 5落入到Node 3中,Key 6落入到Node 4中。

这时如果在Node 1和Node 2之间增加一个Node 5,你可以看到原本命中Node 2的Key 3现在命中到Node 5,而其它的Key都没有变化;同样的道理,如果我们把Node 3从集群中移除,那么只会影响到Key 5 。所以你看,在增加和删除节点时,只有少量的Key会“漂移”到其它节点上大部分的Key命中的节点还是会保持不变,从而可以保证命中率不会大幅下降。 

存在的问题

  • 缓存节点在圆环上分布不平均,会造成部分缓存节点的压力较大;当某个节点故障时,这个节点所要承担的所有访问都会被顺移到另一个节点上,会对后面这个节点造成压力。
  • 一致性Hash算法的脏数据问题

 极端情况下,比如一个有三个节点A、B、C承担整体的访问,每个节点的访问量平均,A故障后,B将承担双倍的压力(A和B的全部请求),当B承担不了流量Crash后,C也将因为要承担原先三倍的流量而Crash,这就造成了整体缓存系统的雪崩

(3)一致性Hash算法中引入虚拟节点

它将一个缓存节点计算多个Hash值分散到圆环的不同位置,这样既实现了数据的平均,而且当某一个节点故障或者退出的时候,它原先承担的Key将以更加平均的方式分配到其他节点上,从而避免雪崩的发生

2.主从机制

主从机制最大的优点就是当某一个Slave宕机时,还会有Master作为兜底不会有大量请求穿透到数据库的情况发生,提升了缓存系统的高可用性。 

3.多副本

 

对于极端流量的场景下,一组Slave通常来说并不能完全承担所有流量,Slave网卡带宽可能成为瓶颈。为了解决这个问题,我们考虑在Master/Slave之前增加一层副本层,整体架构是这样的

当客户端发起查询请求时,请求首先会先从多个副本组中选取一个副本组发起查询如果查询失败,就继续查询Master/Slave,并且将查询的结果回种到所有副本组中,避免副本组中脏数据的存在

基于成本的考虑,每一个副本组容量比Master和Slave要,因此它只存储了更加热的数据。在这套架构中,Master和Slave的请求量会大大减少,为了保证它们存储数据的热度


三、中间代理层方案

虽然客户端方案已经能解决大部分的问题,但是只能在单一语言系统之间复用。例如微博使用Java语言实现了这么一套逻辑,我使用PHP就难以复用,需要重新写一套,很麻烦。而中间代理层的方案就可以解决这个问题

所有缓存的读写请求 都是经过代理层完成的。代理层是无状态的,主要负责读写请求的路由功能,并且在其中内置了一些高可用的逻辑,不同的开源中间代理层方案中使用的高可用策略各有不同。 比如Facebook的Mcrouter,Twitter的Twemproxy,豌豆荚的Codis


四、服务端方案

Redis在2.4版本中提出了Redis Sentinel模式来解决主从Redis部署时的高可用问题,它可以在主节点挂了以后自动将从节点提升为主节点,保证整体集群的可用性,整体的架构如下图

Redis Sentinel也是集群部署的,这样可以避免Sentinel节点挂掉造成无法自动故障恢复的问题,每一个Sentinel节点都是无状态的。在Sentinel中会配置Master的地址,Sentinel会时刻监控Master的状态,当发现Master在配置的时间间隔内无响应,就认为Master已经挂了,Sentinel会从从节点中选取一个提升为主节点,并且把所有其他的从节点作为新主的从节点。Sentinel集群内部在仲裁的时候,会根据配置的值来决定当有几个Sentinel节点认为主挂掉可以做主从切换的操作,也就是集群内部需要对缓存节点的状态达成一致才行。 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值