概念
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。即主机以写为主,从机以读为主。
默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
核心思想:主从复制,读写分离!
主从复制的作用
主从复制的作用主要包括:
- 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
- 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
- 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
- 高可用(集群)基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
一般来说,要把redis运用到项目中,只是用一台redis是万万不能的(至少一主二从),原因如下:
- 从结构上,单个服务器会发生单点故障,并且一台服务器负载的压力也是巨大的
- 从容量上,就算服务器的内存很大,但也不能把内存都用来执行redis。一般来说,单台redis的最大使用内存不应该超过20G。
环境配置
127.0.0.1:6379> info replication #查看主机的主从复制信息
# Replication
role:master #角色是主机
connected_slaves:0 #从机个数为0
master_replid:2eb56abfc3afe3ba188c0031238688adbc10e71c
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
复制两个配置文件作为从机的配置文件,修改其内容:
- 端口号
- log日志文件名
- pid名字
- dump.rdb名字
启动三个redis服务:
一主二从
一般来说,只配置从机,不用配置主机
一主(6379),二从(6380,6381)
命令行配置
#第一台从机
127.0.0.1:6380> slaveof 127.0.0.1 6379
OK
127.0.0.1:6380> info replication #查看replication信息
# Replication
role:slave #角色为从机
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:7
master_sync_in_progress:0
slave_repl_offset:14
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:a6ca5374489f32541ac14603b170286f6e0cb6cb
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
#第二台从机
127.0.0.1:6381> slaveof 127.0.0.1 6379
OK
127.0.0.1:6381> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6379
master_link_status:up
master_last_io_seconds_ago:6
master_sync_in_progress:0
slave_repl_offset:404
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:a6ca5374489f32541ac14603b170286f6e0cb6cb
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:404
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:405
repl_backlog_histlen:0
#主机中查看
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2 #拥有两台从机
slave0:ip=127.0.0.1,port=6380,state=online,offset=418,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=418,lag=0
master_replid:a6ca5374489f32541ac14603b170286f6e0cb6cb
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:418
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:418
真实的主从配置应该在配置文件中配置,这样才能持久,而命令行配置只能是暂时的。
细节
主机可以写,从机不能写只能读!主机中的信息都会被从机保存
主机可以写!
从机只能读!
测试:
主机宕机,从机依旧连接到主机,能够读,但是没有写操作。一旦主机连上,从机依旧可以直接获取主机写的信息;
如果是使用的命令行配置的主从,那么从机重启之后就会变成主机(因为reids服务器默认是主节点),一旦变为从机,就能从主机中获得值。
复制原理
slave启动成功连接到master后会发送一个sync信号,master接收到信号之后,启动后台的存盘进程,同时收集所有的修改数据集的命令,在后台进程执行完毕后(命令执行完毕),master将传送整个数据文件给slave,完成一次完全同步
全量复制:slave在收到master传送的数据文件之后,将其全盘加载到内存当中
增量复制:master继续收集修改数据集命令依次传送给slave,完成同步
只要是从机重新连接主机,那么一次完全同步(全量复制)将会被自动执行!
主从复制的级联模型
主从复制也可以有另外一种模型
这时,slave01依旧是从节点,只能读不能写
如果主机宕机了,在哨兵模式还没出来之前,我们可以手动将slave01变成主机
127.0.0.1:6380> slaveof no one #s从机变为主机
OK
127.0.0.1:6380> info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=6381,state=online,offset=84,lag=1
master_replid:3f3c6ad875be94610da3d123a407b946905c43ac
master_replid2:c7041162d151e84dd6bfba93c935b4a29f887c19
master_repl_offset:84
second_repl_offset:85
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:84
哨兵模式(Sentinel)
概述
主从切换技术的方法是:当主机宕机之后,我们需要手动将从机变为主机,这就需要认为干预,比较费时费力。这并不是推荐的方式。从redis2.8开始正式提供Sentinel(哨兵模式)来实现集群主从切换
哨兵模式能够后台监控主机是否故障,如果故障就根据投票数自动将从机转换为主机
哨兵模式是一种特殊的模式,redis提供了哨兵模式的命令,哨兵是一个独立的进程,它的原理是:哨兵通过给redis服务器发送命令,等待redis回应,从而监控多个运行的redis实例
这里的哨兵有两个作用:
- 通过发送命令,让redis服务器返回其运行状态,包括主机和从机
- 当哨兵检测到master宕机,会自动将slave切换为master,并通过发布订阅模式通知其他从机,修改配置文件,让它们切换主机
然而一个哨兵进程对redis服务器进行监控可能会出现问题,所以我们需要配置多个哨兵,在监控redis服务器的同时,让哨兵与哨兵之间也互相监控,多哨兵也可以成为一个集群
假设主机宕机了,哨兵1发现了这个结果,但系统不会马上failover(故障转移),这仅仅是哨兵1的主观认为,这个现象称为主观下线,当后面的哨兵也发现这个主机不可用,并且数量达到一定值时,哨兵之间就会进行一次投票(投票算法),选取一个从机来当主机。投票的结果由一个哨兵发起,进行failover操作。主从切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的服务器实现切换主机,这个过程称为客观下线。
测试
目前的状态是一主二从
-
配置哨兵配置文件sentinel.conf
#sentinel monitor 哨兵监控 myredis-master 名字 127.0.0.1 6379 主机ip,port 1代表这是一个主机 sentinel monitor myredis-master 127.0.0.1 6379 1
-
redis-sentinel开启哨兵模式
zyj@zyj-B365M-D2VX-SI:/usr/local/bin/zyjconfig$ sudo redis-sentinel sentinel.conf 21705:X 24 Sep 2020 21:19:38.399 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 21705:X 24 Sep 2020 21:19:38.399 # Redis version=6.0.8, bits=64, commit=00000000, modified=0, pid=21705, just started 21705:X 24 Sep 2020 21:19:38.399 # Configuration loaded 21705:X 24 Sep 2020 21:19:38.399 * Increased maximum number of open files to 10032 (it was originally set to 1024). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 6.0.8 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in sentinel mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 26379 | `-._ `._ / _.-' | PID: 21705 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 21705:X 24 Sep 2020 21:19:38.453 # Sentinel ID is 316402f67107b49632d3024526ed6a1cbff0c16f 21705:X 24 Sep 2020 21:19:38.453 # +monitor master myredis-master 127.0.0.1 6379 quorum 1 21705:X 24 Sep 2020 21:19:38.453 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:19:38.477 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis-master 127.0.0.1 6379
测试:主机意外宕机!
等待一会儿,查看哨兵日志:
21705:X 24 Sep 2020 21:22:27.508 # +sdown master myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:27.509 # +odown master myredis-master 127.0.0.1 6379 #quorum 1/1 21705:X 24 Sep 2020 21:22:27.509 # +new-epoch 1 21705:X 24 Sep 2020 21:22:27.509 # +try-failover master myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:27.551 # +vote-for-leader 316402f67107b49632d3024526ed6a1cbff0c16f 1 21705:X 24 Sep 2020 21:22:27.551 # +elected-leader master myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:27.551 # +failover-state-select-slave master myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:27.651 # +selected-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:27.651 * +failover-state-send-slaveof-noone slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:27.706 * +failover-state-wait-promotion slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:28.093 # +promoted-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:28.093 # +failover-state-reconf-slaves master myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:28.125 * +slave-reconf-sent slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:29.103 * +slave-reconf-inprog slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:29.103 * +slave-reconf-done slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:29.159 # +failover-end master myredis-master 127.0.0.1 6379 21705:X 24 Sep 2020 21:22:29.159 # +switch-master myredis-master 127.0.0.1 6379 127.0.0.1 6380 21705:X 24 Sep 2020 21:22:29.159 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis-master 127.0.0.1 6380 21705:X 24 Sep 2020 21:22:29.159 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ myredis-master 127.0.0.1 6380
可以看到哨兵监控到主机宕机之后,故障转移,并选取了127.0.0.1:6380的从机作为主机(选择哪个从机作为主机有一个投票算法)127.0.0.1:6380> info replication # Replication role:master connected_slaves:1 slave0:ip=127.0.0.1,port=6381,state=online,offset=23519,lag=0 master_replid:fad23481b4faed8651d8836b9ebe623e25bf06f6 master_replid2:c7041162d151e84dd6bfba93c935b4a29f887c19 master_repl_offset:23519 second_repl_offset:12584 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:85 repl_backlog_histlen:23435
就算此时,之前的主机6379重启了,也只能当新主机的从机!
哨兵日志:
哨兵模式的优缺点
优点:
- 哨兵集群,基于主从复制模式,所有的主从复制优点,他都有
- 主从可以切换,故障可以转移,系统的可用性就会很好
- 哨兵模式是主从模式的升级版,手动到自动
缺点:
- redis不好在线扩容,集群容量一旦到达上限,在线扩容就会很麻烦
- 实现哨兵模式的配置其实是很麻烦的,里面有很多选择
哨兵模式的全部配置
#哨兵端口 默认26379
port 26379
#哨兵sentinel的工作目录
dir /tmp
#哨兵监控的redis主节点
#master-name 自定义的主节点名字
#quorum 配置多少个哨兵统一认为master主节点失联,就客观认为主节点失联
#sentinel monitor <master-name> <ip> <port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
#主节点的授权密码
#sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 1234
#指定多少毫秒后,主节点没有应答哨兵,哨兵就认为主节点失联 默认30秒
sentinel down-after-milliseconds mymaster 30000
#这个配置指定了在发生failover主从切换时最多可以由多少个slave同时新的master进行同步
这个数字越小,完成failover的时间就越长;数字越大,就意味着多的slave因为replication而不可用
可以通过设置为1来保证每次只有一个slave处于不能处理客户端请求的状态
#sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
#设置故障转移的超时时间
#默认3分钟
#sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员
#对于脚本的运行结果有以下规则:
#若脚本执行返回1,那么脚本稍后会被再次执行,默认重复执行次数为10
#若脚本执行返回2或者比2更大,脚本将不会重复执行
#如果脚本在执行过程中被系统中断,则同执行返回1一样
#一个脚本的最大执行时间是60秒,如果超过这个时间,脚本会被一个SIGKILL的信号终止,然后重新执行
#通知型脚本:当哨兵有任何警告级别的事件发生时,如redis实例的主观失效和客观失效,就会调用这个脚本。这时,脚本应该通过邮件,SMS等方式通知系统管理员。调用脚本时,传给脚本两个参数,一个是事件的类型,一个事件的描述。如果这条配置不是可执行的,那么哨兵无法启动成功
#sentinel notification-script <master-name> <scirpt-path>
sentinel notification-script mymaster /var/redis/notify.sh
#客户端重新配置主节点参数脚本
#当一个主机由于failover而发生改变时,这个脚本将会被调用,通知相关客户端关于master地址已经发生改变的信息
#以下参数将在调用时传给脚本:
#<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
#<state>目前是failover
#<role>是leader或者observer中的一个
#<from-ip> <from-port> 旧master <to-ip> <to-port> 新master
#这个脚本应该是通用的,能被多次调用,不是针对性的
#sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh