redis--主从复制

11 篇文章 0 订阅

虽然Redis可以实现单机的数据持久化,但无论是RDB也好或者AOF也好,都解决不了单点宕机问题,即一旦单台 redis服务器本身出现系统故障、硬件故障等问题后,就会直接造成数据的丢失
此外,单机的性能也是有极限的,因此需要使用另外的技术来解决单点故障和性能扩展的问题。

主从复制

架构

主备模式,可以实现Redis数据的跨主机备份。
程序端连接到高可用负载的VIP,然后连接到负载服务器设置的Redis后端real server,此模式不需要在程序里面配置Redis服务器的真实IP地址,当后期Redis服务器IP地址发生变更只需要更改redis 相应的后端real server即可,可避免更改程序中的IP地址设置

特点

  • 一个master可以有多个slave
  • 一个slave只能有一个master
  • 数据流向是单向的,master到slave

实现

Redis Slave 也要开启持久化并设置和master同样的连接密码,因为后期slave会有提升为master的可能,Slave端切换master同步后会丢失之前的所有数据。
一旦某个Slave成为一个master的slave,Redis Slave服务会清空当前redis服务器上的所有数据并将master的数据导入到自己的内存,但是断开同步关系后不会删除当前已经同步过的数据。

当配置Redis复制功能时,强烈建议打开主服务器的持久化功能。否则的话,由于延迟等问题,部署的服务应该要避免自动启动 

参考案例: 导致主从服务器数据全部丢失

1.假设节点A为主服务器,并且关闭了持久化。并且节点B和节点c从节点A复制数据
2.节点A崩溃,然后由自动拉起服务重启了节点A.由于节点A的持久化被关闭了,所以重启之后没有任何数据
3.节点B和节点c将从节点A复制数据,但是A的数据是空的,于是就把自身保存的数据副本删除

在关闭主服务器上的持久化,并同时开启自动拉起进程的情况下,即便使用Sentinel来实现Redis的高可用性,也是非常危险的。因为主服务器可能拉起得非常快,以至于Sentinel在配置的心跳时间间隔内没有检测到主服务器已被重启,然后还是会执行上面的数据丢失的流程。无论何时,数据安全都是极其重要的,所以应该禁止主服务器关闭持久化的同时自动启动。 

命令行配置

重启失效

slave配置


127.0.0.1:6379> replicaof 192.168.148.158 6379
OK
127.0.0.1:6379> config set masterauth 123456
OK
127.0.0.1:6379> info replication
# Replication
role:slave
master_host:192.168.148.157  地址
master_port:6379   端口
master_link_status:up  状态
master_last_io_seconds_ago:6 最后一次与master通信时间,不会超过10s
master_sync_in_progress:0  
slave_read_repl_offset:4076
slave_repl_offset:4076
slave_priority:100  slave优先级,选择哨兵
slave_read_only:1
replica_announced:1
connected_slaves:0
master_failover_state:no-failover
master_replid:e121a5c378b2218a8ba6ffa04a04eeedb4712541
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:4076
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:4076

master配置

127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:0
master_failover_state:no-failover
master_replid:c04ede694cf84176af85d5460db13fab09df6097
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6379> 

测试

master

127.0.0.1:6379> set hello redis
OK
127.0.0.1:6379> get hello
"redis"

slave

127.0.0.1:6379> get hello
"redis"

slave日志文件

认证失败

 解决:

127.0.0.1:6379> config set masterauth 123456
OK

 首次同步

确认slave的密码正确,允许同步
1535:S 23 May 2024 11:56:28.545 * MASTER <-> REPLICA sync started
1535:S 23 May 2024 11:56:28.545 * Non blocking connect for SYNC fired the event.
1535:S 23 May 2024 11:56:28.545 * Master replied to PING, replication can continue...
尝试同步增量服务
增量服务:通过位置指定,master增加增加数据,slave会在原来基础上进行与master进行相同操作
1535:S 23 May 2024 11:56:28.548 * Partial resynchronization not possible (no cached master)

127.0.0.1:6379> info replication
master_repl_offset:2242 记录master和slave同步位置
第一次同步没有同步数据,全量服务
1535:S 23 May 2024 11:56:28.549 * Full resync from master: e121a5c378b2218a8ba6ffa04a04eeedb4712541:0  生成master的id并从0位置开始同步数据
1535:S 23 May 2024 11:56:28.679 * MASTER <-> REPLICA sync: receiving 196 bytes from master to disk   执行rdb快照发送给slave节点大小196 bytes
1535:S 23 May 2024 11:56:28.679 * MASTER <-> REPLICA sync: Flushing old data 格式化数据库
1535:S 23 May 2024 11:56:28.679 * MASTER <-> REPLICA sync: Loading DB in memory 在内存中加载数据

后台rdb过程

master日志文件

文件配置

修改redis.conf文件

replicaof 192.168.148.157 6379
masterauth 123456

修改后重启

 slave状态只读不能写入数据

 主从复制过程

Redis支持主从复制分为全量同步和增量同步,首次同步是全量同步,主从同步可以让从服务器从主服务器备份数据,而且从服务器还可与有从服务器,即另外一台redis服务器可以从一台从服务器进行数据同步,redis 的主从同步是非阻塞的,master收到从服务器的sync(2.8版本之前是PSYNC)命令会fork一个子进程在后台执行bgsave命令,并将新写入的数据写入到一个缓冲区里面,bgsave执行完成之后并生成的将RDB文件发送给客户端,客户端将收到后的RDB文件载入自己的内存,然后redis master再将缓冲区的内容在全部发送给redis slave,之后的同步slave服务器会发送一个offset的位置(等同于MySQL的binlog的位置)给主服务器,主服务器检查后位置没有错误将此位置之后的数据包括写在缓冲区的积压数据发送给redis从服务器,从服务器将主服务器发送的导入数据写入内存,这样一次完整的数据同步,再之后再同步的时候从服务器只要发送当前的offset位 置给主服务器,然后主服务器根据相应的位置将之后的数据发送给从服务器保存到其内存即可

Redis全量复制一般发生在Slave首次初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体主从同步骤如下:

1)从服务器连接主服务器,发送SYNC命令;
2)主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB快照文件并使用缓冲区记录此后执行的所有写命令;
3)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令;
6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
7)后期同步会先发送自己slave_repl_offset位置,只同步新增加的数据,不再全量同步。

全量同步图解

增量同步图解

 redis优化

Redis在2.8版本之前没有提供增量部分复制的功能,当网络闪断或者slave Redis重启之后会导致主从之间的全量同步,即从2.8版本开始增加了部分复制的功能


repl-diskless-sync no # 是否使用无盘同步RDB文件,默认为no,no为不使用无盘,需要将RDB文件保存到磁盘后再发送给slave,yes为支持无盘,支持无盘就是RDB文件不需要保存至本地磁盘,而且直接通过socket文件发送给slave。

repl-diskless-sync-delay 5 #Master准备好RDB文件后等等待传输时间

repl-ping-slave-period 10 #slave端向server端发送ping的时间区间设置,默认为10秒

repl-timeout 60 #设置超时时间


repl-disable-tcp-nodelay no #是否启用TCP_NODELAY,如设置成yes,则redis会合并小的TCP包从而节省带宽,但会增加同步延迟(40ms),造成master与slave数据不一致,假如设置成no,则redis master会立即发送同步数据,没有延迟,前者关注性能,后者关注redis服务中的数据一致性。


repl-backlog-size 1mb #master的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:repl-backlog-size = 允许从节点最大中断时长 * 主实例offset每秒写入量,比如master每秒最大写入64mb,最大允许60秒,那么就要设置64mb*60秒=3840MB(3.8G)


repl-backlog-ttl 3600 #如果一段时间后没有slave连接到master,则backlog size的内存将会被释放。如果值为0则表示永远不释放这部份内存。

slave-priority 100 #slave端的优先级设置,值是一个整数,数字越小表示优先级越高。当master故障时将会按照优先级来选择slave端进行恢复,如果值设置为0,则表示该slave永远不会被选择。


#min-slaves-to-write 1 #设置一个master端的可用slave少于多少个

#min-slaves-max-lag 20 #设置所有slave延迟时间都大于多少秒时,master不接收写操作(拒绝写入)。

slave切换master

关闭master节点

查看slave节点

 slave节点变为master节点

127.0.0.1:6379> slaveof no one 
OK

永久修改

在redis.conf文件中注释掉
replicaof 192.168.148.157 6379
masterauth 123456

注意

  1. master和slave之间必须保持版本一致
  2. 在开启了安全模式情况下,设置bind地址或者密码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值