Redis 的主从同步,及两种高可用方式

一、Redis 介绍

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。

二、Redis 主从同步

Redis主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布 记录。同步对读取操作的可扩展性和数据冗余很有帮助。

工作原理:

Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。

  •  全量同步

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

  1)从服务器连接主服务器,发送SYNC命令; 

  2)主服务器接收到SYNC命名后,开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所有写命令; 

  3)主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令; 

  4)从服务器收到快照文件后丢弃所有旧数据,载入收到的快照; 

  5)主服务器快照发送完毕后开始向从服务器发送缓冲区中的写命令; 

  6)从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令; 

完成上面几个步骤后就完成了从服务器数据初始化的所有操作,从服务器此时可以接收来自用户的读请求。

  •  增量同步

  Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。 

增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

  • Redis主从同步策略

  主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave 在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求从机进行全量同步。

  •  注意点

如果多个Slave断线了,需要重启的时候,因为只要Slave启动,就会发送sync请求和主机全量同步,当多个同时出现的时候,可能会导致Master IO剧增宕机。

实验环境:

server3:172.25.254.103  redis-slave

server4:172.25.254.104 redis-slave

server2:172.25.254.101  redis-master

1.redis 环境搭建

1)在所有实验主机上安装 Redis

先下载安装包 redis-4.0.8.tar.gz 并做以下操作

tar zxf redis-4.0.8.tar.gz  ##解压安装包
cd redis-4.0.8
yum install gcc -y   
make && make install  ###安装
cd redis-4.0.8/utils/
./install_server.sh   执行这个脚本

2)编辑配置文件

vim /etc/redis/6379.conf 
找到第70行的bind  后面写0.0.0.0
/etc/init.d/redis_6379 stop
/etc/init.d/redis_6379 start

Redis 的主从同步,及两种高可用方式_第1张图片

2.配置redis-slave

[root@server3 ~]# vim /etc/redis/6379.conf
slaveof 172.25.254.101 6379     # redis-master 的ip

[root@server3 ~]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...

[root@server4 ~]#  vim /etc/redis/6379.conf
slaveof 172.25.254.101 6379
 
[root@server4 ~]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...

如上操作所示,已经完成redis的主从复制
3.测试

在master端server2:操作,在slave端server3查看
执行redis-cli,登陆   若数据一致,则同步成功

1)在master 端操作

Redis 的主从同步,及两种高可用方式_第2张图片

2)在selave 端查看

Redis 的主从同步,及两种高可用方式_第3张图片

Redis 的主从同步,及两种高可用方式_第4张图片

Redis Sentinel(哨兵)架构下的高可用

Redis的主从复制下,一旦主节点由于故障不能提供服务,需要人工将从节点晋升为主节点,同时还要通知应用方更新主节点地址,对于很多应用场景这种故障处理的方法是无法接受的。但是Redis从2.8开始正式提供了Redis Sentinel(哨兵)架构来解决这个问题。

        Redis Sentinel是一个分布式架构,其中包含若干个Sentinel节点和Redis数据节点,每个Sentinel节点会对数据节点和其余Sentinel节点进行监控,当它发现节点不可达时,会对节点做下线标识。如果被标识的是主节点,它还会和其他Sentinel节点进行“协商”,当大多数Sentinel节点都认为主节点不可达时,它们会选举出一个Sentinel节点来完成自动故障转移的工作,同时会将这个变化通知给Redis应用方。整个过程完全是自动的,不需要人工来介入,所以这套方案很有效地解决了Redis的高可用问题。

实现原理:

  • 三个定时监控任务

1)每隔10秒,每个Sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构。

2)每隔2秒,每个Sentinel节点会向Redis数据节点的__sentinel__:hello频道上发送该Sentinel节点对于主节点的判断以及当前Sentinel节点的信息,同时每个Sentinel节点也会订阅该频道,来了解其他Sentinel节点以及它们对主节点的判断。

3)每隔一秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,来确认这些节点当前是否可达。

  • 主观下线

因为每隔一秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,当这些节点超过down-after-milliseconds没有进行有效回复,Sentinel节点就会对该节点做失败判定,这个行为叫做主观下线。

  • 客观下线

当Sentinel主观下线的节点是主节点时,该Sentinel节点会向其他Sentinel节点询问对主节点的判断,当超过个数,那么意味着大部分的Sentinel节点都对这个主节点的下线做了同意的判定,于是该Sentinel节点认为主节点确实有问题,这时该Sentinel节点会做出客观下线的决定。

  • 领导者Sentinel节点选举

Raft算法:假设s1(sentinel-1)最先完成客观下线,它会向其余Sentinel节点发送命令,请求成为领导者;收到命令的Sentinel节点如果没有同意过其他Sentinel节点的请求,那么就会同意s1的请求,否则拒绝;如果s1发现自己的票数已经大于等于某个值,那么它将成为领导者。

  • 故障转移

1)领导者Sentinel节点在从节点列表中选出一个节点作为新的主节点

2)上一步的选取规则是与主节点复制相似度最高的从节点

3)领导者Sentinel节点让剩余的从节点成为新的主节点的从节点

4)Sentinel节点集合会将原来的主节点更新为从节点,并保持着对其关注,当其恢复后命令它去复制新的主节点

1.实验环境 (首先搭建好Redis环境并可以进行主从同步)

系统版本:rhel6.5

server3:172.25.254.103  redis-slave

server4:172.25.254.104 redis-slave

server2:172.25.254.101  redis-master

2.主节点操作

1)在安装包中将 sentinel 文件复制到/etc/redis/下

[root@server2 ~]# cd redis-4.0.1
[root@server2 redis-4.0.1]# cp sentinel.conf /etc/redis/
[root@server2 redis-4.0.1]# cd /etc/redis/

2)修改配置文件
[root@server2 redis]# vim sentinel.conf

关闭保护模式

Redis 的主从同步,及两种高可用方式_第5张图片

第98 行  Sentinel 去监视一个名为 mymaster 的主服务器, 这个主服务器的IP 地址为 172.25.154.101,端口号为 6379 ,而将这个主服务器判断为失效至少需要 2 个 Sentinel 同意 (只要同意 Sentinel 的数量不达标,自动故障迁移就不会执行)
如:

sentinel monitor mymaster 172.25.254.101 6379 2

3)将配置好的文件发送给所有从节点

[root@server2 redis]# scp sentinel.conf [email protected]:/etc/redis/
sentinel.conf                                    100% 7609     7.4KB/s   00:00    
[root@server2 redis]# scp sentinel.conf [email protected]:/etc/redis/
sentinel.conf                                    100% 7609     7.4KB/s   00:00

4)三台redis 开启 sentinel 服务

[root@server2 redis]# redis-sentinel /etc/redis/sentinel.conf

Redis 的主从同步,及两种高可用方式_第6张图片

两台slave
[root@server3 ~]# redis-sentinel /etc/redis/sentinel.conf

Redis 的主从同步,及两种高可用方式_第7张图片

[root@server4 ~]# redis-sentinel /etc/redis/sentinel.conf
 Redis 的主从同步,及两种高可用方式_第8张图片

+slave 表示 :一个新的从服务器已经被 Sentinel 识别并关联 可以看到片此时 master 是 server2;server3和 server4 是 slave。

3.测试

1)停掉现在的Redis-master  info 查看 replication 信息

[root@server2 ~]# redis-cli -p 26379
127.0.0.1:26379> info
master0:name=mymaster,status=ok,address=172.25.254.101:6379,slaves=2,sentinels=3[root@server2 ~]# redis-cli
127.0.0.1:6379> SHUTDOWN
not connected>
[root@server2 ~]# redis-cli
Could not connect to Redis at 127.0.0.1:6379: Connection refused
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected>
[root@server2 ~]# redis-cli -p 26379
127.0.0.1:26379> info
master0:name=mymaster,status=ok,address=172.25.254.102:6379,slaves=2,sentinels=3
127.0.0.1:26379>

2)查看任意一台redis主机的监控日志

[root@server4 ~]# redis-sentinel /etc/redis/sentinel.conf

Redis 的主从同步,及两种高可用方式_第9张图片

+switch-master :配置变更,主服务器的 IP 和地址已经改变 由之前的172.25.254.101 更改为172.25.254.102。
+sdown :给定的实例 server2现在处于主观下线状态。
在原先的master被停掉后,通过选举产生新的master 172.25.254.102 6379

实际现在只有一个slave 可以使用

四、Redis Cluster(集群)下的高可用

实现原理:

  • 主观下线

       集群中每个节点都会定期向其他节点发送ping消息,接受节点回复ping消息作为响应。如果在cluster-node-timeout时间内通信一直失败,则发送节点会认为接收节点存在故障,把接受节点标记为主观下线(pfail)状态。

  • 客观下线

1)当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播。

2)假设节点a标记节点b为主观下线,一段时间后节点a通过消息把节点b的状态发送到其他节点,当其他节点收到消息并解析出消息体中含有b的pfail状态,把节点b加入下线报告链表;

3)当某一节点c收到节点b的pfail状态时,此时有超过一半的槽主节点都标记了节点b为pfail状态时,则标记故障节点b为客观下线;

4)向集群广播一条pfail消息,通知集群内的所有节点标记故障节点b为客观下线状态并立刻生效,同时通知故障节点b的从节点触发故障转移流程。

  • 故障恢复

1)资格检查

若从节点与主节点断线时间超过一定时间,则不具备资格
2)准备选举时间

当从节点符合故障转移资格后,要等待一段选举时间后才开始选举

在故障节点的所有从节点中,复制偏移量最大的那个从节点最先开始(与主节点的数据最一致)进行选举,然后是次大的节点开始选举.....剩下其余的从节点等待到它们的选举时间到达后再进行选举
3)发起选举
4)选举投票

只有持有槽的主节点才具有一张唯一的选票,从从节点收集到N/2 + 1个持有槽的主节点投票时,从节点可以执行替换主节点操作
5)替换主节点

当从节点收集到足够的选票之后,触发替换主节点操作

  • 当前从节点取消复制变为主节点
  • 撤销故障主节点负责的槽,并把这些槽委派给自己
  • 向集群广播自己的pong消息,通知集群内所有的节点当前从节点变为主节点并接管了故障主节点的槽信息

1.实验环境:

使用任意一台redis 主机 

2.部署高可用

1)搭建环境

[root@server2 redis]# /etc/init.d/redis_6379 stop

cd /usr/local/ mkdir cluster ##建立集群目录

[root@server2 local]# cd cluster/
[root@server2 cluster]# pwd
/usr/local/cluster
[root@server2 cluster]# mkdir 700{1..6}
[root@server2 cluster]# ll
total 24
drwxr-xr-x 2 root root 4096 Oct  9 11:02 7001
drwxr-xr-x 2 root root 4096 Oct  9 11:02 7002
drwxr-xr-x 2 root root 4096 Oct  9 11:02 7003
drwxr-xr-x 2 root root 4096 Oct  9 11:02 7004
drwxr-xr-x 2 root root 4096 Oct  9 11:02 7005
drwxr-xr-x 2 root root 4096 Oct  9 11:02 7006
[root@server2 cluster]# cd 7001/

[root@server2 7001]# vim redis.conf
[root@server2 ~]# cat /usr/local/cluster/7001/redis.conf
port 7001
cluster-enabled yes        #打开集群设备

cluster-config-file nodes.conf
cluster-node-timeout 5000     #延时时间
appendonly yes
daemonize yes

pidfile /usr/local/cluster/7001/redis.pid ##pid文件存放目录

logfile /usr/local/cluster/7001/redis.log ##日志存放目录

[root@server2 7001]# redis-server redis.conf          ###打开集群服务

Redis 的主从同步,及两种高可用方式_第10张图片

[root@server2 cluster]# cp 7001/redis.conf 7002/
[root@server2 cluster]# cp 7001/redis.conf 7003/
[root@server2 cluster]# cp 7001/redis.conf 7004/
[root@server2 cluster]# cp 7001/redis.conf 7005/
[root@server2 cluster]# cp 7001/redis.conf 7006/

[root@server2 cluster]# cd 7002/

[root@server2 7002]# vim redis.conf  ###将文件中的端口号改为7002和存放目录的更改

redis-server redis.conf ###打开集群的redis

cd ..

cd 7003/ vim redis.conf ###将文件中的端口号改为7003和存放目录的更改

redis-server redis.conf ###打开集群的redis

cd ..

cd 7004/ vim redis.conf ###将文件中的端口号改为7004和存放目录的更改

redis-server redis.conf ###打开集群的redis

cd ..

cd 7005/

vim redis.conf ###将文件中的端口号改为7005和存放目录的更改

redis-server redis.conf ###打开集群的redis

cd ..

cd 7006/ vim redis.conf ###将文件中的端口号改为7006和存放目录的更改

redis-server redis.conf ###打开集群的redis
ps ax ##查看进程是否都打开了
netstat -antlp ##查看端口号是否开启

[root@server2 ~]# cd redis-4.0.1
[root@server2 redis-4.0.1]# cd src/
[root@server2 src]# cp redis-trib.rb /usr/local/bin/
[root@server2 src]# yum install -y ruby
[root@server2 ~]# yum install -y rubygems-1.3.7-5.el6.noarch.rpm

[root@server2 ~]# rpm -Uvh ruby-2.2.3-1.el6.x86_64.rpm
[root@server2 ~]# yum install -y  ruby-2.2.3-1.el6.x86_64.rpm libyaml-0.1.3-4.el6_6.x86_64.rpm
[root@server2 ~]# gem install --local redis-4.0.1.gem

Redis 的主从同步,及两种高可用方式_第11张图片

2)创建集群

[root@server2 ~]# redis-trib.rb create --replicas 1 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 127.0.0.1:7006

Redis 的主从同步,及两种高可用方式_第12张图片

Redis 的主从同步,及两种高可用方式_第13张图片

[root@server2 ~]# redis-cli -c -p 7001
127.0.0.1:7001> set name linux
-> Redirected to slot [5798] located at 127.0.0.1:7002
OK
127.0.0.1:7002>

[root@server2 ~]# redis-cli -c -p 7006
127.0.0.1:7006> set name kb
-> Redirected to slot [5798] located at 127.0.0.1:7002
OK
127.0.0.1:7002> get name
"kb"
127.0.0.1:7002>

redis-cli -c -p 7001
登录,set name linux 写入内容,会提示写入内容传到2上
redis-cli -c -p 7002

输入info,发现2是master,他的slave是6

3)测试

停掉master 2

[root@server2 ~]# redis-cli -c -p 7002
127.0.0.1:7002> SHUTDOWN
not connected>

redis-trib.rb check 127.0.0.1:7001 ##查看集群的状态

Redis 的主从同步,及两种高可用方式_第14张图片

可以查看之前的内容

[root@server2 ~]# redis-cli -c -p 7001
127.0.0.1:7001> get name
-> Redirected to slot [5798] located at 127.0.0.1:7005
"kb"
127.0.0.1:7005>

再关掉一个master

[root@server2 ~]# redis-cli -c -p 7005
127.0.0.1:7005> SHUTDOWN
not connected>

查看信息

Redis 的主从同步,及两种高可用方式_第15张图片

关闭掉两个master后,集群的功能会破坏

[root@server2 ~]# redis-cli -c -p 7001
127.0.0.1:7001> get name
(error) CLUSTERDOWN The cluster is down
127.0.0.1:7001>

4)恢复关闭的两个节点

[root@server2 ~]# cd /usr/local/cluster/
[root@server2 cluster]# ls
7001  7002  7003  7004  7005  7006
[root@server2 cluster]# cd 7002
[root@server2 7002]# redis-server redis.conf
1292:C 09 Oct 11:40:46.513 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1292:C 09 Oct 11:40:46.513 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1292, just started
1292:C 09 Oct 11:40:46.513 # Configuration loaded
[root@server2 7002]# cd ..
[root@server2 cluster]# cd 7005
[root@server2 7005]# redis-server redis.conf
1298:C 09 Oct 11:41:15.609 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1298:C 09 Oct 11:41:15.609 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=1298, just started
1298:C 09 Oct 11:41:15.609 # Configuration loaded

Redis 的主从同步,及两种高可用方式_第16张图片

高可用搭建成功

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Redis 的主从同步,及两种高可用方式)