当前位置: 首页 > 科技观察

说说Redis的高可用原理

时间:2023-03-19 19:35:03 科技观察

大家好,我是楼仔!Redis的高可用太重要了!在找工作面试之前,这个问题的面试频率可以排在前列,尤其是在一些大厂。不要担心阅读这篇文章。如果面试官抛给你这样的问题,你会怎么回答?你可以考虑5分钟。在这里要等5分钟。。。其实我也可以偷懒,完全转贴其他博客,但是我没有找到我想要的。为了不让粉丝们失望,楼哥还是单独写了一篇文章给大家,主要是根据这块知识,结合之前的一些采访情况,跟大家聊一聊。1.Redis分片策略1.1Hash分片我们都知道,对于一个Reids集群,我们需要使用Hash策略将key分配给Redis的不同分片。如果我们有3台机器,常用的分片方式是hash(IP)%3,其中3是机器总数。目前很多小公司都在这么玩,上手快,简单粗暴,但是这种方式有一个致命的缺点:在增减缓存节点时,节点总数发生变化,导致分片值发生变化,并且有必要更新缓存数据进行迁移。那么如何解决这个问题呢,答案就是一致性Hash。1.2ConsistencyHashConsistencyHash算法是MIT于1997年提出的一种分布式哈希实现算法。环空间:根据常用的哈希算法,将对应的key散列到一个有2^32个桶的空间,即0~(2^32)-1。现在我们可以把这些数字首尾相连,想象一个闭环。Keyhash哈希环:现在我们通过特定的Hash函数计算出object1、object2、object3、object4这四个对象对应的key值,然后将它们哈希到Hash环上。Machinehash哈希环:假设有NODE1、NODE2、NODE3三台机器,按顺时针方向计算,将所有对象存储在最近的机器中,object1存储在NODE1中,object3存储在NODE2中,object2、object4存储到NODE3中。节点删除:如果NODE2出现故障被删除,则将object3迁移到NODE3。这样,只有object3的映射位置发生了变化,其他对象保持不变。新增节点:如果集群中新增节点NODE4,则object2迁移到NODE4,其他对象不变。一致性哈希算法通过对节点的增删分析,在保持单调性的同时,最大限度地减少数据迁移。该算法非常适合分布式集群,避免大量数据迁移,减轻服务器压力。如果机器数量太少,为了避免大量数据集中在几台机器上,达到平衡,可以创建虚拟节点(比如一台机器3-4个虚拟节点),然后对虚拟节点进行hash节点。2、高可用方案很多时候,公司只给我们提供了一套Redis集群。至于如何计算碎片,我们一般有两套成熟的解决方案。客户端方案:即客户端自己计算Redis分片。无论你使用Hash分片还是一致性Hash,都是由客户端自己完成的。客户端方案简单粗暴,但只能在单一语言系统之间复用。如果你使用的是PHP系统,后面还需要用到Java。你需要用Java重写一套分片逻辑。为了解决多语言、多平台复用的问题,衍生出中间代理层方案。中间代理层方案:将客户端方案的经验移植到代理层,通过通用协议(如Redis协议)实现在其他语言中的复用。用户不需要关心缓存如何实现高可用,只需要依赖你的代理层就可以了。代理层主要负责读写请求的路由功能,内置了一些高可用逻辑。大家可以看看,你们公司的Redis用的是什么方案?至于“客户端方案”,不用自己写。比如负责维护Redis的部门会提供不同语言的SDK,你只需要集成相应的SDK即可。3、高可用原理3.1Redis主从Redis基本上是以“主从”模式部署的,主从库之间采用读写分离的方式。和MySQL类似,主库支持写和读,从库只支持读。数据会先写入主库,然后定时同步到从库。具体的同步规则主要是将RDB日志从主库同步到从库,然后从库读取RDB日志,这里比较复杂,还涉及到复制缓冲区,就不展开了。这里有一个问题。在一次同步过程中,主库需要完成两个耗时的操作:生成RDB文件和传输RDB文件。如果从库过多,主库忙于fock子进程生成rdb文件和数据同步,会阻塞主库的正常请求。如何解决这个问题?答案是“主-从-从”模式。为了防止所有从库从主库同步RDB日志,可以使用从库来完成同步:比如添加3个和4个从库,可以等Slave2同步完成,再同步到Slave3和从站4到从站2。如果我是面试官,我可能会继续问,如果80%的数据都同步了,突然断网了,后面网络恢复的时候Redis会怎么运行?3.2Redis分片这个有点像MySQL分片分片,将数据存储在不同的地方,避免查询时全部集中在一个实例中。其实还有一个好处,就是master同步数据到slave的时候,如果RDB数据过大,会严重阻塞主线程。如果采用分片的方式,可以对数据进行分摊。每个分片只有2GB。可能有同学会问,Redis分片和“主从”模式有什么关系?可以理解图中每个分片都是主库,每个分片都有自己的“主从”模式结构。那么如何找到对应的数据分片呢?前面说了,如果我们有3台机器,常见的分片方式是hash(IP)%3,其中3是机器总数,hash值就是机器的IP。每台机器都有自己的分片号。对于key,也可以用同样的方法找到对应的机器段号hash(key)%3。hash算法有很多种,可以使用CRC16(key),也可以直接取key中的字符,转成数字。3.3Redis哨兵机制3.3.1什么是哨兵机制?在主从模式下,如果master宕机,从库无法从主库同步数据,主库也无法提供读写功能。怎么做?这时候就需要引入哨兵机制了!Sentinel节点是Redis的特殊服务,不提供读写服务,主要用于监控Redis实例节点。那么master宕机的时候sentinel是怎么执行的呢?3.3.2判断主机下线Sentinel进程会使用PING命令检测自身与主从库的网络连接,从而判断实例的状态。它将首先标记为“主观离线”。sentinel是否判断自己“主观下线”,直接下线master?答案肯定不是,需要遵循“少数服从多数”的原则:只有当N/2+1个实例判断主库“主观下线”时,才能判断主库“主观下线”客观离线”。比如上图中有3个sentinel,其中2个判断“主观下线”,则将主库标记为“客观下线”。3.3.3选择新的主库我们有5个从库,需要选择一个最优的从库作为主库,分为2个步骤:筛选:查看从库当前在线状态和之前的网络连接状态库,过滤不合适的从库;打分:根据从库的优先级和与老主库数据同步的远近进行打分,选择得分最高的作为主库。如果分数匹配怎么办?Redis还有一个策略:ID号最小的从库得分最高,将被选为新的主库。当slave3被选为新的主库时,会通知其他的从库和客户端,宣布自己是新的主库。每个人都得听我的!今天就到这里,下次再见,大家学够了吗?