【面试题】Redis集群架构以及主从复制

1. redis集群原理(slot槽,crc16算法)

在这里插入图片描述
redis 集群是一个由多个主从节点群组成的分布式服务器群,它具有复制、高可用和分片特性。Redis 集群不需要 sentinel 哨兵,也能完成节点移除和故障转移的功能。需要将每个节点设置成集群模式,这种集群模式没有中心节点,可水平扩展,据官方文档称可以线性扩展到上万个节点(官方推荐不超过1000个节点)。

集群特点

至少需要 3 个主节点
从节点仅用于数据备份,读写都从主节点进行
整个集群所有节点逻辑分片,16384 个Hash槽可以均匀分布给不同的节点
建议错峰连接(主节点可以和从节点不在一台机器),即使机器断开也不影响使用
不能批量操作(如MSET),key 值 Hash 出的槽位不同,导致存储机器不同(可以设计Key)
重启集群只需要重启单个节点

Redis 高可用集群的搭建

redis 集群至少需要三个master节点,并且给每个 master 再搭建一个slave节点,总共 6 个redis节点,这里演示用三台机器部署 6 个 redis 实例,每台机器一主一从,搭建集群的步骤如下:

第一步:在第一台机器的/usr/local下创建文件夹redis-cluster,然后在其下面分别创建2个文件夾如下
(1)mkdir -p /usr/local/redis-cluster
(2)mkdir 8001 8004

第二步:把之前的redis.conf配置文件copy到8001下,修改如下内容:
(1)daemonize yes #后台运行
(2)port 8001(分别对每个机器的端口号进行设置)
(3)pidfile /var/run/redis_8001.pid  # 把pid进程号写入pidfile配置的文件
(4)dir /usr/local/redis-cluster/8001/(指定数据文件存放位置,必须要指定不同的目录位置,不然会丢失数据)
(5)cluster-enabled yes(启动集群模式)
(6)cluster-config-file nodes-8001.conf(集群节点信息文件,这里800x最好和port对应上)
(7)cluster-node-timeout 10000
 (8)# bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)
 (9)protected-mode  no   (关闭保护模式,包含模式下只运行本机访问)
 (10)appendonly yes
如果要设置密码需要增加如下配置:
 (11)requirepass password     (设置redis访问密码)
 (12)masterauth password      (设置集群节点间访问密码,跟上面一致)

第三步:把修改后的配置文件,copy到8004,修改第2346项里的端口号,可以用批量替换::%s/源字符串/目的字符串/g 

第四步:另外两台机器也需要做上面几步操作,第二台机器用80028005,第三台机器用80038006

第五步:分别启动6个redis实例,然后检查是否启动成功
(1/usr/local/redis-5.0.3/src/redis-server /usr/local/redis-cluster/800*/redis.conf
(2)ps -ef | grep redis 查看是否启动成功
    
第六步:用redis-cli创建整个redis集群(redis5以前的版本集群是依靠ruby脚本redis-trib.rb实现)
# 下面命令里的1代表为每个创建的主服务器节点创建一个从服务器节点
# 执行这条命令需要确认三台机器之间的redis实例要能相互访问,可以先简单把所有机器防火墙关掉
# 如果不关闭防火墙则需要打开redis服务端口和集群节点gossip通信端口16379
# 关闭防火墙
# systemctl stop firewalld # 临时关闭防火墙
# systemctl disable firewalld # 禁止开机启动
(1/usr/local/redis-5.0.3/src/redis-cli -a password --cluster create --cluster-replicas 1 192.168.56.10:8001 192.168.56.11:8002 192.168.56.12:8003 192.168.56.10:8004 192.168.56.11:8005 192.168.56.12:8006 

第七步:验证集群:
(1)连接任意一个客户端即可:./redis-cli -c -h -p (-a访问服务端密码,-c表示集群模式,指定ip地址和端口号)
    如:/usr/local/redis-5.0.3/src/redis-cli -a password -c -h 192.168.56.10 -p 800*2)进行验证: cluster info(查看集群信息)、cluster nodes(查看节点列表)
(3)进行数据操作验证
(4)关闭集群则需要逐个进行关闭,使用命令:
/usr/local/redis-5.0.3/src/redis-cli -a password -c -h 192.168.56.10 -p 800* shutdown

Redis 集群原理分析

Redis Cluster 将所有数据划分为 16384 个 slots(槽位)【slot槽值的范围0-16383】,每个节点负责一部分槽位。当 Redis Cluster 的客户端来连接集群时,它也会得到一份集群的槽位配置信息并将其缓存在客户端本地。这样当客户端要查找某个 key 时,可以直接定位到目标节点。同时因为槽位的信息可能会存在客户端与服务器不一致的情况,还需要纠正机制来实现槽位信息的校验调整。

槽位定位算法

Redis Cluster 默认会对 key 值使用 crc16 算法进行 Hash 得到一个整数值,然后用这个整数值对 16384 进行取模来得到具体槽位(位运算)。HASH_SLOT = CRC16(key) & (16384 - 1)。
Redis Cluster还允许用户强制把某个key挂在特定槽位上,通过key字符串里面嵌入tag标记以此来强制key所挂的槽位等于tag所在的槽位。

跳转重定位

当客户端向一个错误的节点发出了指令,该节点会发现指令的 key 所在的槽位并不归自己管理,这时它会向客户端发送一个特殊的跳转指令携带目标操作的节点地址,告诉客户端去这个节点去获取数据。客户端收到指令后除了跳转到正确的节点上去操作,还会同步更新纠正本地的槽位映射表缓存,后续所有 key 将使用新的槽位映射表。【例如在某活动大促期间,增加了 Redis 集群服务器台数,将槽位分发给了这几个节点,将导致客户端缓存的槽位映射表不正确,从而指令错误】

Redis集群选举原理分析

当 slave 发现自己的 master 变为 FAIL 状态时,便尝试进行 Failover,以期成为新的 master。由于挂掉的 master 可能会有多个 slave,从而存在多个 slave 竞争成为 master 节点的过程, 其过程如下:

  1. slave 发现自己的 master 变为FAIL
  2. 将自己记录的集群 currentEpoch 加 1,并广播 FAILOVER_AUTH_REQUEST 信息
  3. 其他节点收到该信息,只有 master响应,判断请求者的合法性,并发送 FAILOVER_AUTH_ACK,对每一个 epoch 只发送一次 ack
    尝试 failover 的 slave 收集 master 返回的 FAILOVER_AUTH_ACK
  4. slave 收到超过半数 master 的 ack 后变成新 Master(集群为什么至少需要三个主节点,如果只有两个,当其中一个挂了,只剩一个主节点是不能选举成功的)
  5. slave 广播 Pong 消息通知其他集群节点。

从节点并不是在主节点一进入 FAIL 状态就马上尝试发起选举,而是有一定延迟,一定的延迟确保我们等待 FAIL状态在集群中传播,slave 如果立即尝试选举,其它 masters 或许尚未意识到 FAIL 状态,可能会拒绝投票。
延迟计算公式:DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms
SLAVE_RANK 表示此 slave 已经从 master 复制数据的总量的 Rank。Rank 越小代表已复制的数据越新。这种方式下,持有最新数据的slave将会首先发起选举(理论上)。

Redis集群对批量操作命令的支持

对于类似 mset,mget 这样的多个 key 的原生批量操作命令,redis 集群只支持所有 key 落在同一 slot 的情况,如果有多个 key 一定要用 mset 命令在 redis 集群上操作,则可以在 key 的前面加上 {XX},这样参数数据分片 hash 计算的只会是大括号里的值,这样能确保不同的 key 能落到同一 slot 里去,示例如下:

  mset {user1}:1:name zhuge {user1}:1:age 18

假设 name 和 age 计算的 hash slot 值不一样,但是这条命令在集群下执行,Redis 只会用大括号里的 user1 做hash slot计算,所以算出来的slot值肯定相同,最后都能落在同一slot。

集群进入fail状态的必要条件

1.如果集群任意master挂掉,且当前master没有slave,集群进入fail状态
2.某个主节点和所有从节点全部挂掉,我们集群就进入faill状态
3.如果集群超过半数以上master挂掉,无论是否有slave,集群进入fail状态

怎么判断某个节点的主机是否可以正常工作

通过心跳检测机制。
首先要说的是,每一个节点都存有这个集群所有主节点以及从节点的信息。它们之间通过互相的ping-pong判断是否节点可以连接上(心跳检测机制)。如果有一半以上的节点去ping一个节点的时候没有回应,集群就认为这个节点宕机了,然后去连接它的备用节点。

2. redis主从复制

Redis主从复制可以根据是否是全量分为全量同步和增量同步。

2.1 全量复制

Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
  1)Slave 连接Master ,发送SYNC命令;
  2)Master 接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件 , 同时将这之后新的写命令记入缓冲区;
  3)Master BGSAVE执行完后,向所有Slave 发送快照文件, 并继续记录写命令;
  4)Slave 收到快照文件后丢弃所有旧数据,载入收到的快照;
  5)Master 快照发送完毕后开始向Slave 发送缓冲区中的写命令;
  6)Slave 完成对快照的载入,开始接收命令请求,并执行来自Master 缓冲区的写命令;
  完成上面几个步骤后就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求。
  在这里插入图片描述

2.2 增量复制

增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

2.3 Redis主从同步策略

主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。

2.4 redis主从一致性

redis集群:https://blog.csdn.net/weixin_49352973/article/details/123058684

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值