zoukankan      html  css  js  c++  java
  • Redis学习笔记七:主从复制和哨兵

    作者:Grey

    原文地址:Redis学习笔记七:主从复制和哨兵

    单机,单节点,单实例的Redis会有什么问题呢?

    容易导致单点故障,那么如何解决呢?

    可以通过主备方式

    image

    同时可以实现读写分离

    image

    这里的每个节点是全量的,镜像的。

    单节点的容量有限而且单点的压力比较大,如何解决呢?

    可以分不同的实例来存不同的业务数据

    每种业务数据也可以根据不同的规则放到同一组的Redis库中

    引入多个Redis实例后,会出现数据一致性的问题,如何解决呢?

    如果要达到强一致性(同步方式),就容易导致不可用性,比如一个节点写成功后,同步到其他节点,假设其他节点有一个网络延迟或者故障,就会导致整个服务不可用,所以,如果要保证可用 ,需要容忍丢失一些数据(主节点写成功立即给客户端返回成功,异步把数据同步到其他备用节点)。如果要保证数据不丢失(保证最终一致性),可以考虑使用消息队列。

    image

    这里就要求消息队列本身是可靠的,这种方式保证了最终一致性,也会有问题,比如多个客户端访问的时候,有可能会取到不一致的数据。

    主从方式

    客户端可以访问主,也可以访问从

    主备方式

    客户端只访问主,不访问备,只有当主挂了才访问备

    无论主从和主备,主都成了单点故障,如何解决这个问题呢?

    所以必须要对主做HA(比如主挂了,从机顶上去做主机)
    要对主进行HA,必须要选择一个高可用的监控程序,
    监控程序的设计要考虑,是多个监控程序报告Redis挂了才算Redis真的挂了(如果不这样,容易产生脑裂问题,即:出现数据分区)

    如果有N个节点,需要N/2+1个节点报告异常(过半),才算真的异常。

    脑裂是否要处理,要看你的分区容忍性。

    机器的台数是奇数比较好。

    主从复制实验

    通过install_server.sh脚本在一台机器安装三个redis实例

    • 6379

    • 6380

    • 6381

    首先停掉这三个实例,然后把这三个实例的配置文件统一放到一个地方,我放在/data目录下

    cp /etc/redic/*.conf /data/
    

    修改三个实例的如下配置

    # 关闭aof
    appendonly no
    
    # 设置前台运行
    daemonize no
    
    # 注释掉logfile
    # logfile /var/log/redis_6379.log
    

    然后启动三个实例

    redis-server /data/6379.conf
    redis-server /data/6380.conf
    redis-server /data/6381.conf
    

    启动客户端

    redis-cli -p 6379
    redis-cli -p 6380
    redis-cli -p 6381
    

    把6380 和 6381 设置为6379的从机,在6380和6381两个客户端均执行

    replicaof 127.0.0.1 6379
    

    我们在6379客户端执行一条语句

    set k1 from6379
    

    然后在6380和6381都执行

    127.0.0.1:6381> get k1
    "from6379"
    
    127.0.0.1:6380> get k1
    "from6379"
    

    可以看到从机同步到了主机的数据

    在6380或者6381中任意一台的客户端执行

    127.0.0.1:6381> set k2 asdfasd
    (error) READONLY You can't write against a read only replica.
    
    

    会提示如下信息:

    (error) READONLY You can't write against a read only replica.
    

    即在从机无法做写操作。

    假设两台从机挂了一台,挂完以后,主机还做了若干次的操作,此时如果挂了的从机继续启动(以--appendonly no模式),只会增量同步数据。
    如果是以appendonly yes方式启动挂了的从机,则会触发全量同步

    rdb方式可以记录当初追随者的信息,所以可以做到增量,而aof不会记录,所以只能全量。

    假如主机挂了,由于从只能读不能写,我们可以人为把其中的一台从机变成主(先在这个从机上执行:replicaof no one),然后让另外一个从机追随这个主即可,追随过程中,如果从机开启了replica-serve-stale-data=yes, 则从机在同步主机数据的时候,还可以查询自身的旧数据,

    replica-diskless-sync yes 表示直接用网络来同步主机和从机的数据(不落磁盘),这种情况一般适用于磁盘性能低于网络性能的情况。

    repl—backlog-size 1mb
    主机维护的队列大小,防止从机重启后又挂掉,这个维护的是一个偏移量,如果写的频率不高,则可以设置为1mb,如果写的频率非常高,这个值要适当调大。

    # 规定最少写成功的数值
    min-replicas-to-write 3
    min-replicas-max-lag 10
    

    主从复制的问题:

    所以需要人工维护主的故障问题!

    所以需要HA, HA如何做呢?

    引入:sentinel机制

    sentinel实验

    保持前面配置的三个主机(一主两从)为启动状态
    其中6379为主,6380和6381为从。

    准备三个sentinel的配置文件(配置成监控主机)

    在/data/redis/sentinel目录下准备:26380.conf,26381.conf,26379.conf三个配置文件,配置文件中配置如下内容,以26379.conf为例(其他两个同理)

    port 26379
    sentinel monitor mymaster 127.0.0.1 6379 2
    

    配置说明见:http://www.redis.cn/topics/sentinel.html

    准备好三个配置后,我们以sentinel模式启动三个实例,启动命令如下:以26379为例,其他两个同理。

    redis-server /data/redis/sentinel/26381.conf --sentinel
    

    启动好以后,我们模拟主机挂掉,停掉6379这个实例,

    service redis_6379 stop
    

    查看任何一个sentinel实例的日志,发现开启新的epoch,并选出了新的主为6380

    4594:X 29 May 2021 16:32:19.997 # +new-epoch 1
    4594:X 29 May 2021 16:32:19.999 # +vote-for-leader 27e706bf27e99c10310c6c9595fcffef63d67e60 1
    4594:X 29 May 2021 16:32:20.762 # +config-update-from sentinel 27e706bf27e99c10310c6c9595fcffef63d67e60 127.0.0.1 26380 @ mymaster 127.0.0.1 6379
    4594:X 29 May 2021 16:32:20.762 # +switch-master mymaster 127.0.0.1 6379 127.0.0.1 6380
    4594:X 29 May 2021 16:32:20.762 * +slave slave 127.0.0.1:6381 127.0.0.1 6381 @ mymaster 127.0.0.1 6380
    4594:X 29 May 2021 16:32:20.762 * +slave slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
    
    

    用一个客户端连接6380,进行set操作

    [root@base ~]# redis-cli -p 6380
    127.0.0.1:6380> set k1 ddd
    OK
    

    操作成功,然后连接6381,尝试get k1

    [root@base ~]# redis-cli -p 6381
    127.0.0.1:6381> get k1
    "ddd"
    

    获取到了最新的数据,此时重新启动6379这个实例,然后打开任何一个sentinel的运行日志

    4594:X 29 May 2021 16:32:50.823 # +sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
    4594:X 29 May 2021 16:36:16.528 # -sdown slave 127.0.0.1:6379 127.0.0.1 6379 @ mymaster 127.0.0.1 6380
    

    发现6379已经作为从机追随了6380
    尝试在6379中get和set值

    [root@base ~]# redis-cli -p 6379
    127.0.0.1:6379> get k1
    "ddd"
    127.0.0.1:6379> set k1 asdf
    (error) READONLY You can't write against a read only replica.
    

    可以get,无法set了。

    更多

    由于主机知道自己有几个从机,所以sentinel只要监控了主机,就同时也可以知道主机有几个从机。
    那么一个sentinel是如何知道其他的sentinel的呢?用到了redis中的发布订阅的功能。

  • 相关阅读:
    个人技能总结8--linux 基本命令的使用
    个人技能总结7--Apache服务器反向代理,负载均衡,热备份+Tomcat配置
    个人技能总结6--Java网络接口以及协议
    个人技能总结5--Redis在Javaweb项目中的应用
    个人技能总结4--MongoDB在windows上安装以及java中的增删改查
    个人技能总结3--Mysql--20170828
    从源码的角度解读String、StringBuilder、StringBuffer的性能差别
    java二叉树的实现
    如何理解递归?
    继承泛型类
  • 原文地址:https://www.cnblogs.com/greyzeng/p/14815454.html
Copyright © 2011-2022 走看看