当前位置: 移动技术网 > IT编程>数据库>Redis > Redis--AKF架构

Redis--AKF架构

2020年07月17日  | 移动技术网IT编程  | 我要评论

Redis--AKF架构

  1. AKF架构

    1. 由于redis是单进程、单线程、单实例的,所以如果我们只使用一个redis与客户端交互就会带来单点故障、缓存容量、压力等一系列问题,如下图所示
      在这里插入图片描述
    2. 基于以上三种问题,人们提出了AKF架构,其中,x轴的扩展为redis的全量镜像,保证当前redis挂掉之后服务依然可以正常提供,而且x轴上的redis实例可以向client提供一些服务,缓解压力
      在这里插入图片描述
    3. x轴的扩展有效的缓解了压力和单点故障的问题,但是依旧没有解决容量的问题,毕竟由于要保持数据一致,其中一个满了,其它的也会满,所以,y轴的扩展就是基于业务,不同的场景使用不同的redis
      在这里插入图片描述
    4. 同样的道理,z轴的扩展就是将数据根据优先级进行更细粒度的划分,进一步降低数据的耦合度
      在这里插入图片描述
    5. 到了这里AKF的架构图已经画出来了,但其中依旧有许多存在的问题,这里我们首先要明确一点,在一台服务器中,无论我们后面分了多少redis,有多少集群,对用户来说都是不可见的,用户只负责调用服务,因此,这时我们就需要考虑以下的问题
      1. X轴上的全量拷贝怎么实现?如何操作?
      2. Y轴上根据业务场景的划分怎么实现?
  2. 主从复制

    1. 解决上面提出的第一个问题,全量拷贝使用redis提供的RDB方式很容易便可实现,但是所有的redis实例显然不能同时提供读写服务,若是都提供写服务,需要考虑数据同步的问题,这会明显拖慢redis的速度,违背了redis的设计初衷。因此,大部分情况下,是由一个redis实例提供读写服务,其它的redis实例只提供读服务,这就是redis的主从复制,提供完整服务的redis为主,其它为从
    2. 基于主从复制搭建了集群后,我们就需要考虑数据一致性的问题了,主redis写入数据后,从redis如何知道,如何同步?有三种思路
      1. 同步阻塞:主redis写入数据后,从redis进入阻塞状态同步数据,这个状态下不提供服务,但这显然是不可取的,破坏了可用性
        在这里插入图片描述
      2. 异步(redis选择的方式):在同步数据的同时,从redis继续提供服务,但由于是异步的,所以可能导致数据未能成功读取,视作丢失数据
        在这里插入图片描述
      3. 使用中间代理,在主redis和从redis间使用一种其它集群技术(例如kafka),该集群必须拥有高可靠性和响应时间短的特点。在主redis更新完数据后,同步到中间代理上,中间代理阻塞从redis,更新数据,自己代替从redis提供服务。该方法虽然依旧有可能丢失数据,但明显比上面的更可靠。为什么redis不使用该方法?保证redis的快!
        在这里插入图片描述
    3. 了解了数据一致性后,我们会发现一个新的问题:主redis只有一台,它down掉了怎么办?芜湖,又回到最初的起点~(๑´ㅂ`๑)。但其实是有些不一样的,由于我们有了从redis,而数据又和主redis一致,显然我们可以从中挑选一个新的主redis,其它redis继续跟随它,继续提供服务,这就牵扯redis的哨兵机制了。
      1. 首先,显然不可能由用户发现不对后再告诉redis主redis挂了,从redis是可以根据连接来判断主redis的状态的,由于从redis也可能出现故障,所以redis内部规定需要有一半的从redis认为主redis挂了,才能采取相应的操作,这个时候,从redis的数量选择就需要斟酌一下了
        在这里插入图片描述
        在这里插入图片描述
      2. 在主redis挂掉之后,所有的哨兵会通过投票的方式选出一个新的主redis,其它从redis继续追随该主redis
  3. 容量问题解决方案

    1. 回到上面提出的第二个问题,Y轴上根据业务场景划分怎么实现,以下有几个方案以供讨论
      1. 在有多台服务器的情况下,我们可以通过逻辑代码的控制,将不同类型的数据交给不同的redis服务端处理,但是当数据无法分类,或者没有多台服务器的情况下,我们该如何划分呢?
      2. 采用hash算法,对所有的数据进行取模运算,再根据结果来划分该存入到哪个redis实例中。但模数值显然是我们一开始就需要指定的,这样当后期遇到什么情况时,扩展就会变得相对困难。
        在这里插入图片描述
      3. 采用随机的方式,将数据随机分不到不同的redis实例中。但使用该方法将导致数据不能精确取出,毕竟你无法判断最近的数据存到了哪个redis中,该模式最常用的地方是消息队列
        在这里插入图片描述
      4. 采用kemata一致性哈希算法
           一致性哈希算法是一种映射算法,将key和设备进行哈希计算,映射到一个哈希环上。在哈希环上绝大部分点是虚拟的,但有一部分点是物理的,即设备与环的映射点。增加虚拟节点的主要目的是为了解决数据倾斜的问题。当我们想设备中存数据的时候,实际上是对数据的key做一致性哈希算法,将得到的值映射到哈希环上,并向左右两边分别寻找设备,找到离他最近的一台设备的物理点,通过物理点将数据写入设备
        在这里插入图片描述
           但是这里存在一个问题,当device3插入到哈希环上的时候,假设我们刚刚把数据存到了device2,这个时候由于device3的加入,有些数据就查不到了,因为查询时是寻找离他最近的物理点。因此,该算法可能造成redis的击穿,即redis中有数据但依然像数据库中进行查找。由于相同的问题,使用该算法的redis更倾向于缓存而不是数据库,因为数据库必须保证数据的完整性!
      5. 在client端和server间添加代理层,由代理来实现上面所述的逻辑代码,这样我们只需要关注代理的性能便可以了,当然,代理也必须是集群,不然依旧会出现单点故障的问题。但是redis并不推荐这种方法,原因依旧是redis想尽可能的保证轻量,尽可能的快!
        在这里插入图片描述
      6. 说了这么多,redis自身到底是使用哪种方式来解决该问题的呢?答案是预分区
        在这里插入图片描述
        如上图,假设在client端采用取模算法得到了hash值有0-9十个数,现在有三台redis,每一台redis都有一个哈希映射,client端可以通过映射去redis寻找数据,并且每台redis还有其他两台redis的映射表。客户端如果想找key为3的数据,那么先随机找一个redis,redis对key进行取模然后去自己的映射表找有没有能和取模后的数对应上的,有的话直接返回数据,没有的话在其他两个redis的映射表中去寻找是否还有该key,没有的话告诉没找到,有的话返回客户端让他重定向到另一个redis,定位到了redis3。基于此方式,redis自身很难实现事务相关操作,需要由用户控制。
  4. 零碎知识点

    1. replicaof host port : 将当前redis实例作为从redis,host为主redis ip地址,port为端口号,若输入replicaof no one则代表当前redis实例脱离主redis
    2. 当初次完成追随后,从redis中的数据会被清空,将用RDB的方式从主redis中拿取数据
    3. 当从redis挂掉后,若在一段时间内再次联系上主redis,则会有以下两种情况
      1. 若在配置文件中配置了必须使用AOF方式来转移数据,则一定会导致从redis中原有数据被清空,重新读入数据,因为AOF文件中并不会记录相关的主从信息
      2. 若配置文件中没有指定必须用AOF方式转移数据,则会判断此时的数据是否超过repl-backlog-size配置的值,没超过则使用AOF添加数据,超过了则重新读入数据。比如若repl-backlog-size设置的值为5m,则当从redis重新追随主redis时,判断从它挂掉的时间点到现在主redis是否写入了超过5m的数据,未超过则代表还有救,可以使用AOF往后追加数据,超过了则表示没救了,重新写入!
    4. 启动哨兵:redis-server 配置文件路径(里面写需要监控的redis) --sentinel,下面是配置文件最简单的写法
      在这里插入图片描述
    5. 哨兵与哨兵间通过订阅和发布的方式交流信息

本文地址:https://blog.csdn.net/qq_45489824/article/details/107355046

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网