【Redis】八股总结六:三大集群

124 阅读10分钟

三大集群各有什么优缺点?

  1. 主从
    1. 优点读写分离
    2. 缺点不能自动故障切换主节点
  1. 哨兵
    1. 优点,解决了主从集群不能自动故障切换的痛点,完成自动选主过程
    2. 缺点:不能横向扩展,只有一个主节点,内存缓存容量有瓶颈。
  1. 分片
    1. 优点:数据横向扩展。缓解内存压力。缓解并发写的压力。
    2. 缺点:去中心化。

单个Redis节点有什么问题?

  1. 存在单点故障问题(对应主从集群解决)
  2. 存在容量有限问题,存在高并发写问题。(对应分片集群解决)

主从集群

参考

高级篇-分布式缓存-08-Redis主从-主从的全量同步原理_哔哩哔哩_bilibili

主从复制是怎么实现的?

zhuanlan.zhihu.com/p/675942562(redis集群)

全量同步----命令传播-----增量同步

主从同步 之 全量同步(三步)

高级篇-分布式缓存-08-Redis主从-主从的全量同步原理_哔哩哔哩_bilibili

  1. slave第一次请求增量同步,master根据repli_id判断不一致,拒绝增量同步;准备全量同步
  2. master执行bgsave(后台子进程)生成RDB文件,并发送给slave,slave加载RDB进行同步
  3. master将RDB期间的命令,写在replication buffer中,RDB结束后将replication buffer中的命令发送给slave,完成全量同步的所有步骤。

注意第三阶段,是将RDB期间的命令写入replication buffer中,不是repli_baklog中,master会为每个slave配置一个replication buffer,而repli_baklog全局只有一个

主从同步之 命令传播(长连接)

主从服务器在完成第一次同步后,双方之间就会维护一个 TCP 连接

后续主服务器可以通过这个连接继续将写操作命令传播给从服务器,然后从服务器执行该命令,使得与主服务器的数据库状态相同。

主从同步之 增量同步(差不多两步)

高级篇-分布式缓存-09-Redis主从-增量同步原理_哔哩哔哩_bilibili

主从服务器在完成第一次同步后,就会基于长连接进行命令传播

可是,网络总是不按套路出牌的嘛,说延迟就延迟,说断开就断开。所以从节点重启后会进行增量同步

  1. slave重启后,发起psync同步命令,提交自己的offset给master。
  2. matser去repli_baklog中获取 从节点offset之后的命令,发送给slave节点(从repli_baklog)。

repl_backlog_buffer 缓冲区是什么时候写入的呢?

repl_backlog_buffer是一个环形缓冲区

在命令写入之后,就会记录

在主服务器进行命令传播时,不仅会将写命令发送给从服务器,还会将写命令写入到 repl_backlog_buffer 缓冲区里,因此 这个缓冲区里会保存着最近传播的写命令。

repl_backlog_buffer 和 replication_buffer有什么区别?

repl_backlog_buffer

  • master只要一个这个buffer
  • 增量同步的时候用

replication_buffer

  • master为每个从节点都设置一个replication_buffer
  • 增量同步和全量同步时都有用到

什么时候会进行全量同步?

  1. 第一次主从连接。
  2. 从节点断开太久,导致repli_baclog中offset被覆盖了。

什么时候执行增量同步?

从节点重启之后 且从节点的offset在repli_baclog中没有被覆盖。

从节点太多,导致主从同步压力太大怎么办?

主从复制是怎么实现的?

为什么会主从复制压力大呢?因为这样主节点要给没一个从节点都进行 全量或增量同步

采用 主-从-从分摊主节点压力

主从是短连接还是长连接?

长连接

分片集群

Redis Cluster:缓存的数据量太大怎么办?

高级篇-分布式缓存-15-Redis分片集群-集群伸缩_哔哩哔哩_bilibili

字节喜欢问

为什么要分片集群?

  1. 缓存数据量太大的情况下需要,单机redis不够 (需要横向扩展)
  2. 并发 或者 并发写的量太大。主从无法缓解并发写的压力。 (缓解写压力)

所以需要横向扩展

优点

  1. 横向扩展 缓解写压力存储压力,支持动态扩容缩容
  2. 同时具备主从复制、故障转移功能。

集群如何分片?

如何确定key分配的槽?(crc16校验码然后取模,得到槽位)

注重理解,关键信息:16384个哈希槽,平均分配到节点,每个key对应槽,每个key计算CRC16校验码 然后 对16384取模,就是这个key对应的哈希槽。

优点解耦数据节点之间的关系(加了一层哈希槽),提升集群扩展性容错性

扩展: 使用哈希槽 比 一致性哈希有什么优点?9.4 什么是一致性哈希?

  1. 一致性哈希算法并不保证节点能够在哈希环上分布均匀,这样就会带来一个问题,会有大量的请求集中在一个节点上。使用哈希槽没有这个问题,key可以均匀的分布在哈希槽上,而哈希槽是均匀分布在节点上的。
  2. 哈希槽可以手动分配槽位给节点。比如哪个节点多哪个节点少都可以手动决定而一致性哈希没有那么灵活
  3. 扩容缩容的时候更灵活,比如一致性哈希缩容导致下线节点的数据全部给到下一个节点

总结:比一致性哈希更均匀。更加灵活,手动分配

那一致性哈希引入虚拟节点 也可以解决数据倾斜(分布不均匀)的问题,哈希槽有什么优势?

虽然可以引入虚拟节点。但是还是没有哈希槽灵活,哈希槽可以手动分片槽位给节点。

什么是一致性哈希,解决什么问题?缺点是什么?

解决普通哈希 扩容缩容时 移动太多元素的问题。

但是一致性哈希也有数据倾斜的问题。

Redis Cluster 扩容缩容期间可以提供服务吗?

也就是迁移哈希槽的时候 可以提供服务吗?

可以提供服务。

Redis Cluster 中的节点是怎么进行通信的?

因为redis去中心化,所有没有注册中心,通过Gossip 协议进行通信。

很形象啊,Gossip翻译过来就是“流言蜚语”。

简单来说就是 新节点加入进来后,假如A知道了,A会告诉B,B又告诉C和D这样,最后一传十十传百就都知道了。

Redis分片集群如何实现故障转移?

虽然分片集群没有哨兵,但是各个节点之间互相进行心跳监控(gossip?),如果某个节点挂了其他节点也能感知,并完成主从切换。

Redis 分片集群的缺点?

去中心化,节点不能过多。

不然会造成难以管理监控,以及节点之间通信的问题

Redis节点是不是越多越好?

不是(两点,元数据大小,通信的延迟性)

  1. 因为redis集群是去中心化。因此节点总是全量存储整个集群的信息(槽位及节点信息),节点越多占用 元数据占用空间更多
  2. 去中心化很难清晰的掌握整个集群的状态,节点状态变化的延迟性也会带来极大的管理成本,就是说节点变化具有延迟性(某个节点挂了,需要让所有节点都知道具有一定延迟)

Redis的核心数是越多越好吗?

  1. 核心数不是 。因为只有主线程执行命令,其他的线程要么执行网络IO读写,要么是子进程进行RDB或aof重写。腾讯云那边建议是给redis分配两个核心。

分片集群key是如何路由的,就是key怎么知道我访问哪个节点哪个槽位?

默认情况下,当你操作一个 Key 的时候,你可以直接将请求打到集群中任意一个节点上,然后:

  1. Redis 实例将会根据 CRC16 算法计算出一个值,再对 16384 取模,从而得到该 Key 要落到的槽位
  2. 若 Key 恰好落在当前节点拥有的槽位上,那就直接执行命令;
  3. 否则就检查拥有槽位的节点是否存在,如果存在,则它会返回一个 MOVED 响应,告知客户端应该访问哪一个节点;
  4. 接着,客户端将会根据(如果支持的话)MOVED 重定向命令将请求重定向到正确的 Redis 节点

总结:随便访问一个节点,计算key之后得到槽位,如果槽位不在本节点则重定向(因为节点之间是通信的)

为什么哈希槽是16384?

Redis节点之间通信采用ping/pong心跳包,哈希槽信息会随着心跳包一起发送,(16384/8bit)占用2K,是个合适的大小。

如果是65536/8 = 8K,太大了。

哨兵集群

为什么要有哨兵?

自动完成 故障发现 和 主从切换。

主节点挂了 ,从节点是无法自动升级为主节点的,这个过程需要人工处理,在此期间 Redis 无法对外提供写操作。

此时,Redis 哨兵机制就登场了,哨兵在发现主节点出现故障时,由哨兵自动完成故障发现和故障转移,并通知给应用方,从而实现高可用性。

哨兵集群的 监控、选主以及切换 流程

1、服务状态监控

  1. 通过心跳机制,每秒发ping命令进行监控。
  2. 主观下线和客观下线

2、选举master规则

  1. 首先判断slave和master的断开时间,排除断开时间太长的slave。
  2. 判断slave的slave-priority优先级
  3. 优先级一样,判断offset的值
  4. offset一样,判断运行redis运行id

3、进行切换,故障转移

  1. 给选举出来的节点发送 slaveof no one,成为master
  2. 给其他节点发送,slaveof ip:port(新master的)
  3. 修改故障节点的配置文件slaveof ip:port

Redis哨兵模式下的脑裂问题了解吗?如何解决?(阿里)

📎33-脑裂:一次奇怪的数据丢失 .pdf(文章)

Redis脑裂就是主库假故障(通常可能是网络引起的),导致哨兵把原主库判断为客观下线,然后哨兵进行主从切换(在这期间原主库好了继续接收客户端请求),最后切换完成有了两个主库

切换之后,哨兵对原主库执行slava of命令全量同步新主库的数据,导致客户端写入原主库的数据丢失。

如何解决脑裂?

  1. Redis自身解决方案:通过minslaves-to-write 和 min-slaves-max-lag解决。
  2. 其他方案,RocketMQ中的Dleger集群,通过时间片分配,没有永远的主。(但是缺点就是选举阶段太频繁, 每次时间片走完都要选举)