zoukankan      html  css  js  c++  java
  • Redis 的主从同步,及两种高可用方式 (序列六)

    Redis 主从同步(Master&Slave)

    Redis主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。

    工作原理:

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

    Master&Slave是什么?

             也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。

     

     全量同步
      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

    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...

    复制原理:

           1、Slave启动成功连接到master后会发送一个sync命令;

           2、Master接到命令启动后的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master

                将传送整个数据文件到slave,以完成一次完全同步;

           3、全量复制:而slave服务在数据库文件数据后,将其存盘并加载到内存中;

           4、增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步;

           5、但是只要是重新连接master,一次完全同步(全量复制)将被自动执行。
    ————————————————

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

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

    1)在master 端操作

     2)在selave 端查看

     

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

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

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

    哨兵模式(sentinel)

           反客为主的自动版,能够后台监控Master库是否故障,如果故障了根据投票数自动将slave库转换为主库。一组sentinel能

           同时监控多个Master。

           使用步骤:

           1、在Master对应redis.conf同目录下新建sentinel.conf文件,名字绝对不能错;

           2、配置哨兵,在sentinel.conf文件中填入内容:

                 sentinel monitor 被监控数据库名字(自己起名字) ip port 1

                 说明:上面最后一个数字1,表示主机挂掉后slave投票看让谁接替成为主机,得票数多少后成为主机。

          3、启动哨兵模式:

                命令键入:redis-sentinel  /myredis/sentinel.conf

               注:上述sentinel.conf路径按各自实际情况配置
    ————————————————

    实现原理:

    三个定时监控任务
    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节点询问对主节点的判断,当超过<quorum>个数,那么意味着大部分的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

    关闭保护模式

    第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 root@172.25.254.102:/etc/redis/
    sentinel.conf                                    100% 7609     7.4KB/s   00:00    
    [root@server2 redis]# scp sentinel.conf root@172.25.254.104:/etc/redis/
    sentinel.conf                                    100% 7609     7.4KB/s   00:00

    4)三台redis 开启 sentinel 服务

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

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

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

     +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

    +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          ###打开集群服务

    [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

    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

     

    [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 ##查看集群的状态

    可以查看之前的内容

    [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>

    查看信息

    关闭掉两个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


     高可用搭建完成

  • 相关阅读:
    PLSQL快捷补充代码设置
    VS2012未找到与约束ContractName...匹配的导出
    VS2012下安装NuGet
    360°全景效果展示
    ArcGIS应用——四种计算图斑面积的方法
    ArcGIS应用——使用Python为图斑连续编号及扩展应用
    Shapefile点图层转换为Shapefile线图层
    SharpMap开发教程——图层标注
    SharpMap入门教程
    常用SQL语句集锦
  • 原文地址:https://www.cnblogs.com/xiaozengzeng/p/12657334.html
Copyright © 2011-2022 走看看