概念
主从复制,是指将一台 Redis 服务器的数据,复制到其他的 redis 服务器;前者称为主节点(master、leader),后者称为从节点(slave、follower)
数据复制是单向的,只能从主节点到从节点
master 以写为主,slave 以读为主
默认情况下,每台 redis 服务器都是主节点
且一个主节点可以有多个从节点(或者没有从节点),但是一个从节点只能有一个主节点
主从复制的作用:
-
数据冗余
主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
-
故障恢复
当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际是一种服务的冗余
-
负载均衡
在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写 Redis 数据时,应用连接主节点;读 Redis 数据时,应用连接从节点),分担服务器负载;
尤其在写少读多的情况下,通过多个从节点分担读负载,可以大大提高 Redis 服务器的并发量
-
高可用(集群)基石
主从复制还是哨兵和集群能够实施的基础,因此,主从复制是 Redis 高可用的基础
一般来说,将 Redis 运用于工程项目中,只使用一台 Redis 是不可行的
原因如下:
-
从结构上,单个 Redis 服务器会发生单点故障,并且一台服务器需要处理所有的请求负载,压力较大
-
从容量上,单个 Redis 服务器内存容量有限,就算一台 Redis 服务器内存容量为 256G,也不能将所有内存用作 Redis 存储内存,一般来说,单个 Redis 最大使用内存不应该超过 20G
环境配置
只配置从库,不用配置主库
# 查看当前库的信息
127.0.0.1:6379> info replication
# Replication
role:master # 角色, master
connected_slaves:0 # 没有从机
master_replid:7f312e4fbe4d9748970dc198a265f11f9f5f27ea
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
复制 3 个配置文件,然后修改对应的信息:
- 端口号
- pid 名称
- log 文件名称
- dump.rdb 文件名称
[root@localhost zconfig]# cp redis.conf redis79.conf
[root@localhost zconfig]# cp redis.conf redis80.conf
[root@localhost zconfig]# cp redis.conf redis81.conf
[root@localhost zconfig]# ls
redis79.conf redis80.conf redis81.conf redis.conf
[root@localhost zconfig]# vim redis79.conf
[root@localhost zconfig]# vim redis80.conf
[root@localhost zconfig]# vim redis81.conf
修改完成后,启动 3 个 Redis,查看进程,可以看到三个进程
一主二从
默认情况下,每台 Redis 服务器都是主节点
只需要配置从机就行
一主(79)二从(80,81)
# 从机配置
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379 # 找主机,认老大
OK
127.0.0.1:6380> info replication
# Replication
role:slave # 角色,从机
master_host:127.0.0.1 # 主机信息
master_port:6379
master_link_status:up
master_last_io_seconds_ago:3
master_sync_in_progress:0
slave_repl_offset:0
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:643fa1ac45b9a37e157e6765b43deecb8603e32e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:0
# 再次查看主机信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:1 # 从机信息
slave0:ip=127.0.0.1,port=6380,state=online,offset=182,lag=0
master_replid:643fa1ac45b9a37e157e6765b43deecb8603e32e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:182
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:182
这里使用命令进行从机配置,只是暂时的!
真实的主从配置应该在配置文件中配置,这样的话,就是永久的
注意:
- 主机可以写,从机不可以写
- 主机中的所有信息和数据,都会自动被从机保存
主机:可读可写
从机:只读
主机断开连接,从机依旧连接到主机,但是没有写操作;如果主机回来了,从机依然可以直接获取到主机写的信息
如果使用命令行配置的主从,从机重启时,就会变回主机;只要再次变为主机,仍然可以从主机中获取值
复制原理
Slave 启动成功连接到 Master 后会发送一个 sync 同步命令
Master 接到命令后,启动后台的存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完之后,Master 将传送整个数据文件到 slave,并完成依次完成同步
-
全量复制:
slave 服务在接收到数据库文件数据后,将其存盘并加载到内存中
-
增量复制:
Master 继续将新的所有收集到的修改命令依次传给 slave ,完成同步
但是,只要重新连接 master,一次完成同步(全量复制)将自动被执行
谋朝篡位
如果主机(79)断开了连接,从机(80)可以使用 SLAVEOF no one
让自己变成主机
其他从机,就可以连到这个从机当从机(没有哨兵,需要手动设置)
如果这个时候,原来的主机(79)回来了,需要再次配置,才能再次变为其他从机的主机
哨兵模式
哨兵模式,是自动选举老大的模式
当主服务器宕机后,如果手动把一台从服务器切换为主服务器,需要人工干预,费时费力,还会造成一段时间内服务不可用
Redis 从 2.8 开始,正式提供了 Sentinel(哨兵) 架构来解决这个问题
哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行
其原理是:哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例
哨兵的作用
- 通过发送命令,让 Redis 服务器返回监控其运行状态,包括主服务器和从服务器
- 当哨兵检测到 master 宕机后,会自动将 slave 切换称 master ,然后通过 发布订阅模式 通知其他的主从服务器,修改配置文件,让他们切换主机
然而一个哨兵进程对 Redis 服务器进行监控,可能会出现问题;
为此,我们可以使用多个哨兵进行监控,各个哨兵之间还会进行监控,这样就形成了多哨兵模式
- 单机哨兵模式:
- 多哨兵模式:
假设服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行 failover 过程,仅仅是哨兵1主观地认为主服务器不可用,这个现象称为 主观下线
当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票结果由一个哨兵发起,进行 failover (故障转移)操作
切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为 客观下线
测试
- 配置哨兵配置文件 sentinel.conf
# sentinel monitor # 被监控的名称 host port 1
sentinel monitor myredis 127.0.0.1 6379 1
后面的数字 1 ,代表主机宕机后,slave 投票选择新的主机
票数最多的,就会称为主机
- 启动哨兵
[root@localhost bin]# redis-sentinel zconfig/sentinel.conf
25454:X 15 Mar 2021 18:47:07.295 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
25454:X 15 Mar 2021 18:47:07.295 # Redis version=5.0.7, bits=64, commit=00000000, modified=0, pid=25454, just started
25454:X 15 Mar 2021 18:47:07.295 # Configuration loaded
25454:X 15 Mar 2021 18:47:07.296 * Increased maximum number of open files to 10032 (it was originally set to 1024).
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 5.0.7 (00000000/0) 64 bit
.-`` .-```. ```\/ _.,_ ''-._
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 25454
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | http://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
25454:X 15 Mar 2021 18:47:07.297 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
25454:X 15 Mar 2021 18:47:07.298 # Sentinel ID is a1d1d329a18d993f4f49e382776d3dbcd1991de5
25454:X 15 Mar 2021 18:47:07.298 # +monitor master myredis 127.0.0.1 6379 quorum 1
25454:X 15 Mar 2021 18:47:07.299 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ myredis 127.0.0.1 6379
25454:X 15 Mar 2021 18:47:07.300 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ myredis 127.0.0.1 6379
如果主机宕机,就会从从机中,根据投票算法,选择一个新的主机
如果原来的主机回来了,只能归到新的主机下,当作从机,这就是哨兵的规则
优缺点
优点:
- 哨兵集群,基于主从复制模式,所有的主从配置优点,他都有
- 主从可以切换,故障可以转移,系统的可用性更好
- 哨兵模式就是主从模式的升级,手动到自动,更加健壮
缺点:
- Redis 不好在线扩容,集群容量一旦达到上限,在线扩容十分麻烦
- 实现哨兵模式的配置很麻烦
# Example sentinel.conf
# 哨兵 sentinel 实例运行的端口 默认 26379
port 26379
# 哨兵模式的工作目录
dir "/tmp"
# 哨兵 sentinel 监控的 redis 主节点的 ip port
# master-name 可以自己命名的主节点名字,只能由字母 A-Z、数字0-9,字符 “.-_” 组成
# quorum 配置多少个 sentinel 哨兵统一认为 master 主节点失联,那么此时就客观认为主节点失联
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 2
# 当在 Redis 实例中开启了 requirepass foobared 授权密码;这样所有连接 Redis 实例的客户端都要提供密码
# 设置哨兵 sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123
# 指定多少毫秒后,主节点没有应答哨兵 sentinel ,此时哨兵主观认为主机下线 默认 30s
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 1500
# 配置指定了在发生 failover 主备切换时,最多可以有多少个 slave 同时对新的 master 进行同步
# 数字越小,完成 failover 所需的时间越长
# 数字越大,越多的 slave 因为 replication 而不可用
# 可以设置为 1;保证每次只有一个 slave 处于不能处理命令滚请求的状态
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
# 故障转移的超时时间 failover-timeout应用在:
# 1、同一个 sentinel 对统一个 master 两次 failover 之间的间隔时间
# 2、当一个 slave 从一个错误的 master 同步数据开始计算时间,直到 slave 被纠正为向正确的 master 同步数据
# 3、当想要取消一个正在进行的 failover 所需时间
# 4、当进行 failover时,配置所有的 slave 执行新的 master 所需的最大时间
# 不过即使过了这个超时, slaves 依然会被正确配置为指向 master。但是就是不按照 parallel-syncs 所配置的规划来了
# Default is 3 minutes.
# sentinel parallel-syncs <master-name> <milliseconds>
sentinel failover-timeout mymaster 80000
protected-mode yes
# Specify the log file name. Also the empty string can be used to force
# Redis to log on the standard output. Note that if you use standard
# output for logging but zedaemonize, logs will be sent to /dev/null
logfile "/var/log/redis/sentinel.log"
daemonize yes
# SCRIPTS EXECUTION
#
# sentinel notification-script and sentinel reconfig-script are used in order
# to configure scripts that are called to notify the system administrator
# or to reconfigure clients after a failover. The scripts are executed
# with the following rules for error handling:
#
# If script exits with "1" the execution is retried later (up to a maximum
# number of times currently set to 10).
#
# If script exits with "2" (or an higher value) the script execution is
# not retried.
#
# If script terminates because it receives a signal the behavior is the same
# as exit code 1.
#
# A script has a maximum running time of 60 seconds. After this limit is
# reached the script is terminated with a SIGKILL and the execution retried.
# NOTIFICATION SCRIPT
#
# sentinel notification-script <master-name> <script-path>
#
# Call the specified notification script for any sentinel event that is
# generated in the WARNING level (for instance -sdown, -odown, and so forth).
# This script should notify the system administrator via email, SMS, or any
# other messaging system, that there is something wrong with the monitored
# Redis systems.
#
# The script is called with just two arguments: the first is the event type
# and the second the event description.
#
# The script must exist and be executable in order for sentinel to start if
# this option is provided.
#
# Example:
#
sentinel notification-script mymaster /var/redis/notify.sh
# CLIENTS RECONFIGURATION SCRIPT
#
# sentinel client-reconfig-script <master-name> <script-path>
#
# When the master changed because of a failover a script can be called in
# order to perform application-specific tasks to notify the clients that the
# configuration has changed and the master is at a different address.
#
# The following arguments are passed to the script:
#
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
#
# <state> is currently always "failover"
# <role> is either "leader" or "observer"
#
# The arguments from-ip, from-port, to-ip, to-port are used to communicate
# the old address of the master and the new address of the elected slave
# (now a master).
#
# This script should be resistant to multiple invocations.
#
# Example:
#
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh