redis-主从复制

一、主从复制简而言之为将主redis的数据同步到从redis,达到主从数据一致。主从复制应用:java

  • 读写分离
  • 容灾备份

二、怎样设置主从?redis

  • 原则:配从不配主
  • 方式:

       a、在从redis中使用执行命令 slaveof host port  [slaveof no one命令表示禁止和主机的同步]数据库

     b、在从redis的配置文件中配置slaveof host port服务器

  • 查询主从信息:info replication

 三、主从复制原理spa

全量复制:slave链接上master时候,master将整个快照发给slave,slave加载快照的数据,此时为全量复制.net

增量复制:master每次接收到在本身数据库的写操做,同时会把写命令传给slave日志

  • 主从复制存在的问题:

因为全部的写操做都是先在Master上操做,而后同步更新到Slave上,因此从Master同步到Slave机器有必定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增长也会使这个问题更加严重。code

四、常见问题blog

  • 切入点问题?slave一、slave2是从头开始复制仍是从切入点开始复制?好比从k4进来,那以前的123是否也能够复制

-->从头开始复制,不是从切入点(建立从的时间),主从数据保持一致了部署

  • 从机是否能够写?set能否?

-->从机通常配置为slave-read-only yes,即为不可set,只能够读

  • 主机shutdown后状况如何?从机是上位仍是原地待命

-->从机不上位,原地待命

  • 主机又回来了后,主机新增记录,从机还可否顺利复制?

-->主机回来后仍是主机身份,主机新增,从机仍然顺利复制

  • 其中一台从机down后状况如何?依照原有它能跟上大部队吗?

-->若是经过命令slaveof设置的主从,重新启动从机后身份会变成主机,须要重新用命令设置为原来主机的从机,那么此时数据就同步了;

若是是经过当前从机的配置文件配置的,那么启动后仍然是从机,且数据是同步的

  • 若是从机中途变动主机,数据变化?

-->清空全部数据,并与新主机的数据同步

五、哨兵模式

  • 什么是哨兵模式?

监控主机是否发生故障,若是发生了故障,根据投票数自动将从机切换为主机。一个哨兵能够同时监控多个主机。

  • 怎么启动哨兵?

新建配置sentinel.conf文件,并添加内容(这里是最简化的配置):

sentinel monitor 被监控主机名字(随意) 127.0.0.1(主机的IP) 6379(主机redis的端口号) 1(至少1 个 Sentinel 赞成才进行故障切换)

启动哨兵:redis-sentinel sentinel.conf

  • 每一个哨兵(sentinel)按期执行的任务

a、每一个 Sentinel 以每秒钟一次的频率向它所知的主服务器、从服务器以及其余 Sentinel 实例发送一个 PING 命令。

b、若是一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 那么这个实例会被 Sentinel 标记为主观下线。 一个有效回复能够是: +PONG 、 -LOADING 或者 -MASTERDOWN 。

c、若是一个主服务器被标记为主观下线, 那么正在监视这个主服务器的全部 Sentinel 要以每秒一次的频率确认主服务器的确进入了主观下线状态。

d、若是一个主服务器被标记为主观下线, 而且有足够数量的 Sentinel (至少要达到配置文件指定的数量)在指定的时间范围内赞成这一判断, 那么这个主服务器被标记为客观下线。

e、在通常状况下, 每一个 Sentinel 会以每 10 秒一次的频率向它已知的全部主服务器和从服务器发送 INFO 命令。 当一个主服务器被 Sentinel 标记为客观下线时, Sentinel 向下线主服务器的全部从服务器发送 INFO 命令的频率会从 10 秒一次改成每秒一次。

f、当没有足够数量的 Sentinel 赞成主服务器已经下线, 主服务器的客观下线状态就会被移除。 当主服务器从新向 Sentinel 的 PING 命令返回有效回复时, 主服务器的主管下线状态就会被移除。

  • 一个实例:

假设127.0.0.1 6379  6380 6381三个端口分别启动了redis服务,6380为master,其它为slave,而后启动哨兵(只监控一个master)

哨兵的日志:

2793:X 19 Aug 02:02:42.868 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
2793:X 19 Aug 02:02:42.883 # Sentinel ID is bfbd85c34ae2f4d8f0cd584dda8a90bb44ebe7af
2793:X 19 Aug 02:02:42.883 # +monitor master host6379 127.0.0.1 6380 quorum 1 【监视主机】
2793:X 19 Aug 02:02:42.884 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380 【sentinel识别到的从机6379】
2793:X 19 Aug 02:02:42.885 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380 【sentinel识别到的从机6381】

关闭6380的服务,日志:

2820:X 19 Aug 02:21:32.136 # +sdown master host6379 127.0.0.1 6380                  【主观下线】
2820:X 19 Aug 02:21:32.136 # +odown master host6379 127.0.0.1 6380 #quorum 1/1    【客观下线】
2820:X 19 Aug 02:21:32.136 # +new-epoch 2
2820:X 19 Aug 02:21:32.136 # +try-failover master host6379 127.0.0.1 6380
2820:X 19 Aug 02:21:32.147 # +vote-for-leader bfbd85c34ae2f4d8f0cd584dda8a90bb44ebe7af 2
2820:X 19 Aug 02:21:32.147 # +elected-leader master host6379 127.0.0.1 6380
2820:X 19 Aug 02:21:32.147 # +failover-state-select-slave master host6379 127.0.0.1 6380  【故障转移操做如今处于select-slave状态-sentinel选择能够升级为主的从机】
2820:X 19 Aug 02:21:32.206 # +selected-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380 【已经找到能够升级为主的从机】
2820:X 19 Aug 02:21:32.207 * +failover-state-send-slaveof-noone slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380【故障转移操做如今处于send-slaveof-noone状态-执行slaveof no one命令将从升级为主】
2820:X 19 Aug 02:21:32.292 * +failover-state-wait-promotion slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380【故障转移操做如今处于wait-promotion状态-等待从升级为主】
2820:X 19 Aug 02:21:32.853 # +promoted-slave slave 127.0.0.1:6381 127.0.0.1 6381 @ host6379 127.0.0.1 6380
2820:X 19 Aug 02:21:32.853 # +failover-state-reconf-slaves master host6379 127.0.0.1 6380【故障转移操做如今处于reconf-slaves状态-从新配置院主机的全部从机】
2820:X 19 Aug 02:21:32.906 * +slave-reconf-sent slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2820:X 19 Aug 02:21:33.863 * +slave-reconf-inprog slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2820:X 19 Aug 02:21:33.863 * +slave-reconf-done slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6380
2820:X 19 Aug 02:21:33.939 # +failover-end master host6379 127.0.0.1 6380【故障转移操做顺利完成。全部从服务器都开始复制新的主服务器了】
2820:X 19 Aug 02:21:33.939 # +switch-master host6379 127.0.0.1 6380 127.0.0.1 6381【配置变动,主服务器的 IP 和地址已经改变。 这是绝大多数外部用户都关心的信息】
2820:X 19 Aug 02:21:33.940 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ host6379 127.0.0.1 6381
2820:X 19 Aug 02:21:33.940 * +slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6381
2820:X 19 Aug 02:22:03.944 # +sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6381

从日志能够看出,主机从6380切换到了6381。上面日志也能够当作一次故障转移的步骤。

此时,启动6380端口的服务,日志:

2820:X 19 Aug 02:30:57.570 # -sdown slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6381
2820:X 19 Aug 02:31:07.500 * +convert-to-slave slave 127.0.0.1:6380 127.0.0.1 6380 @ host6379 127.0.0.1 6381

从日志能够看出,原主机down机后,再恢复时候,哨兵会将其做为当前主机(6381)的从机使用

注:在故障切换的时候各个实例的配置文件和sentinel.conf配置文件会自动作出相应的修改

  • 多哨兵模式(来源博客https://blog.csdn.net/enlyhua/article/details/80544135)

哨兵+主从复制保证了redis的高可用,一般为保证哨兵的健壮性,将哨兵部署为集群,至少3个节点

a、为何redis哨兵集群不能为2个节点?

 若是哨兵集群仅仅部署了个2个哨兵实例,Configuration: quorum = 1

+----+          +----+

| M1 |---------| R1 |

| S1 |            | S2 |

+----+         +----+

master宕机,s1(哨兵1)和s2中只要有1个哨兵认为master宕机就能够执行切换,同时s1和s2中会选举出一个哨兵来执行故障转移。同时这个时候,也就是大多数(majority)哨兵都是运行的,可是若是整个M1和S1运行的机器宕机了,那么哨兵只有1个了,此时就没有majority来容许执行故障转移,虽然另一台机器还有一个R1,可是故障转移不会执行。

b、经典的3节点哨兵模式:Configuration: quorum = 2,majority

  +----+
   | M1 |
   | S1 |
  +----+

 +----+          +----+

 | R2 |            | R3 |

 | S2 |            | S3 |

+----+           +----+

若是M1所在机器宕机了,那么三个哨兵还剩下2个,S2和S3能够一致认为master宕机,而后选举出一个来执行故障转移。同时3个哨兵的majority是2,因此还剩下的2个哨兵运行着,就能够容许执行故障转移

c、小结:每次一个哨兵要作主备切换,首先须要quorum数量的哨兵认为odown,而后选举出一个哨兵来作切换,这个哨兵还得获得majority哨兵的受权,才能正式执行切换。若是quorum < majority,好比5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵受权就能够执行切换。可是若是quorum >= majority,那么必须quorum数量的哨兵都受权,好比5个哨兵,quorum是5,那么必须5个哨兵都赞成受权,才能执行切换

六、客户端API链接使用redis

  • 直连redis

首先细读redis.conf文件如下说明,正确配置redis.conf的bind、protect-mode并确认防火墙,不然会致使链接不上redis。

直连redis代码:

package com;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        
        JedisPool jedisPool=new JedisPool("192.168.1.113", 6381);
        Jedis jedis=jedisPool.getResource();
        Set<String> out=jedis.keys("*");
        System.out.println(out);
        jedis.set("zhongguo","weida");

    }
} 
  • 经过哨兵链接redis

首先细读sentinel.conf文件如下说明,正确配置redis.conf的bind、protect-mode并确认防火墙,不然会致使链接不上redis。

经过哨兵链接redis代码

package com;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) {

        Set<String> sentinels=new HashSet<String>();
        sentinels.add("192.168.1.113:26379");//若是有多个哨兵,可继续添加
        JedisSentinelPool jedisSentinelPool=new JedisSentinelPool("host6379", sentinels);
        Jedis jedis=jedisSentinelPool.getResource();
        Set<String> out=jedis.keys("*");
        System.out.println(out);
        jedis.set("shoudu","beijing");
    }
}
相关文章
相关标签/搜索