美文网首页
Redis-集群

Redis-集群

作者: 麦大大吃不胖 | 来源:发表于2020-12-13 10:18 被阅读0次

by shihang.mai

1. redis单节点问题

1. 单点故障
2. 容量有限
3. 压力大(多连接)

2. AKF分析,解决redis单节点问题

主备:client只能访问主,master挂了,备机能接上
主从:client同时能访问主和从

akf分析
  1. 沿x轴,做redis实例全量镜像,1主多备,主做读写,备做读,实现读写分离。解决单点问题。
  2. 沿y轴,业务功能拆分。解决容量问题。
  3. 沿z轴,同一业务数据分散。解决压力问题。

通过AKF,一个redis变多个,会引入新的问题:数据一致性

2.1 X轴推导最终一致性

akf分析-x轴

如上图的"情况1"
强一致性,破坏可用性
当客户端set值时,set完主,所有节点阻塞直到数据同步一致,这样是强一致性。但当有一个从10分钟后才返回,客户端响应慢,破坏了可用性。引入1变多,就是因为解决单点,即解决可用性问题,而现在强一致性破坏可用性,方案不可取

如上图的"情况2"
丢失数据
既然情况1中强一致性会破坏可用性,那么我们就容忍丢失一部分数据。同步数据改为异步。当数据还没同步完成,主down了,那么从备为主后,数据就丢失了。

如上图的"情况3"
最终一致性
相对于情况2,可以保证数据不丢失。kafka不是唯一的实现方式,只要是可靠的,集群的,响应速度足够快。这样做数据不会丢失,也可以及时向客户端返回。

"情况3"看似很好,但是主还是单点。所以一般对主做HA(高可用)

高可用:主从切换

2.2 Sentinel推导

redis集群数奇数
  1. 当3个监控节点时,3个说没down,redis才没down.强一致性
  2. 因为会网络波动,可能会有些监控程序无法连接,我们让一步,一部分(n/2+1)给出结果即可。
- 当3个节点时,需要2个说redis没down,redis才没down.
- 当4个节点时,需要3个说redis没down,redis才没down.
3个和4个节点对比,都同样容许一个down,但是4台发生的风险比3台高.所以我们一般使用奇数台(n/2+1说没down,才没down).
  1. 可用性

3. 主从复制

“情况2”就是redis的主从复制模式
可以设置同步方式:

  1. 主redis,下一个rdb到磁盘,然后通过网络给从redis
  2. 主redis,直接不下rdb,直接通过网络发出rdb给从redis

3.1 Sentinel哨兵

看上面图的"监控",哨兵是监控Master的。

每个哨兵只需配置监控那个master,但是每个哨兵最终是知道有其他的哨兵的。这是通过redis发布订阅功能,哨兵监听master中sentinel通道得知的。

以上利用Sentinel哨兵+主从复制,解决主单点问题,并且主挂掉后,也有从补上,但是容量问题未解决


4. 解决容量问题-在client端集成分发逻辑

解决容量问题,利用akf的y和z轴


akf-y轴-解决容量问题

4.1 方案1

逻辑:业务拆分,根据不同的业务分到不同的redis

用在数据可拆分的场景。

4.2 方案2

模式:modula模式
逻辑:hash+取模

它的弊端取模的数是固定的,影响分布式下的扩展性。

4.3 方案

模式: random

用在消息队列

4.4 方案

模式: ketama
逻辑:一致性哈希环,映射算法不仅限于hash,crc16,crc32,fnv,md5。环上一共有0-2^32点
一致性是指,当我新加入redis节点时,不需要做全量redis节点的重哈希,只会一部分数据缓存失效,对于大多数(数据-服务器)这个对应关系前后一致

  1. node1和node2通过映射算法,将redis映射到哈希环上作为物理点
  2. 现在来一个data放入redis,data也通过映射算法,映射到哈希环上
  3. 可以利用treeMap等等一个具有排序的数据结构,将redis映射的物理点放进去,然后用data映射出来的点去treeMap找,找出比自身大的点,可能处在多个这样的点,找离自己点最近的物理点,将data存进去就可以了
  4. 此时放入一个node3,会导致(key->node3)段中的数据找不到,而(node3->node2)段的没影响,原因如下:
before:另外一个key映射到(key->node3)段,此时并没有node3,所以把数据放入到了node2
after: 此时加入node3,还是这个key,它还是映射到(key->node3)段,那么它就会在node3查找,发现数
据找不到

4.4.1 优点

可以分担压力,不会造成全局洗牌(取模的方式会全部洗牌)

4.4.2 缺点

新增节点,会导致一小部分数据不能命中。正因如此,会有缓存击穿的问题,将压力压到mysql。可以用这样的方案解决:查的时候,查离自己最近的两个点,没得话再去mysql查

4.5 虚拟节点

如果只有两个node,为避免数据倾斜到某一个node上,可以将两个node的值分别加上1-10的数字,再hash,形成20个点

5. 解决容量问题-client不需要集成分发代码

但是上述方案2 3 4在实际上会有多个客户端,同时连接多个redis,redis的连接成本好高。发展为下面的lvs+proxy。将modula、random、ketama转移到proxy层(无状态的),这样不用和业务代码耦合。

akf-y轴-解决容量问题-多客户端

方案234与lvs+proxy区别,只是将3中模式分在了业务和proxy端,他们的弊端都是不能做数据库用。

此方案倾向于将redis作为缓存,而不是数据库用。数据库用cluster模式

6. redis-cluster模式

redis官方就是使用redis-cluster模式去解决容量问题的。每个实例均有一些虚拟槽,redis虚拟槽位有16384个。当增加或者删除实例节点时,槽位会进行迁移

6.1 cluster原理例子

redis-cluster模式
  1. 预分区,先取模为10,现在有redis1和redis2,然后通过mapping,redis1获得了01234槽,redis2获得56789槽
  2. 当新增redis3时,将redis1的(3,4),redis2的(8,9)给到redis3,redis3获得3489,并形成上图。这样做的话,不用重新rehash,只需迁移数据.

寻找槽的过程并不是一次就命中的,集群保证了最多两次就能命中对应槽所在的节点。因为每个实例中均有hash函数和其他节点负责的槽信息。

假设要获取的key在redis3,4号槽位.但客户端实际连接的是redis2

  1. 客户端将key发向实际的redis2,然后在redis2做hash取模运算,得到值为4。
  2. 4与自己的槽位(5,6,7)比较,发现不在自己槽位上,而是在redis3上。将这个信息告诉客户端。
  3. 客户端连接redis3,发出key,查找结果。

6.2 集群通讯

为什么某一个节点拥有其他节点的信息呢,这就涉及到集群是如何通讯的了。gossip协议

redis集群节点通讯.png
节点之间通过ping/pong交互信息
  1. 节点A对节点B发送一个meet操作,B返回后表示A和B之间能够进行沟通。
    2.节点A对节点C发送meet操作,C返回后,A和C之间也能进行沟通。
  2. 然后B根据对A的了解,就能找到C,B和C之间也建立了联系。
    直到所有节点都能建立联系。

这样每个节点都能互相直到对方负责哪些槽

6.3 集群伸缩

6.3.1 集群扩容

当有新的节点准备好加入集群时,这个新的节点还是孤立节点,并且它不是主节点就是从节点。

  • 主节点就要分担槽位数据(原理例子中写得很清楚了)
  • 从节点作为故障转移备份

这里详细说说具体怎么做


redis槽迁移步骤.png

6.3.2 集群缩容

  1. 当是从节点下线,是不影响集群的,各个主节点只是记录这个从节点下线了。
  2. 当是主节点下线,如果该主节点没槽位,那么直接下线,其他主节点直接记录这个主节点下线。
  3. 当下线的主节点具有槽位,那么就需要触发故障转移

故障转移是主观下线+客户下线实现的

redis故障转移-主观下线.png

上图为主观下线

  1. NodeA定时ping NodeB
  2. 如果ping通,那么NodeA会记录和NodeB最后通讯时间
  3. 如果没ping通,那么就要判断上一次的最后通讯时间有没超过配置的时间了,如果超了,那么NodeA就标记NodeB为主观下线了
  4. NodeA会拥有其他NodeB、NodeC....的信息。即NodeA有其他Node对NodeB是否主观下线的信息,当半数以上的持有槽的主节点都标记某个节点主观下线,就会尝试客观下线。

客观下线


redis故障转移-客观下线.png

那么从节点如何成为master节点呢。

  1. 首先是进行资格检查,只有具备资格的从节点才能参加选举:
  • 故障节点的所有从节点检查和故障主节点之间的断线时间。超过cluster-node-timeout * cluster-slave-validati-factor(默认10)则取消选举资格
  1. 不同的从节点,会有不同的偏移量。offset最大的slave节点,优先参与选举,其他的从解节点按顺序延迟选举。所以说offset最大的slave节点最有机会当选master节点。
  2. 当发出选举后,其他的主节点就开始投票了,过半当选。当选出了master节点后,该master向集群中其他节点广播Pong消息,表明已完成故障转移

6.4 数据分治弊端

  • 聚合操作和事务很难实现。

  • cluster支持用hash tag将key分布到同一个节点上,这样就可以实现类似单机的事务

7. 题外话

twitter/twemproxy和predixy可以做redis的代理,可以像单机一样使用集群

相关文章

  • redis-集群

    redis3.0版本开始支持集群功能,当我第一次学习它的时候,感觉它是我看到的第一个智能系统,后来发现很多同学的吐...

  • Redis-集群

    演变过程:单机-主从-哨兵(解决主机宕机问题)-cluster(解决故障转移时系统无法使用问题) 主从模式 在 R...

  • Redis-集群

    集群 by shihang.mai redis单节点 AKF分析 主备:client只能访问主,master挂了,...

  • Redis-集群

    哈希槽Redis集群没有采用一致性hash,而是引入了哈希槽的概念。Redis集群有16384个哈希槽,每个key...

  • springboot 集成culster-redis集群 doc

    doker搭建redis- culster集群 下载doker等过程不再介绍 本文搭建环境是mac os 与cen...

  • Redis-集群与高可用

    1- 水平分区 VS 垂直分区 分区是分割数据到多个Redis实例的处理过程,因此每个实例只保存key的一个子集。...

  • Redis-学习之旅(13)-redis-集群的配置过程

    1. 首先还是安装redis 参见系列文章(一) redis的安装 2. 开始创建集群 新建集群文件夹 然后将...

  • 使用过Redis,我竟然还不知道Rdb

    使用过Redis,那就先说说使用过那些场景吧 字符串缓存 //举例$redis->set();$redis->ge...

  • Redis学习之路(12)- 杂记

    Redis-过期删除策略 Redis-删除策略: 1、定时删除:对内存友好, 但是占用cpu 2、惰性删除:对cp...

  • Redis-构建集群redis-cluster

    一、引子 1.Redis主从复制以及哨兵,它们可以提高读的并发,但是单个master容量有限,数量达到一定程度后会...

网友评论

      本文标题:Redis-集群

      本文链接:https://www.haomeiwen.com/subject/usoziktx.html