什么是复制
单机的redis通常情况是无法满足项目需求的,一般都建议使用集群部署的方式进行数据的多机备份和部署,这样既可以保证数据安全,同时在redis宕机的时候,复制也可以对于数据进行快速的修复。
采取的方式
- 单机部署(忽略)
- 主从链
- 一主多从
- 哨兵模式
- 集群模式
复制的前提
- 需要保证
redis.conf
里面的配置是正确的,比如:
dir ./ dbfilename "dump.rdb" 复制代码
- 需要保证指定的路径对于redis来说是可写的,意味着如果当前目录没有写权限同样会失败
从服务器连接主服务器的几种方式
- 在从服务器的配置文件里面配置连接那个主服务器:
连接的具体配置如下:
在5.0版本中使用了
replicaof
代替了slaveof
(github.com/antirez/red…),slaveof
还可以继续使用,不过建议使用replicaof
下面是个人的配置
# replicaof <masterip> <masterport> replicaof 127.0.0.1 16379 复制代码
警告:此小节只说明了这一个配置的更改,进行主从配置的时候还有其他几个参数需要更改,这里只作为部分内容参考
- 在启动的适合,在redis从服务器的redis-cli当中敲击如下的命令:
127.0.0.1:16380> slaveof 127.0.0.1 16379 OK Already connected to specified master 复制代码
这样就可以在从服务器动态的指定要连接哪个主服务器了,但是这种配置是当前运行时有效,下次再次进入的时候,会根据配置文件进行配置或者按照默认的规则当前实例就是master3.
- 在从服务器执行
slaveof no one
,当前实例脱离控制自动成为master
redis 复制启动的过程==(重点)==
主服务器操作 | 从服务器操作 |
1. (等待命令) | 1. 连接(重新连接)主服务器,发送sync命令 |
2. 开始执行bgsave,使用缓冲区记录bgsave之后执行所有写命令 | 2. 根据配置选项是使用现有的数据(存在)处理客户端请求,还是向请求的客户端返回错误信息 |
3. bgsave执行完毕,向从服务器发送快照文件,同时异步执行缓冲区记录的写命令 | 3. 丢弃所有的旧数据,载入主服务器的快照文件 |
4. 快照文件发送完毕,开始向着从服务器发送存储在缓冲区的写命令 | 4. 完成对于快照的解释操作,恢复日常的请求操作 |
5. 缓冲区写命令发送完成,同时现在每执行一个写命令就像从服务器发送相同写命令 | 5. 执行主服务器发来的所有存储在缓冲区的写命令,并且从现在开始接受主服务器的每一个命令 |
建议:由于bgsave需要开启进行子线程的创建写入缓冲区的创建,所以最好在系统中预留30% - 45% 内存用于redis的bgsave操作
特别注意:当从服务器连接主服务器的那一刻,执行到第三步会清空当前redis里面的所有数据。
配置方式和命令方式的区别:
redis.conf 配置slaveof 的方式:不会马上进行主服务器同步,而是先载入当前本地存在的rdb或者aof到redis中进行数据恢复,然后才开始同步复制
命令slaveof方式:会立即连接主服务器进行同步操作
关于redis的主主复制:
如果我们尝试让两台服务器互相slaveof 那么会出现上面情况呢?
从上面的复制过程可以看到,当一个服务器slaveof另一个服务器,产生的结果只会是两边相互覆盖,也就是从服务器会去同步主服务器的数据,如果此时按照主主的配置,两边互相同步对方的数据,这样产生的数据可能会不一致,或者数据干脆就是不完整的。不仅如此,这种操作还会大量占用资源区让两台服务器互相知道对方
当一台服务器连接另一台服务器的时候会发生什么?
当有新服务器连接的时候 | 主服务器操作 |
步骤3还没有执行 | 所有从服务器都会收到相同的快照文件和相同缓冲区写命令 |
步骤3正在执行或者已经执行 | 完成了之前同步的五个操作之后,会跟新服务器重新执行一次新的五个步骤 |
系统故障处理
复制和持久化虽然已经基本可以保证系统的数据安全,但是总有意外的情况,比如突然断电断网,系统磁盘故障,服务器宕机等一系列情况,那么会出现各种莫名奇妙的问题,下面针对这些情况说明一下解决方式:
验证快照文件以及aof文件
在redis的bin
目录下面,存在如下的两个sh
-rwxr-xr-x 1 root root 9722168 Nov 15 20:53 redis-check-aof -rwxr-xr-x 1 root root 9722168 Nov 15 20:53 redis-check-rdb 复制代码
他们的命令作用和内容如下:
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ ./redis-check-aof Usage: ./redis-check-aof [--fix] <file.aof> [xd@iZwz99gyct1a1rh6iblyucZ bin]$ ./redis-check-rdb Usage: ./redis-check-rdb <rdb-file-name> 复制代码
redis-check-aof:如果加入--fix
选项,那么命令会尝试修复aof文件,会将内容里面出现错误的命令以及下面的所有命令清空,一般情况下回清空尾部的一些未完成命令。
redis-check-rdb:遗憾的是目前这种修复收效甚微。建议在修复rdb的时候,用SHA1和SHA256验证文件是否完整。
校验和与散列值:
redis2.6 之后加入了校验和与散列值进行验证。
快照文件增加CRC64校验和
什么是crc循环冗余校验?
更换故障主服务器:
- 假设A故障,存在BC两台机器,B为从服务,C为将要替换的主服务器
- 向机器B发送save命令,同时创建一个新的快照文件,同步完成之后,发送给C
- 机器C上面启动redis,让C成为B的主服务器
Redis sentienel 哨兵
可以监视指定主服务器以及属下的从服务器
也就是我们常用的哨兵模式
但是随着时代进步,目前使用redis基本还是以cluster模式
为主
redis主从复制模式(redis6.0版本):
前提说明:
有条件的可以弄三台虚拟机查看效果,这样模拟出来的效果算是比较真实的。
三台从服务器以及一台主服务器的配置
个人的办法是copy一个公用的配置,然后进行修改(这里只列举区别以及改动较多的地方,其他地方根据需要配置):
第一台机器的配置:
pidfile /var/run/redis_16379.pid port 16379 dbfilename dump16379.rdb appendfilename "appendonly16379.aof" logfile "log16379" 复制代码
第二台机器的配置:
pidfile /var/run/redis_16380.pid port 16380 dbfilename dump16380.rdb appendfilename "appendonly16380.aof" logfile "log16380" 复制代码
第三台机器的配置:
pidfile /var/run/redis_16381.pid port 16381 dbfilename dump16381.rdb appendfilename "appendonly16381.aof" logfile "log16381" 复制代码
这时候要配置一台主服务器
pidfile /var/run/redis_10000.pid port 10000 dbfilename dump10000.rdb appendfilename "appendonly10000.aof" logfile "log10000" 复制代码
启动redis一主多从:
配置很简单,可以用手动进行主从复制,也可以使用redis.conf提前配置,具体区别上文已经进行过介绍,这里不再赘述。
从服务器可以通过命令:slaveof 127.0.0.1 10000
实现主从复制拷贝
可以通过命令info replication
查看主从配置的信息。
主服务器启动日志:
127.0.0.1:10000> info replication # Replication role:master connected_slaves:0 master_replid:e2a92d8c59fbdde3b162da12f4d74ff28bab4fbb 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:10000> info replication # Replication role:master connected_slaves:3 slave0:ip=127.0.0.1,port=16381,state=online,offset=14,lag=1 slave1:ip=127.0.0.1,port=16380,state=online,offset=14,lag=1 slave2:ip=127.0.0.1,port=16379,state=online,offset=14,lag=1 master_replid:029e455ee6f8fdc0e255b6d5c4f63136d933fb24 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:16379> set key 1 (error) READONLY You can't write against a read only replica. 复制代码
测试一主多从复制:
主服务器敲入如下命令:
127.0.0.1:10000> hset key1 name1 value1 (integer) 1 127.0.0.1:10000> keys * 1) "key1" 复制代码
从服务器:
127.0.0.1:16379> hget key1 name1 "value1" 127.0.0.1:16380> hget key1 name1 "value1" 127.0.0.1:16381> hget key1 name1 "value1" 复制代码
主从链
配置方式:
和主从配置一样,只不过主节点换为从节点。
注意:主从链的配置依然只能是master节点可以写数据,同时中间的节点也是slave
扩展
如何检测磁盘是否写入数据?
- 主从服务器通过一个虚标值(unique dummy value)来验证从服务器是否真的把数据写入到自己的磁盘。
- 通过命令:
info
检查结果当中的aof_appending_bio_fsync
的值是否为0:
# 5.0 版本之后改为如下形式验证
repl_backlog_active:0
redis主从哨兵模式(Redis sentienel)(redis6.0版本)
哨兵模式有什么作用:
Redis的哨兵模式就是对redis系统进行实时的监控,其主要功能有下面两点
1.监测主数据库和从数据库是否正常运行。
2.当我们的主数据库出现故障的时候,可以自动将从数据库转换为主数据库,实现自动的切换。
为什么要使用哨兵模式:
- 主从复制在主节点宕机的情况下,需要人工干预恢复redis,无法实现高可用。
- 主节点宕机的情况下需要备份数据到新的从节点,然后其他节点将主节点设置为新的redis,需要一次全量复制同步数据的过程
哨兵模式原理
主节点故障的时候,由redis sentinel自动完成故障发现和转移
如何部署哨兵模式:
- 首先按照上一节配置,已经设置了一个主节点三个从节点的配置
下面的配置如下:
主节点:10000
从节点1:16379
从节点2:16380
从节点3:16381
[xd@iZwz99gyct1a1rh6iblyucZ ~]$ ps -ef | grep redis xd 2964 2910 0 18:02 pts/0 00:00:00 grep --color=auto redis root 26412 1 0 Nov23 ? 00:06:07 ./redis-server 127.0.0.1:10000 root 26421 1 0 Nov23 ? 00:05:37 ./redis-server 127.0.0.1:16379 root 26428 1 0 Nov23 ? 00:05:37 ./redis-server 127.0.0.1:16380 root 26435 1 0 Nov23 ? 00:05:37 ./redis-server 127.0.0.1:16381 复制代码
sentinel.conf
配置文件在安装redis的源码包里面有,所以如果误删了可以下回来然后把文件弄到手,其实可以配置一个常用的或者通用的配置放到自己的本地有需要直接替换- 配置5个sentienl.conf文件(建议奇数个哨兵,方便宕机选举产生新的节点)
[xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26379.conf [xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26380.conf [xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_26381.conf [xd@iZwz99gyct1a1rh6iblyucZ bin]$ sudo cp sentinel.conf sentinel_10000.conf 复制代码
- 四个配置文件的改动依次如下:
所有的sentinel.conf
配置如下:
# 指定哨兵端口 port 20000 # 监听主节点10000 sentinel monitor mymaster 127.0.0.1 10000 2 # 连接主节点时的密码,如果redis配置了密码需要填写 sentinel auth-pass mymaster 12345678 # 故障转移时最多可以有2从节点同时对新主节点进行数据同步 sentinel config-epoch mymaster 2 # 故障转移超时时间180s, sentinel failover-timeout mymasterA 180000 # sentinel节点定期向主节点ping命令,当超过了300S时间后没有回复,可能就认定为此主节点出现故障了…… sentinel down-after-milliseconds mymasterA 300000 # 故障转移后,1代表每个从节点按顺序排队一个一个复制主节点数据,如果为3,指3个从节点同时并发复制主节点数据,不会影响阻塞,但存在网络和IO开销 sentinel parallel-syncs mymasterA 1 # 设置后台启动 daemonize yes # 进程的pid文件,保险起见设置不一样的,特别是设置后台启动的时候 pidfile /var/run/redis-sentinel.pid 复制代码
扩展:如何判定转移失败:
a - 如果转移超时失败,下次转移时时间为之前的2倍;
b - 从节点变主节点时,从节点执行slaveof no one命令一直失败的话,当时间超过180S时,则故障转移失败
c - 从节点复制新主节点时间超过180S转移失败
下面为配好五个之后的配置:
-rw-r--r-- 1 root root 10772 Nov 28 21:00 sentienl_26382.conf -rw-r--r-- 1 root root 10767 Nov 28 20:43 sentinel_10000.conf -rw-r--r-- 1 root root 10772 Nov 28 21:03 sentinel_26379.conf -rw-r--r-- 1 root root 10766 Nov 28 20:46 sentinel_26380.conf -rw-r--r-- 1 root root 10772 Nov 28 20:59 sentinel_26381.conf -rw-r--r-- 1 root root 10772 Nov 28 21:03 sentinel_26382.conf -rw-r--r-- 1 root root 10744 Nov 28 18:06 sentinel.conf 复制代码
- 上一节已经启动过,这里不再介绍
- 启动sentinel服务
启动五个哨兵:
./redis-sentinel ./sentinel_10000.conf ./redis-sentinel ./sentinel_26379.conf ./redis-sentinel ./sentinel_263780.conf ./redis-sentinel ./sentinel_263781.conf ./redis-sentinel ./sentinel_263782.conf 复制代码
使用ps
命令查看所有的服务:
root 3267 1 0 21:14 ? 00:00:01 ./redis-sentinel *:20000 [sentinel] root 3280 1 0 21:15 ? 00:00:01 ./redis-sentinel *:26379 [sentinel] root 3296 1 0 21:20 ? 00:00:00 ./redis-sentinel *:26380 [sentinel] root 3303 1 0 21:21 ? 00:00:00 ./redis-sentinel *:26381 [sentinel] root 3316 3254 0 21:28 pts/0 00:00:00 grep --color=auto redis root 26412 1 0 Nov23 ? 00:06:17 ./redis-server 127.0.0.1:10000 root 26421 1 0 Nov23 ? 00:05:47 ./redis-server 127.0.0.1:16379 root 26428 1 0 Nov23 ? 00:05:47 ./redis-server 127.0.0.1:16380 root 26435 1 0 Nov23 ? 00:05:47 ./redis-server 127.0.0.1:16381 复制代码
- 验证一下哨兵是否管用
10000是主节点,他的info
信息如下:
# Keyspace db0:keys=1,expires=0,avg_ttl=0 127.0.0.1:10000> info replication # Replication role:master connected_slaves:3 复制代码
使用kill -9 master节点进程端口号
之后,我们已经干掉了额主进程,验证一下从节点是否启动
进入到6379端口的redis-cli
当中,可以看到从节点6379的实例被选举为新的的节点
127.0.0.1:16379> info replication # Replication role:master connected_slaves:2 slave0:ip=127.0.0.1,port=16380,state=online,offset=857706,lag=1 slave1:ip=127.0.0.1,port=16381,state=online,offset=858242,lag=1 复制代码
挂掉的主节点恢复之后,能不能进行恢复为主节点?
尝试重启挂掉的master之后,可以发现他变成了从节点
127.0.0.1:10000> info replication # Replication role:slave master_host:127.0.0.1 master_port:16379 master_link_status:up master_last_io_seconds_ago:2 复制代码
注意:生产环境建议让redis Sentinel部署到不同的物理机上
如果不喜欢上面的启动哨兵模式,也可以使用下面的命令开启:
[root@dev-server-1 sentinel]# redis-server sentinel1.conf --sentinel [root@dev-server-1 sentinel]# redis-server sentinel2.conf --sentinel [root@dev-server-1 sentinel]# redis-server sentinel3.conf --sentinel 复制代码
哨兵模式部署建议
a,sentinel节点应部署在多台物理机(线上环境)
b,至少三个且奇数个sentinel节点
c,通过以上我们知道,3个sentinel可同时监控一个主节点或多个主节点
监听N个主节点较多时,如果sentinel出现异常,会对多个主节点有影响,同时还会造成sentinel节点产生过多的网络连接,
一般线上建议还是, 3个sentinel监听一个主节点
也可以按照下面的方式在启动哨兵的时候启动:
哨兵模式的优缺点:
优点:
- 哨兵模式基于主从复制模式,所以主从复制模式有的优点,哨兵模式也有
- 哨兵模式下,master挂掉可以自动进行切换,系统可用性更高
缺点:
- 同样也继承了主从模式难以在线扩容的缺点,Redis的容量受限于单机配置
- 需要额外的资源来启动sentinel进程,实现相对复杂一点,同时slave节点作为备份节点不提供服务