高薪Offer收割机之redis集群

单节点的redis并发能力是有限的,如果需要进一步提高redis的并发能力,就需要搭建集群。

Redis中的集群分为三种:

主从复制,哨兵模式,分片集群

先来看一下主从复制:

5713914d5766f11656ba7f475a727a0f.jpeg

在主从集群中一个主节点可以有多个从节点,一个从节点只能有一个主节点。主节点负责写数据,从节点负责读数据。当数据写入主节点以后会被同步到从节点,从而保证所有节点上的数据一致性。

主节点的数据同步到从节点有两种方式:全量同步和增量同步。

先来看一下全量同步,全量同步分为三个阶段:

f40b9a4a499cba7c4de0e181f6b3d8ee.jpeg

第一阶段:建立连接

Slave(从)服务器执行slaveof ip host和master(主)服务器建立连接,其中ip、host 是 master 服务器的 IP 地址和端口号。比如:slaveof 127.0.0.1 6376

第二阶段:数据同步

在 slave 初次连接 master 后,复制 master 中的所有数据到 slave,步骤如下:

1.slave 发送 psync 指令到 master 请求同步数据(psync ? -1)。psync 指令包含两个参数,完整的格式为 psync {replid} {offset},其中 replid为replid,offset 为复制的偏移量,因为现在是首次复制,所以 replid并不知道,设为『?』,offset设置为 -1。

2.master判断是否是第一次同步,判断方法为比较自己的replid和从服务器发送过来的replid看看是否一致,如果不一致则是第一次同步,主服务器会 将自己的 replid发送给从服务器(FULLRESYNC {replid} {offset}),从服务器收到后会记录 replid和 offset。

3 master 执行 bgsave 生成 RDB 文件,并通过 socket 发送给 slave,同时将 bgsave 之后的命令写进repl_baklog日志文件。

4 slave 接收 RDB 文件后,清空本地数据,并加载 RDB 文件,加载完毕之后,向 slave 请求部分同步数据。

5 master 将repl_baklog日志文件的信息发送给 slave。

6 slave 接收到信息后,执行这些命令,恢复数据。

这里的Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid。

offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

再来看一下增量同步:

slave节点重启或者后期数据发生变化的时候可以使用增量同步.

增量同步的步骤如下:

1.当slave节点重启以后向master发送命令psync {replid} {offset}

2.master判断是否第一次同步,如果replid相同则不是第一次同步,返回continue

3.master会从repl_baklong中获取到slave发送的offset之后的数据并将命令发送给slave

4.slave接收到后执行命令完成增量同步。

接下来看一下哨兵模式:

在Redis主从复制模式中,因为系统不具备自动恢复的功能,所以当主服务器(master)宕机后,需要手动把一台从服务器(slave)切换为主服务器。在这个过程中,不仅需要人为干预,而且还会造成一段时间内服务器处于不可用状态,同时数据安全性也得不到保障,因此主从模式的可用性较低,不适用于线上生产环境。

Redis Sentinel 哨兵模式,它弥补了主从模式的不足。Sentinel 通过监控的方式获取主机的工作状态是否正常,当主机发生故障时, Sentinel 会自动进行 Failover(即故障转移),并将其监控的从机提升主服务器(master),从而保证了系统的高可用性。

哨兵的结构和作用如下:

监控:Sentinel 会不断检查master和slave是否按预期工作

自动故障恢复:如果master故障,Sentinel会将一个slave提升为master,然后使用 PubSub 发布订阅模式,通知其他的从节点,修改配置文件,跟随新的主服务器

通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

87af7cf8171c5efba21c11cfbf54d7a3.jpeg04e97cd2ff098b833e2310e8741690bb.jpeg

下面详细讲解一下服务状态监控:

Sentinel基于心跳机制检测服务状态,每隔一秒向集群中的每个实例发送ping命令。

如果某sentinel节点发现某实例未在规定时间响应则认为该实例主观下线。

若超过指定数量的sentinel都认为该实例主观下线,则该实例客观下线。指定数量值最好超过sentinel实例总数量的一半。

再来看一下哨兵的选主规则:

1.首先判断一下主与从节点断开的时间长短,如果超过指定值说明断开时间过长,数据丢失过多,于是排除该从节点。

2.判断从节点的优先级(slave-priority)该值越小优先级越高。

3.如果优先级一样则判断该从节点的offset值,offset值越大说明该从节点和主节点的数据越接近,被选主的优先级也就越高。

哨兵模式下的脑裂问题:

efab5d07b3ff0d0dddacad1e325135ba.jpeg

什么是脑裂问题,一旦网络发生了故障,master和sentinel及slave分别处于不同的网络,sentinel检测不到master于是从slave中选择一个提升为master,于是就有了两个master,这也是脑裂名称的由来,此时客户端还在向master中写入数据,等故障恢复以后原来的master被降级为slave,它会将自己的数据清空然后从新的master同步数据这样就会有一部分数据丢失。

怎么解决脑裂问题呢?

可以通过两个配置参数来解决:

min-replicas-to-write 1 表示最少的salve节点为1个

min-replicas-max-lag 5 表示数据复制和同步的延迟不能超过5秒

配置这两个参数以后当发生脑裂时,原来的master会拒绝数据的写入。

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:海量数据存储问题,高并发写的问题

使用分片集群可以解决上述问题,分片集群特征:

集群中有多个master,每个master保存不同数据这样就解决了高并发写的问题。

每个master都可以有多个slave节点,可以解决海量数据的存储和高并发读的问题

master之间通过ping监测彼此健康状态,master起到了哨兵的作用。

客户端请求可以访问集群任意节点,最终都会被转发到正确节点。

b8d25a922af17ec5e4d553f69596aa5f.jpeg

既然分片集群有多个master节点,那么如果我要写一个数据究竟会被写到哪个节点上呢?

Redis分片集群引入了哈希槽的概念,redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。

ea50a23bd8fbad51a6cfad893d0c7a9b.jpeg

比如集群中有三个master第一个master的哈希槽为0-5460第二个为5461-10922第三个为10923到16383.

假如要执行set name hello 将name hello存入,则会使用CRC16算法计算name的hash值得到666666对16384取模结果为11306,11306处于10923到16383之间,所以该值会被存储到第三个master节点。

如果想将多个键值对放到同一个节点,可以通过设置键的前缀的方式,比如set name hello可以给键name一个前缀set {aaa}name hello用CRC16算法计算其前缀aaa的hash值得到888888,对16384取模结果为4152根据区间放在第一个master节点。如果需要再存入set city Beijing 也可以设置前缀set {aaa}city Beijing这样该键值对也会写入第一个master节点。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaxiaomao1981

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值