zoukankan      html  css  js  c++  java
  • Redis系统学习之主从复制

    Redis主从复制

    • 什么是主从复制(来自小姐姐的面试题72)?
    • 使用一个redis实例作为主机,其余的作为备份机。主机和备份的数据完全一致,主机支持写入和读取操作,而从机只支持数据同步和读取操作。客户端将数据写入当主机,由主机自动将数据同步到从机。因而可以将写入数据的命令发送给主机执行,读取数据的命令发送给不同的从机执行,达到读写分离的目的。(64为mysql的主从同步原理)
      • slave从节点不会竞选成为master,因为每个客户端连接redis实例时都指定了ip和端口号,如果所连接的redis实例故障下线了,而主从模式没有提供手段通知客户端另外可连接的客户端地址,则需要手动更改客户端配置重新连接。
      • 优点:7点
        • 一个master可以同步多个slaves
        • slave同样可以接收其他slaves的连接和同步请求,有效分载master的同步压力
        • master server是以非阻塞的方式为slaves提供服务,在master-slave同步期间,客户端仍然可以提交查询或修改的请求
        • slave server也是以非阻塞的方式完成数据同步,在同步期间,客户端提交查询请求,则返回同步前的数据
        • 为了分载master的读操作压力,slave服务器可以为客户端提供只读操作的服务,写服务由master来完成,系统的伸缩性得到了很大的提高
        • master可以将数据保存操作交给slaves完成,避免在master中要有独立的进程来完成此操作(不是写操作由master完成吗?)
        • 应该是由Master写到内存,然后slaves同步到自己的里面的
        • 支持主从复制,主机会自动将数据同步到从机,读写分离
      • 缺点:4点
        • redis不具备自动容错和恢复功能,主从机宕机都会导致前端部分读写请求失败,需要等待重启或手动切换前端ip才能恢复
        • 主机宕机前有部分数据未能及时同步到从机,切换ip后数据不一致,降低系统可用性
        • redis的主从复制采用全量复制,复制过程中主机会fork出一个子进程对内存做一份快照,并将子进程对内存快照保存为文件发送给从机。需要确保主机有足够多的内存空间,若快照文件较大,对集群对服务能力会产生较大的影响。而且复制过程是在从机新加入或从机和主机网络断连时都会进行,也就是网络波动会造成主机和从机间的一次全量复制,对系统运营造成麻烦。
        • redis较难支持在线扩容,运维人员在系统上线时必须确保有足够的空间,这对资源造成很大浪费
      • 主从复制的作用主要包括:
        • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
        • 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,实际上是一种服务的冗余
        • 负载均衡:在主从复制的基础上,,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(就是写redis数据时应用连接主节点,读redis数据时,应用连接从节点),分担服务器负载,尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高redis服务器的并发量
        • 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础
      • 一般来说Redis在项目中,不可能是一台的,当然也有,我之前做的就是
        • 从结构上,单个Redis服务器存在单点故障问题,并且一台服务器需要处理所有的请求负载,压力较大
        • 从容量上,单个Redis服务器内存容量有限,就算一台Redis服务器内存容量为256G,也不可能将所有内存用作Redis的存储内存,一般来说线上服务器,单台Redis最大使用内存不应该超过20G
      • 电商网站上的商品,一般都是一次上传,无数次浏览,其实就是读多写少
        • 对于这种场景我们可以使用下面这种架构
        • image.png

    环境搭建

    启动源redis

    image.png

    连接查看信息

    [root@localhost bin]# redis-cli 连接客户端
    127.0.0.1:6379> info replication
    NOAUTH Authentication required.
    127.0.0.1:6379> auth 123456 #认证
    OK
    127.0.0.1:6379> info replication 查看redis的信息
    # Replication
    role:master #当前位主节点
    connected_slaves:0 #没有从节点
    master_replid:32128903c20911483fef0c990175fc21c4139fac
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:0
    second_repl_offset:-1
    repl_backlog_active:0
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:0
    repl_backlog_histlen:0
    127.0.0.1:6379> config set requirepass "" # 设置密码为空,老麻烦了,老需要认证
    OK
    127.0.0.1:6379>

    打开四个窗口,从左到右称为A B C D,上面的操作是A完成的

    image.png

    全部切换到 /usr/local/bin 目录下

    A,关闭redis,因为刚才连接查看信息,后还在连接中,执行shutdown就可以了

    image.png

    A,查看服务已经关闭

    image.png

    A进入到redisConfig目录下,拷贝三份配置文件,拷贝redis.conf为 redis-6379.conf redis-6380.conf redis-6381.conf,因为默认的端口是6379,我是端口号直接往上加的,不用原来的配置文件,防止修改错误

    image.png

    A,修改redis-6379.conf redis-6380.conf redis-6381.conf三个配置文件

    vi redis-6379.conf
    logfile "" 修改为 logfile "6379.log"
    dbfilename dump.rdb 修改为 dbfilename dump-6379.rdb
    vi redis-6380.conf
    port 6379 修改为 port 6380
    pidfile /var/run/redis_6379.pid 修改为 pidfile /var/run/redis_6380.pid
    logfile "" 修改为 logfile "6380.log"
    dbfilename dump.rdb 修改为  dbfilename dump-6380.rdb
    vi redis-6381.conf
    port 6379 修改为 port 638
    pidfile /var/run/redis_6379.pid 修改为 pidfile /var/run/redis_6381.pid
    logfile "" 修改为 logfile "6381.log"
    dbfilename dump.rdb 修改为  dbfilename dump-6381.rdb

    A运行redis-6379.conf

    image.png

    B运行redis-6380.conf

    image.png

    C 运行redis-6381.conf

    image.png

    D 执行查看服务

    image.png

    一主二从配置(命令配置,命令配置是暂时的,就像设置密码一样缓存丢失,密码失效):

    默认情况下,每台服务器都是主节点

    只需要配置从机就可以了

    规划:6379为主,80 81为从

    A B C 都连接自己的redis进入cli界面

    A:

    image.png

    B:

    image.png

    C:

    image.png

    只需要配置从节点就可以了,主节点不用动

    B:执行设置主节点

    命令:slaveof ip port

    image.png

    A:查看自己节点信息

    image.png

    C:执行设置主节点

    image.png

    A:查看自己的节点状态

    image.png

    一主二从搭建完成

    配置文件配置(上面配置文件中没有写,在这里写)

    # replicaof <masterip> <masterport> 删除前面的井号, 然后 后面的两个标签 分别是写 ip 和 端口的
    # masterauth <master-password> 如果主节点有密码,删除前面的井号,后面的标签 写主节点的密码就可以了

    刚才的命令也是在配置replicaof获取一下就看见了

    B 获取从机配置文件中的replicaof

    image.png

    可以看到 就是IP 和端口

    测试:

    主机断开后,丛机依旧能获取到数据,但是这个时候没有了写操作,并且丛机不能自动提升为主机

    主机重启成功后,从节点会自动连接到主节点,这个时候丛机依旧可以从主节点同步

    如果丛机是采用命令行配置的主从,那么丛机宕机后重启就会自动变回原来的主节点,需要重新设置为从节点,并且在第一次连接主节点的时候,做全量数据复制,之后做增量复制

    这种是默认的一主二从

    架构的演变(层层链路模式)

    6379为主节点,他的子节点是6380,6380的子节点是6381,所以他是从节点也是主节点,当然在6379还活着的时候他是从节点,如果6379宕机了,那么6380可以通过 slaveof no one使自己变成主节点,当然是手动的,但是层层链路有个问题,那就是中间节点宕机了,那么需要手动将他的下级节点指向他的上级节点,也就是说将6381指向6379,来完善链路

    这里就可以有我想到了一个解决方案:

    因为这个层层链路本省就是一个链表我们可以在,内存中维护这个链表,一旦中间的节点宕机,我们将这个链拿出来,等待重启之后添加到最后面,并指定他的主节点为最后一个层节点

    类似于 1->2->3->4->5

    在这个时候3宕机了,那么4直接指定自己的父节点为2

    等3重启之后,直接指定自己的父节点为5就变成了

    1->2->4->5->3

    当然在工作中这些都是不用的[那我在学什么[手动滑稽]]

    redis主从复制的核心原理(来自小姐姐的面试题73)

    通过执行slaveof命令设置slaveof选项,当写操作导致数据变化时会自动将数据同步给从数据库,一个主库可以有多个从库,而一个从库只能有一个主库。

    • 全量复制
      • 主节点通过bgsave命令fork一个子进程进行RDB持久化,生成一个dump.rdb的全量快照文件,该过程是非常消耗CPU、内存(页表复制)、硬盘IO的
      • 主节点通过网络将RDB文件发送给从节点,对主节点的带宽会带来很大的消耗
      • 从节点清空老数据,载入新RDB文件的过程是阻塞的,无法响应客户端的命令,如果从节点执行bgrewriteaof(bg rewrite AOF)也会带来额外的消耗
    • 部分复制
      • 复制偏移量:执行复制的双方,主从节点分别会维护一个复制偏移量offset,当主从节点回复的偏移量记录不同时,以主节点为准
      • 复制积压缓冲区:主节点内部维护了一个固定长度(可以指定,也可临时更改长度)的、先进先出(FIFO)队列作为复制积压缓冲区,将offset后的数据放入队列,每次增量复制时,同步缓存区中的数据即可,避免操作硬盘。当主从节点的offset差距过大超过缓冲区长度时,将无法执行部分复制,只能全量复制
      • 服务器运行ID(runid):每个redis节点在启动时自动生成运行id,主节点会将自己的运行id发给从节点,从节点会保存起来,当主从节点断开后重连,从节点根据运行id判断同步方式:
        • 若从节点保存的runid与主节点现在的runid相同,说明之前有过同步,主节点会继续尝试使用部分复制(具体看offset和复制积压缓冲区的情况)
        • 若runid不同,说明主节点宕机并发生重新选举,断线前同步的redis节点不是当前主节点,只能进行全量复制

    image.png

     

    作者:彼岸舞

    时间:202155

    内容关于:Redis

    本文属于作者原创,未经允许,禁止转发

  • 相关阅读:
    ORA-01733: virtual column not allowed here
    五年磨一剑:Java 开源博客 Solo 1.0.0 发布了!
    五年磨一剑:Java 开源博客 Solo 1.0.0 发布了!
    关于Java中equal函数和==的一些区别
    <Android Framework 之路>Android5.1 Camera Framework(四)——框架总结
    Sqlite基本命令集合(linux/fedora/ubuntu)
    简介分布式计算系统的硬件架构
    <Android Framework 之路>Android5.1 Camera Framework(三)
    “调试器的协议与调试对象不兼容”错误的解决
    log4j:WARN Please initialize the log4j system properly.解决方案
  • 原文地址:https://www.cnblogs.com/flower-dance/p/14731212.html
Copyright © 2011-2022 走看看