redis主从复制(MasterReplicaset)、哨兵(Sentinel)、集群(Cluster)

本文深入解析Redis主从复制原理,包括全量复制、断点续传及哨兵系统的工作机制。同时,详细介绍了Redis集群的架构,数据分片、节点管理和高可用方案,为读者提供全面的Redis集群部署指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

主从复制

redis主从复制原理:

  1. 从库过slaveof命令并启动PSYNC命令发起主从复制的请求。如果是第一次连接主库,那么会触发一次全量复制;如果是重新连接主库,那么主库仅仅会发送从库部分数据。
  2. 主库收到PSYNC之后会立即触发BGSAVE后台保存RDB文件并发送给从库,RDB文件先保存在磁盘再从磁盘加载到内存中。如果所有从库与主库发生网络断线,会自动重连,此时主库发生多从库请求的情况下,主库仅仅会用一个RDB文件服务所有从库,并不会生成多份RDB文件。
  3. 主库陆续将产生写操作的命令缓存在内存中并发送给从库
    在这里插入图片描述

主从复制的"断点续传"

从redis2.8版本之后支持"断点续传"机制:在主从复制过程中 ,网络断开,那么可以接着上次复制的地方继续复制,而不是从头开始重新复制一份。主库会在内存中常建一个backlog,主库和从库都会保存一个replica offset,offset就是保存在backlog中的,backlog是一个等待队列,当有大量请求需要redis处理时,redis有可能处理不过来,所以用backlog来缓存等待的请求,backlog的数量决定了可以缓存的队列数。当主库和从库发生网络故障的时候,从库会让主库从上次offset的点继续复制,但是如果没有找到offset的话,那么会执行全量复制。

实验部署
redis 4.0.9
本实验以三个实例为环镜

mkdir /data/redisCluster/638{0,1}/{conf,log,pid} -p
cat >/data/redisCluster/638{0,1}/conf<<EOF
daemonize yes
#port 6380
port 6381
logfile /data/redisCluster/6381/log/redis.log
#logfile /data/redisCluster/6380/log/redis.log
dir /data/redisCluster/6381
#dir /data/redisCluster/6380
dbfilename dump.rdb
bind 192.168.8.19 127.0.0.1
pidfile /data/redisCluster/6381/pid/redis.pid
#pidfile /data/redisCluster/6380/pid/redis.pid
loglevel notice
masterauth 123
requirepass 123
EOF
#从库执行
redis-cli -a 123 -p 6380 slaveof 主库IP 主库PORT
#查看状态
redis-cli -a 123 -p 6379 info replication

注意::启用了主从复制master必须开启持久化,否则master宕机、重启是没有本地数据可以恢复的,然后就会直接认为数据是空的同步到slave上导致slave的数据全部清空。主从复制也可以直接在需要作为从库的服务器的配置文件中直接设置。

哨兵

redis的哨兵系统用于管理多个redis服务器(实例),该系统执行以下三个任务:

  • 监控(Monitoring):sentinel会不断地检查主服务器和从服务器是否运作正常。
  • 通知(Notification):当被监控的某个服务器出现问题时,sentinel可以通过API向管理员或者其它应用程序发送通知。
  • 自动故障转移(Automatic failover):当一个主服务器不能正常工作时,sentinel会开始一次自动故障迁移操作,它会将失效主节点的其中一个节点升级为主服务器,并让失效节点的其它从节点改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新服务器的地址,使得集群可以使用新主服务器代替失效的服务器。

sentinel是一个分布式系统,可以在一个架构中运行多个sentinel进程,这些进程使用流言协议(gossip protocols) 来接收关于主服务器是否下线的信息,并使用投票协议(agreement protocols) 来决定是否执行自动故障转移以及选择哪个从服务器代替失效服务器。

配置sentinel:(每台物理服务器配置sentinel)

vim /data/26380/sentinel.conf
bind 127.0.0.1
daemonize yes
port 26380
dir "/data/26380"
logfile /var/log/redis-sentinel.log
sentinel monitor mymaster 127.0.0.1 6379 2 #表示有两台以的sentinel认为某一台redis宕机后,才会进行自动故障转移。
sentinel down-after-milliseconds mymaster 5000
sentinel auth-pass mymaster 123
sentinel failover-timeout mymaster 180000
# 对于sentinel程序启动
redis-sentinel /path/to/sentinel.conf 
#对于server程序启动
redis-server /path/to/sentinel.conf --sentinel 

高可用方案:主从复制+哨兵

  • 至少三个sentinel以上
  • sentinel要分散运行在不同的机器上

python客户端配置使用:

# redis 哨兵
REDIS_SENTINELS = [
    ('127.0.0.1', '26380'),
    ('127.0.0.1', '26381'),
    ('127.0.0.1', '26382'),
]
REDIS_SENTINEL_SERVICE_NAME = 'mymaster'

from redis.sentinel import Sentinel
_sentinel = Sentinel(REDIS_SENTINELS)
redis_master = _sentinel.master_for(REDIS_SENTINEL_SERVICE_NAME)
redis_slave = _sentinel.slave_for(REDIS_SENTINEL_SERVICE_NAME)

集群

集群是一个可以在多个redis节点之间进行数据共享的设施,它不仅支持那些需要同时处理多个键的redis命令,因为执行这些命令需要在多个redis节点之间移动数据,并且在高负载的情况下,这些命令会降低redis集群的性能。redis集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命令请求。
redis集群提供了以下两个好处:

  • 将数据自动切分(split)到多个节点的能力
  • 当集群中的一部分节点失效或者无法通信仍可以继续处理命令的请求

集群数据共享

redis集群使用数据分片(shardinng)而非一致性哈希(consistency hashing)来实现:一个redis集群包含16384个哈希槽(hash slot),数据库中的每个键都属于这个16384个哈希槽的其中一个,集群使用公式CRC16(key)%16384来计算key属于哪个槽,其中CRC16(key)语句用于计算key的CRC16校验和。
集群中的每个节点负责处理一部分哈希槽。举个例子,一个集群中有三个哈希槽,其中:

  • a节点负责处理0-5500号哈希槽。
  • b节点负责处理5501-11000号哈希槽。
  • c节点负责处理11001-16383号哈希槽。

这种将哈希槽分不到不同节点的做法使得用户可以很容易地向集群中添加或者删除节点。比如说:

  • 如果用户将新节点d添加到集群中,那么集群只需要将a、b、c中的某些槽移动到节点d就可以了
  • 与此类似,如果用户要从集群中移除节点a,那么集群只需要将节点a中的所有哈希槽移动到节点b和节点c,然后再移除空白(不包含任何哈希槽)的节点a就可以了。

因为将一个哈希槽从一个节点移动到另一个节点不会造成节点阻塞,所以无论是添加节点还是移除节已存在的节点,又或者改变某个节点包含的哈希槽数量,都不会造成集群下线。

集群搭建

  • 准备安装环境
yum install -y ruby rubygems
gem source -a https://mirrors.aliyun.com/rubygems/
gem source --remove https://rubygems.org/
gem sources -l
gem install redis -v x.x.x
  • 修改配置文件 (本集群采用一台虚拟机部署6个节点)
[root@rds-0]# vim /usr/local/data/7001/conf/redis_7001.conf
daemonize yes
port 7001
pidfile "/usr/local/data/7001/redis_7001.pid"
loglevel notice
logfile "/usr/local/data/7001/redis_7001.log"
dbfilename dump.rdb
dir "/usr/local/data/7001"
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
[root@rds-0]# vim /usr/local/data/7002/conf/redis_7002.conf
daemonize yes
port 7002
pidfile "/usr/local/data/7002/redis_7002.pid"
loglevel notice
logfile "/usr/local/data/7002/redis_7002.log"
dbfilename dump.rdb
dir "/usr/local/data/7002"
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

剩下6个节点的配置文件主要是端口号的替换。

  • 全部启动redis服务
[root@rds-0]# redis-server /usr/local/data/700{1..6}/conf/redis_{1..6}.conf
[root@rds-0]# tail -f /usr/local/data/700{1..6}/conf/redis_{1..6}.conf
  • 创建集群
# 
redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006
# 

注意: –replicas 1 表示master/slave节点数的比例。按照命令中IP:PORT的顺序,先是3个主节点,然后是3个从节点。(123为master节点,456为slave节点,一一对应);

在这里插入图片描述

  • 登录、操作集群
# 随便登录一个节点就可以操作集群了
redis-cli -c -p 7001
  • 查看集群信息
127.0.0.1:6379> CLUSTER INFO
  • 列出节点信息
127.0.0.1:6379> cluster nodes 

添加一个master节点:

创建配置文件然后启动该节点:

[root@rds-0]# vim /usr/local/data/7007/conf/redis_7002.conf
daemonize yes
port 7007
pidfile "/usr/local/data/7002/redis_7007.pid"
loglevel notice
logfile "/usr/local/data/7007/redis_7007.log"
dbfilename dump.rdb
dir "/usr/local/data/7007"
protected-mode no
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes


[root@rds-0]# redis-server /usr/local/data/7007/conf/redis_7002.conf
[root@rds-0]# tail -f /usr/local/data/7007/redis_7007.log
[root@rds-0]# redis-trib.rb add-node 127.0.0.1:7007 127.0.0.1:7001 //把7007加入到7001的集群当中
也可以在redis命令行中执行:
127.0.0.1:6379> cluster meet IP 7007
查看:
127.0.0.1:6379> CLUSTER NODES
  • 将 A服务器新增(7010.conf)的身份改为B服务器(7011.conf)的slave
[root@redis-2 ~]# redis-cli -c -h A服务器IP -p 7010 cluster replicate B的node_id(通过CLUSTER NODES命令查看)

在这里插入图片描述
上图可以看到添加完成后是不起作用的,因为没分配哈希槽。接下来对master节点重新分片:

redis-trib.rb reshard 127.0.0.1:7001

输入all后再次输入yes成功添加master节点。
在这里插入图片描述

  • 添加一个slave节点
redis-trib.rb add-node --slave --master-id 24abb63c8840dd4b26b0bdb06645e9c97da814f0 127.0.0.1:7008 127.0.0.1:7001
  • 删除节点
    删除节点之前先reshard移除master的全部哈希槽:
redis-trib.rb reshard 127.0.0.1:7001
redis-trib.rb del-node 127.0.0.1:7007 7467e9b12ec7c4dcc08c916a0bc8666e4470ecaf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值