美文网首页
redis 系列(三)- redis主从复制和哨兵模式

redis 系列(三)- redis主从复制和哨兵模式

作者: 黄二的NPE | 来源:发表于2018-10-27 16:13 被阅读346次

普通主从架构(读写分离)

问题

持久化解决了单机redis的数据保存问题,但是redis还是存在以下两个问题:

  1. 假如某天这台redis服务器挂了,redis服务将彻底丧失
  2. redis的读和写都集中到一台机上,如果请求量比较大时,将可能被击溃
解决

为了解决上述两个问题,redis提供了主从架构,在主从架构中,主服务器负责写服务,多台从服务器负责读服务,缓解了单个redis服务器的压力;主服务器将所有数据源源不断的同步到从服务器上,一旦主服务器挂了,还有从服务器可以提供服务,redis服务将不会间断。

特点
  1. 一台主服务器可以连接多台从服务器
  2. 从服务器也可以连接其他redis服务器,作为其他redis服务器的主服务器,从而形成一条链
  3. 主从同步是异步的,从服务器不会阻塞,但是在数据写到从服务器内存的这段期间,从服务器对外提供的还是旧的数据
类型
  1. 全量同步 指主服务器每次与从服务器同步都是同步全部数据。主服务器持久化数据为一个rdb文件,在此期间用缓存区把所有对主服务器的写操作命令存储起来了,然后再rdb传给从服务器,再把储存起来的命令也传过去;从服务器从接收到的rdb文件加载数据,然后再加载传过来的命令。
  2. 部分同步 指主服务器每次与从服务器同步都是只同步增量数据。

原理

  1. 从服务器收到客户端的saveof命令,检查是否存储了主服务器的运行id和复制偏移量。
  2. 如果没绑存储,从服务器发送 psync 1命令和主服务器进行一次全量复制,并且保存主服务器发过来的运行id 和 复制偏移量
  3. 如果有存储了,从服务器发送运行id和复制偏移量,主服务器比较运行id是否一致,复制偏移量是否正常,如果不一致或者不正常,进行全量同步
  4. 如果运行id和复制偏移量正常,那么二者进行增量同步,同步根据传过来复制偏移量,到复制缓存区找到对应的字节,并且把该字节对应的之后的命令都同步过去
操作
  • slaveof master-ip master-port 在从服务器的redis.conf中配置主服务器的host,port
  • slave-read-only yes 从服务器默认只读,这里可改成no为可写(可选)
  • auth 从服务器配置主服务器的密码(可选)
  • requirepass 主服务器配置密码(可选)

从服务器配置好slaveof master-ip master-port 后重启,就可以与主服务器进行同步了。

# 主服务器信息
172.17.0.3:6379> info replication
role:master
connected_slaves:2
# 两个从服务器复制偏移量为4908
slave0:ip=172.17.0.4,port=6379,state=online,offset=4908,lag=1
slave1:ip=172.17.0.5,port=6379,state=online,offset=4908,lag=1
# 主服务器的复制偏移量也为4908
master_repl_offset:4908
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:4907

哨兵模式

作用
  • 不断的检查主从架构中的redis服务中正常运行。
  • 如果出现问题会发信息提示你。
  • 如果主服务器挂了的话,会从从服务器中重新选举一台作为主服务器。
原理
  • 哨兵系统的分类
    哨兵系统可以分为单哨兵和多哨兵;单哨兵是指只有一个哨兵进程,多哨兵是指有多个哨兵进程;单哨兵挂了的话,哨兵系统也就挂了,多哨兵只有一个哨兵挂了不影响哨兵系统继续提供服务。

  • 大概原理
    哨兵也是一个Linux的进程;各个哨兵分布在不同的Linux服务器或者同一个Linux服务器上(一个风险比较大),它们不停的监控redis的主服务器和从服务器与其它的哨兵进程,一旦察觉redis主服务挂了,就会从从服务器中选出一个作为新的主服务器提供服务。

  • 哨兵怎么知道监控其它哨兵和redis服务?
    哨兵每秒钟会向其它哨兵或者redis服务器发送ping命令,根据是否有返回来判断服务是否已经下线。

  • 我们只是在哨兵的配置文件里配置了主服务器信息,但是它怎么知道从服务器信息?
    哨兵每十秒钟会向redis主服务器或者从服务器执行info replication的命令,来确认它们的主从关系。

  • 我们没有配置其他哨兵的地址,哨兵怎么知道其他哨兵地址?
    哨兵每隔两秒就会向redis主节点的sentinel:hello频道发布哨兵对于主节点的判断以及当前哨兵的信息,其它哨兵也会也会如此,并且从中获取所有的哨兵信息。

  • 确认一台redis服务器下线经历了什么流程?
    哨兵不断的PING redis服务器,当发现服务器超过配置的down-after-milliseconds的时间都没有响应,就会认为这台主观下线;这时候哨兵会向其他哨兵发送is-master-down-by-addr命令询问是否可以标记为客观下线,当认为这台redis服务器主观下线的哨兵超过我们配置的quorum(一般设为哨兵数量的一半加1)的值的时候,我们就可以认为这台redis服务器客观下线。为什么还要去询问其他哨兵呢?这是因为哨兵和redis服务器之间没有ping成功也可以能网络之间的问题。

  • 为什么要对哨兵进行领导者选举?
    当确定redis服务器确实挂了以后,哨兵要进行故障转移,并且只能有一个哨兵去完成该操作,所以这时候就要选举出一名哨兵来当此重任。那怎么选举呢?

  1. 哨兵向其它哨兵发送is-master-down-by-addr除了确认是否机器是否可以下线以外,会有发起选举的作用
  2. 其它哨兵收到命令以后,如果如果没有答应其它哨兵的选举请求就会答应该哨兵的请求
  3. 当同意(包括自己)的哨兵个数达到quorum,该哨兵就会成为领导者
  • 怎么完成故障转移?
    当确定原来的redis主服务器已经客观下线以后,就会从从服务器中选出一台作为新的主服务器,选择顺序如下:
  1. 看配置的slave-priority,如果从服务器不相等,返回最高的那台,如果相同看下一步
  2. 看offset,即复制偏移量,如果复制偏移量不同,返回最高那台,如果相同看下一步
  3. 看runid,程序id,runid越低可以看做是越早开启,返回越低那台

确定完是哪台从服务器作为新的主服务器以后,会修改新的从服务器的slaveof与各个哨兵的监控的主服务器的地址和ip。

举个栗子

开启三个redis服务,一主两从;开启三个哨兵;把主服务器关闭掉,查看从服务器是否会产生新的主服务器。

redis配置
# 主服务器 redis-6379.conf
port 6379 
daemonize yes
protected-mode no
logfile "6379.log"
dbfilename "dump-6379.rdb"

# 从服务器 redis-6380.conf
port 6380 
daemonize yes
protected-mode no
logfile "6380.log"
dbfilename "dump-6380.rdb"
slaveof 139.199.168.61 6379

# 从服务器 redis-6381.conf
port 6381 
daemonize yes
protected-mode no
logfile "6381.log"
dbfilename "dump-6381.rdb"
slaveof 139.199.168.61 6379

redis-server redis-6379.conf 启动各个redis服务。

哨兵配置
#sentinel-26379.conf
port 26379
daemonize yes
protected-mode no
logfile "26379.log"
#监控的redis主服务器,最后面的2就是上面提到的quorum,当哨兵响应的个数超过这个数,redis服务器才会被认为是客观下线
sentinel monitor mymaster 139.199.168.61 6379 2
#当超过这个值redis服务器对哨兵的ping不做出响应会被哨兵认为是主观下线
sentinel down-after-milliseconds mymaster 10000

#sentinel-26380.conf
port 26380
daemonize yes
protected-mode no
logfile "26380.log"
sentinel monitor mymaster 139.199.168.61 6379 2
sentinel down-after-milliseconds mymaster 10000

#sentinel-26381.conf
port 26381
daemonize yes
protected-mode no
logfile "26381.log"
sentinel monitor mymaster 139.199.168.61 6379 2
sentinel down-after-milliseconds mymaster 10000

redis-sentinel sentinel-26379.conf 启动各个哨兵服务。

哨兵启动后我们可以查看sentinel-26379.conf:

port 26379
daemonize yes
protected-mode no
logfile "26379.log"
sentinel myid f65e6f01127c838e023f48b73c0f9642548a176d
sentinel monitor mymaster 139.199.168.61 6379 2
# Generated by CONFIG REWRITE
dir "/usr/local/redis-3.2.6"
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 0
sentinel leader-epoch mymaster 0
sentinel known-slave mymaster 139.199.168.61 6381
sentinel known-slave mymaster 139.199.168.61 6380
sentinel known-sentinel mymaster 10.104.90.159 26381 a8ca7a98c5b462c5c341650386be589cf31a5761
sentinel known-sentinel mymaster 10.104.90.159 26380 eb637934a6e00a26c36fef681cb1e194127b7d2c
sentinel current-epoch 0

会发现哨兵已经把redis的从服务器和其他哨兵加进来了,我们关闭主服务器kill redis主服务器的进程,再查看sentinel-26379.conf

port 26379
daemonize yes
protected-mode no
logfile "26379.log"
sentinel myid f65e6f01127c838e023f48b73c0f9642548a176d
sentinel monitor mymaster 139.199.168.61 6381 2
# Generated by CONFIG REWRITE
dir "/usr/local/redis-3.2.6"
sentinel down-after-milliseconds mymaster 10000
sentinel config-epoch mymaster 1
sentinel leader-epoch mymaster 1
sentinel known-slave mymaster 139.199.168.61 6379
sentinel known-slave mymaster 139.199.168.61 6380
sentinel known-sentinel mymaster 10.104.90.159 26381 a8ca7a98c5b462c5c341650386be589cf31a5761
sentinel known-sentinel mymaster 10.104.90.159 26380 eb637934a6e00a26c36fef681cb1e194127b7d2c
sentinel current-epoch 1

我们可以看到监控的主服务器已经切换成 6381而不是之前的6379了。

Java使用
  • Java使用redis的一般做法:
  Jedis jedis = new Jedis("139.199.168.61", 6379);
  System.out.println(jedis.get("hello"));

这种做法最大的弊端在于万一139.199.168.61:6379 这个redis挂了,这个Java应用就废了。

  • 如果我们现在知道了哨兵模式,我们可以改写成以下的做法:
        //声明一个set 存放哨兵集群的地址和端口
        Set<String> sentinels = new HashSet<String>();
        sentinels.add("139.199.168.61:26379");
        sentinels.add("139.199.168.61:26380");
        sentinels.add("139.199.168.61:26381");
        JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinels);
        // 使用sentinelPool获取jedis对象
        Jedis master = sentinelPool.getResource();
        System.out.println(master.get("hello"));
        master.close();
        sentinelPool.destroy();

这样子,当主服务器挂掉以后,哨兵集群会返回给程序新的主服务器地址,保证服务不会挂掉。

相关文章

  • redis的三种集群方式

    redis的三种集群方式 redis有三种集群方式:主从复制,哨兵模式和集群。 1.主从复制 主从复制原理: 从服...

  • redis(二)

    Redis用户认证 禁用危险命令 主从复制的过程 主从复制的部署 哨兵 Redis哨兵+主从+密码 Redis哨兵...

  • Redis高可用原理

    1 Redis高可用常见的有三种方式: 主从复制 哨兵模式 Redis集群 2 复制 在Redis中,可以通过执行...

  • 第五章----Redis三种集群详解

    Redis集群的三种模式 主从复制(master/slave) 哨兵模式(sentinel) 集群模式(clust...

  • Redis

    什么是Redis Redis的五种数据类型 常见Redis问题 淘汰策略 持久化 主从复制,哨兵模式https:/...

  • Redis哨兵模式安装与配置

    在介绍哨兵模式之前首先介绍下Redis主从复制。 Redis 主从复制 可将 主节点 数据同步给 从节点,从节点此...

  • Redis的高可用

    Redis主从复制 什么是主从复制 Redis有三种集群方案,主从复制,哨兵,cluster集群,主从复制是指将一...

  • Redis哨兵模式高可用解决方案

    一、序言 Redis高可用有两种模式:哨兵模式和集群模式,本文基于哨兵模式搭建一主两从三哨兵Redis高可用服务。...

  • redis 系列(三)- redis主从复制和哨兵模式

    普通主从架构(读写分离) 问题 持久化解决了单机redis的数据保存问题,但是redis还是存在以下两个问题: 假...

  • 分布式缓存利器之Redis集群安装与配置

    引言:在之前的几篇文章中依次介绍了分布式缓存技术以及Redis的基本知识和Redis主从复制模式和哨兵模式的安装,...

网友评论

      本文标题:redis 系列(三)- redis主从复制和哨兵模式

      本文链接:https://www.haomeiwen.com/subject/rjkozftx.html