redis的持久化功能在必定程度上保证了数据的安全性,即使时服务器宕机的状况下,也能够保证数据的丢失很是少,一般,为了不服务的单点故障,会把数据复制到多个副本放在不一样的服务器上,且这些拥有数据副本的服务器能够用于处理客户端的读请求,扩展总体的性能,下面将介绍redis的主从复制。linux
redis的复制功能是支持多个服务器之间的数据同步。被复制的服务器称为主服务器(master),对服务器进行复制操做的为从服务器(slave),主服务器master能够进行读写操做,当发生写操做的时候自动将数据同步到从服务器,而从服务器通常是只读的,并接收master同步过来的数据,一个master能够有多个slave,而一个slave只能由一个master。
主从复制的过程:redis
1,从节点执行slaveof命令; 2,从节点只是保存了slavef命令中主节点的信息,并无当即发起复制; 3,从节点内部的定时任务发现由主节点的信息,开始使用socket链接主节点; 4,链接创建成功后,发送ping命令,但愿获得pong命令响应,不然会进行重连; 5,若是主节点设置了权限,那么就须要进行权限验证;若是验证失败,复制终止; 6,权限验证经过后,进行数据同步,这是耗时最长的操做,主节点将把全部的数据所有发送给从节点; 7,当主节点把当前的数据同步给从节点后,便完成了复制的创建流程,主节点就会持续的把写命令发送给从主节点,保证主从数据一致性;
主从复制的做用:vim
环境描述:安全
主机 | 地址 | 端口 | 操做系统 |
---|---|---|---|
主redis | 172.16.1.100 | 6379 | CentOS 7.3 |
从redis | 172.16.1.110 | 6379 | CentOS 7.3 |
1,部署主节点
1)安装redis
官网下载地址:http://download.redis.io/releases/
[root@redis-master ~]# tar zxf redis-4.0.14.tar.gz
[root@redis-master ~]# cd redis-4.0.14
[root@redis-master redis-4.0.14]# make && make install
经过上图,咱们能够很容易的看出,redis安装到/usr/local,/usr/local/bin,/usr/local/share,/usr/local/include,/usr/local/lib,/usr/local/share/man目录下。服务器
而后再切换到utisl目录下,执行redis初始化脚本install_server.sh,以下:架构
[root@redis-master redis-4.0.14]# cd utils/ [root@redis-master utils]# ./install_server.sh Welcome to the redis service installer This script will help you easily set up a running redis server Please select the redis port for this instance: [6379] Selecting default: 6379 Please select the redis config file name [/etc/redis/6379.conf] Selected default - /etc/redis/6379.conf Please select the redis log file name [/var/log/redis_6379.log] Selected default - /var/log/redis_6379.log Please select the data directory for this instance [/var/lib/redis/6379] Selected default - /var/lib/redis/6379 Please select the redis executable path [/usr/local/bin/redis-server] Selected config: Port : 6379 Config file : /etc/redis/6379.conf Log file : /var/log/redis_6379.log Data dir : /var/lib/redis/6379 Executable : /usr/local/bin/redis-server Cli Executable : /usr/local/bin/redis-cli Is this ok? Then press ENTER to go on or Ctrl-C to abort. Copied /tmp/6379.conf => /etc/init.d/redis_6379 Installing service... Successfully added to chkconfig! Successfully added to runlevels 345! Starting Redis server... Installation successful! #上面所有默认回车就好
过上面的安装过程,咱们能够看出redis初始化后redis配置文件为/etc/redis/6379.conf,日志文件为/var/log/redis_6379.log,数据文件dump.rdb存放到/var/lib/redis/6379目录下,启动脚本为/etc/init.d/redis_6379。并发
#初始化完成后,默认已经启动redis服务了(默认监听端口6379):负载均衡
[root@redis-master ~]# /etc/init.d/redis_6379 status Redis is running (5693) [root@redis-master ~]# ss -anput | grep redis tcp LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",pid=5693,fd=6))
#防火墙规则设置:socket
[root@redis-master ~]# firewall-cmd --add-port=6379/tcp --permanent success [root@redis-master ~]# firewall-cmd --reload success
2),配置redistcp
[root@redis-master ~]# vim /etc/redis/6379.conf #修改内容以下(去掉注释并修改): 70 bind 172.16.1.100 #将redis的监听地址修改成redis主机的ip 501 requirepass pwd@123 #考虑到安全性,须要启动redis的密码验证功能requirepass参数。 137 daemonize yes #以守护进程运行redis实例
#修改完成后,重启redis:
[root@redis-master ~]# /etc/init.d/redis_6379 restart Stopping ... Waiting for Redis to shutdown ... Redis stopped Starting Redis server... [root@redis-master ~]# ss -anput | grep redis tcp LISTEN 0 128 172.16.1.100:6379 *:* users:(("redis-server",pid=5739,fd=6))
#远程链接redis:
要在redis服务上执行命令须要一个redis客户端,Redis 客户端在咱们以前下载的的redis 的安装包中。
[root@redis-master ~]# redis-cli --version redis-cli 4.0.14 [root@redis-master ~]# redis-cli -h 172.16.1.100 -p 6379 -a pwd@123 Warning: Using a password with '-a' option on the command line interface may not be safe. 172.16.1.100:6379> ping #该命令用于检测redis服务是否启动 PONG
2,部署从节点
1)安装redis的过程与上边相同,这里再也不重复。
2)配置redis
[root@redis-slave ~]# vim /etc/redis/6379.conf 70 bind 172.16.1.110 #修改成redis主机的ip 137 daemonize yes #后台运行 501 requirepass pwd@123 #设置redis的验证密码 282 slaveof 172.16.1.100 6379 #这个配置项是主从复制的关键,指向master节点的地址和端口 289 masterauth pwd@123 #配置master的受权密码(若是master没有设置requirepass选项,从服务器则无需配置)
实际上配置主从复制有三种方法:
① 配置文件中加 slaveof [masterHost] [masterPort] ② redis-server 启动时加--slaveof [masterHost] [masterPort] ③ 登陆redis直接使用命令 slaveof [masterHost] [masterPort]
#重启redis服务: [root@redis-slave ~]# /etc/init.d/redis_6379 restart Stopping ... Redis stopped Starting Redis server... [root@redis-slave ~]# ss -anput | grep redis tcp LISTEN 0 128 172.16.1.110:6379 *:* users:(("redis-server",pid=4886,fd=6)) tcp ESTAB 0 0 172.16.1.110:34105 172.16.1.100:6379 users:(("redis-server",pid=4886,fd=7)) #能够看到多了一个主从复制的进程
#配置防火墙: [root@redis-slave ~]# firewall-cmd --add-port=6379/tcp --permanent success [root@redis-slave ~]# firewall-cmd --reload success
3,测试数据同步
主redis: [root@redis-master ~]# redis-cli -h 172.16.1.100 -p 6379 -a pwd@123 Warning: Using a password with '-a' option on the command line interface may not be safe. 172.16.1.100:6379> set name abc #设置一个key/value OK 172.16.1.100:6379> get name "abc"
从redis: [root@redis-slave ~]# redis-cli -h 172.16.1.110 -p 6379 -a pwd@123 Warning: Using a password with '-a' option on the command line interface may not be safe. 172.16.1.110:6379> get name #数据成功同步 "abc"
4,测试读写分离(redis默认就是读写分离)
#在从redis上测试: 172.16.1.110:6379> set age 20 (error) READONLY You can't write against a read only slave.
1,中止主redis,模拟故障
[root@redis-master ~]# redis-cli -h 172.16.1.100 -p 6379 -a pwd@123 shutdown [root@redis-master ~]# ss -anput | grep redis [root@redis-master ~]#
2,将从redis设置成主redis(关闭复制功能)
[root@redis-slave ~]# redis-cli -h 172.16.1.110 -p 6379 -a pwd@123 slaveof no one Warning: Using a password with '-a' option on the command line interface may not be safe. OK
3,测试从redis是否切换成主redis
#查看当前主机的角色:
[root@redis-slave ~]# redis-cli -h 172.16.1.110 -p 6379 -a pwd@123 info replication Warning: Using a password with '-a' option on the command line interface may not be safe. # Replication role:master //角色为master connected_slaves:0 master_replid:51ca62c64f31a7adedfb942a95d01c922f42124b master_replid2:e5a32a89b7806f0fa7954cb0c422172ea889fff0 master_repl_offset:5583 second_repl_offset:5584 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:4607 repl_backlog_histlen:977
#测试读写数据:
[root@redis-slave ~]# redis-cli -h 172.16.1.110 -p 6379 -a pwd@123 Warning: Using a password with '-a' option on the command line interface may not be safe. 172.16.1.110:6379> keys * 1) "age" 2) "name" 172.16.1.110:6379> get name "abc" 172.16.1.110:6379> set name zhangsan OK 172.16.1.110:6379> get name "zhangsan"
4,原来的主redis恢复正常了,要从新切换回去
1)将如今的主redis的数据进行保存
172.16.1.110:6379> keys * 1) "age" 2) "name" 172.16.1.110:6379> save OK 172.16.1.110:6379> get name "zhangsan"
2)将如今的主redis根目录下dump.rdb文件拷贝覆盖到原来主redis的根目录 (确保从新运行的master得到redis中最新的数据):[root@redis-slave ~]# scp /var/lib/redis/6379/dump.rdb root@172.16.1.100:/var/lib/redis/6379/
3)启动原来的主redis:
[root@redis-master ~]# /etc/init.d/redis_6379 start Starting Redis server... [root@redis-master ~]# ss -anput | grep redis tcp LISTEN 0 128 172.16.1.100:6379 *:* users:(("redis-server",pid=19649,fd=6))
4)在如今的主redis中切换:
[root@redis-slave ~]# redis-cli -h 172.16.1.110 -p 6379 -a pwd@123 slaveof 172.16.1.100 6379 Warning: Using a password with '-a' option on the command line interface may not be safe. OK
#查看状态:
能够看到如今主redis状态已经变成了slave
#查看主redis的状态:
能够看到状态已经变成了master,而且数据也是最新的数据,可是这种人工操做的方法在生产环境中,确定是稍显不足,因此接下来介绍redis哨兵机制。
redis的主从复制模式下,一旦主节点因为故障不能提供服务,须要人工将从节点晋升为主节点,同时还要通知应用方更新节点地址,对于不少应用场景这种故障处理的方式是没法接受的;可喜的是redis从2.8开始开始正式提供了Redis Sentinel(哨兵)机制来解决这个问题。
哨兵机制概述
redis的哨兵(sentinel)系统用于管理多个redis服务器,该系统执行如下三个任务:
1,监控(Monitoring):哨兵会不断的检查你的master和slave是否运行正常。
2,提醒(Notification):当被监控的某个redis出现问题时,哨兵能够经过API向管理员或这其余应用程序发送通知;
3,自动故障迁移(Automatic failover):当一个master不能正常工做时,哨兵会开始依次自动故行迁移操做,它会将失效master的其中一个slave升级为新的master,并让失效master的其余slave改成复制新的master,当客户端链接失效的master时,集群也会向客户端返回新master的地址,使得集群可使用新的master代替失效的master。
哨兵本质也是一个redis服务,只是跟普通的redis服务提供了不同的功能,哨兵是一个分布式架构,由于你要保证redis高可用,首先要保证本身高可用,因此咱们须要搭建哨兵的话,至少须要部署三个实例,最好是奇数个,由于在后续的故障转移中会涉及到投票。
部署sentinel 对redis主从架构进行监控管理
上面咱们的主从架构环境是一主一从,根据哨兵的投票机制,至少要三个实例,因此在原有的环境中添加一台slave从节点(172.16.1.120)。
步骤省略,参照上面部署从节点的方式进行安装配置,最终确保可以同步master上面的数据。
2,配置sentinel(三台主机操做相同)
配置3个哨兵,每一个哨兵的配置都是同样的。在redis安装目录下有一个sentinel.conf文件,copy一份进行修改:
[root@redis-master ~]# cp redis-4.0.14/sentinel.conf /etc/redis/ [root@redis-master ~]# ls /etc/redis/ 6379.conf sentinel.conf [root@redis-master ~]# vim /etc/redis/sentinel.conf 修改内容以下: #绑定redis主机的ip地址,注意:这里其余两台slave从节点须要指向本身本机地址 bind 172.16.1.100 #端口号,默认是redis实例+20000,因此咱们沿用这个规则就行了 port 26379 #添加守护进程运行 daemonize yes #添加日志存放的位置,这个很是重要,经过日志能够查看故障转移的过程 logfile "26379.log" #工做目录(sentinel的相关信息文件都会保存在这,包括日志文件),这里保持默认(固然你也能够自定义路径) dir /tmp #指定sentinel要监控的redis实例:监视一个名为mymaster(名字可自定义)的redis服务器,这个地址为master ip地址 , #最后面的2表明着至少有两个哨兵认为主服务器出现故障才会进行故障转移,不然认定主服务未失效,通常设置为N/2+1(N为哨兵总数)。 sentinel monitor mymaster 172.16.1.100 6379 2 #定义服务的密码,mymaster是服务的名称,后面是redis服务器的密码,若是你的redis没有设置密码,则须要关闭保护模式(protected-mode no) sentinel auth-pass mymaster pwd@123 #sentinel判断服务器失效的响应时间,超过这个时间未接收到服务器的响应,就认为该服务器失效了 sentinel down-after-milliseconds mymaster 3000 /#完成故障转移以后,最多多少个从服务器能够同时发起数据复制(并发数), #数字越小,说明完成所有从服务数据复制的时间越长,数字越大,对主服务器的压力就变大了 sentinel parallel-syncs mymaster 1 /#故障转移超时时间,若sentinel在该配置值内未能完成failover操做(即故障时master/slave自动切换),则认为本次failover失败。 sentinel failover-timeout mymaster 180000
3,依次启动哨兵:(两种方法)
方法1: [root@redis-master ~]# redis-sentinel /etc/redis/sentinel.conf 方法2: [root@redis-master ~]# redis-server /etc/redis/sentinel.conf --sentinel
查看端口是否正常:
其余两个slave从节点依次启动。
注意启动顺序:若是redis和sentinel同时启动的状况下,要先启动redis服务,而后再启动sentinel。
#配置防火墙:(须要在各节点上开启哨兵的监听端口) [root@redis-slave2 ~]# firewall-cmd --add-port=26379/tcp --permanent success [root@redis-slave2 ~]# firewall-cmd --reload fisuccess
#由于哨兵也是redis实例,因此咱们经过如下命令查看当前的哨兵监控的信息:
[root@redis-master ~]# redis-cli -p 26379 -h 172.16.1.100 172.16.1.100:26379> info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=172.16.1.100:6379,slaves=2,sentinels=3 #能够看到当前状态为ok,而且监听的主机是当前master节点,2个从节点,3个哨兵
4,模拟主redis服务器故障,是否正常自动迁移至其余从服务器,而且从服务器自动提高为主服务器
#关闭redis服务或者杀掉进程 [root@redis-master ~]# redis-cli -p 6379 -h 172.16.1.100 -a pwd@123 shutdown Warning: Using a password with '-a' option on the command line interface may not be safe. [root@redis-master ~]# ps -ef | grep redis root 19687 1 0 04:35 ? 00:00:00 redis-sentinel 172.16.1.100:26379 [sentinel] root 19700 2242 0 04:39 pts/0 00:00:00 grep --color=auto redis
#查看哨兵的监控信息:
[root@redis-master ~]# redis-cli -h 172.16.1.100 -p 26379 info sentinel # Sentinel sentinel_masters:1 sentinel_tilt:0 sentinel_running_scripts:0 sentinel_scripts_queue_length:0 sentinel_simulate_failure_flags:0 master0:name=mymaster,status=ok,address=172.16.1.110:6379,slaves=2,sentinels=3 #能够发现当前哨兵监听的master节点不是原来的了,而是从节点(172.16.1.110)了。
#查看sentinel的日志信息:
经过日志信息的能够知道,原来的master主机已经挂掉了,而且经过sentinel哨兵机制,已经自动切换master到了172.16.1.110从节点了。
#验证原来从节点是否切换成功:
能够看到本身从原来的slave状态切换成了master,而且172.16.1.20是做为本身的slave节点。
172.16.1.110:6379> keys * 1) "addr" 2) "age" 3) "name" 172.16.1.110:6379> set linux redis OK 172.16.1.110:6379> get linux "redis" //而且能够正常进行读写操做
5,那么当挂掉的master主节点恢复正常,sentine是否会从新推选为master呢? 让咱们来验证一下:
#从新启动redis服务: [root@redis-master ~]# /etc/init.d/redis_6379 start Starting Redis server... [root@redis-master ~]# ps -ef | grep redis root 19687 1 0 04:35 ? 00:00:02 redis-sentinel 172.16.1.100:26379 [sentinel] root 19713 1 0 04:57 ? 00:00:00 /usr/local/bin/redis-server 172.16.1.100:6379 root 19718 2242 0 04:57 pts/0 00:00:00 grep --color=auto redis
#查看本身状态:能够得知,从新恢复挂掉的mater后,没法成为master,只能做为当前master的slave从节点。但须要注意的是,当挂掉的主机恢复后,哨兵机制并不会帮你还原这段时间丢失的数据,因此,还需将其余节点的dump.rdb文件作好备份工做,以再恢复后可以导入丢失的数据。