码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 03-Redis主从架构


    上一篇:02-Redis持久化

    1.主从架构搭建

    配置从节点步骤:

    1、复制一份redis.conf文件

    2、将相关配置修改为如下值:

    port 6380
    pidfile /var/run/redis_6380.pid  # 把pid进程号写入pidfile配置的文件
    logfile "6380.log"
    dir /usr/local/redis-5.0.3/data/6380  # 指定数据存放目录
    # 需要注释掉bind
    # bind 127.0.0.1(bind绑定的是自己机器网卡的ip,如果有多块网卡可以配多个ip,代表允许客户端通过机器的哪些网卡ip去访问,内网一般可以不配置bind,注释掉即可)
    
    3、配置主从复制
    replicaof 192.168.0.60 6379   # 从本机6379的redis实例复制数据,Redis 5.0之前使用slaveof
    replica-read-only yes  # 配置从节点只读
    
    4、启动从节点
    redis-server redis.conf   # redis.conf文件务必用你复制并修改了之后的redis.conf文件
    
    5、连接从节点
    redis-cli -p 6380
    
    6、测试在6379实例上写数据,6380实例是否能及时同步新修改数据
    
    7、可以自己再配置一个6381的从节点
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.主从工作原理

    在这里插入图片描述

    如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个PSYNC命令给master请求复制数据。

    master收到PSYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。

    当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

    主从复制(全量复制)流程图:
    在这里插入图片描述

    数据部分复制
    当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据,slave与master能够在网络连接断开重连后只进行部分数据复制(断点续传)。
    master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。

    主从复制(部分复制,断点续传)流程图:
    在这里插入图片描述

    如果有很多从节点,为了缓解主从复制风暴(多个从节点同时复制主节点导致主节点压力过大),可以做如下架构,让部分从节点与从节点(与主节点同步)同步数据
    在这里插入图片描述

    Jedis连接代码示例:

    引入相关依赖:

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    访问代码:

    public class JedisSingleTest {
        public static void main(String[] args) throws IOException {
    
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(20);
            jedisPoolConfig.setMaxIdle(10);
            jedisPoolConfig.setMinIdle(5);
    
            // timeout,这里既是连接超时又是读写超时,从Jedis 2.8开始有区分connectionTimeout和soTimeout的构造函数
            JedisPool jedisPool = new JedisPool(jedisPoolConfig, "192.168.0.60", 6379, 3000, null);
    
            Jedis jedis = null;
            try {
                //从redis连接池里拿出一个连接执行命令
                jedis = jedisPool.getResource();
    
                System.out.println(jedis.set("single", "gwx"));
                System.out.println(jedis.get("single"));
    
                //管道示例
                //管道的命令执行方式:cat redis.txt | redis-cli -h 127.0.0.1 -a password - p 6379 --pipe
                /*Pipeline pl = jedis.pipelined();
                for (int i = 0; i < 10; i++) {
                    pl.incr("pipelineKey");
                    pl.set("zhuge" + i, "zhuge");
                }
                List results = pl.syncAndReturnAll();
                System.out.println(results);*/
    
                //lua脚本模拟一个商品减库存的原子操作
                //lua脚本命令执行方式:redis-cli --eval /tmp/test.lua , 10
                /*jedis.set("product_count_10016", "15");  //初始化商品10016的库存
                String script = " local count = redis.call('get', KEYS[1]) " +
                                " local a = tonumber(count) " +
                                " local b = tonumber(ARGV[1]) " +
                                " if a >= b then " +
                                "   redis.call('set', KEYS[1], a-b) " +
                                "   return 1 " +
                                " end " +
                                " return 0 ";
                Object obj = jedis.eval(script, Arrays.asList("product_count_10016"), Arrays.asList("10"));
                System.out.println(obj);*/
    
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //注意这里不是关闭连接,在JedisPool模式下,Jedis会被归还给资源池。
                if (jedis != null)
                    jedis.close();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    下一篇:

  • 相关阅读:
    Web APIs:事件高级--DOM事件流及DOM事件流程代码验证
    16.使用 Dockerfile 定制镜像
    细谈MySQL的一下经典问题(一)
    VUE3 之 插件的使用 - 这个系列的教程通俗易懂,适合自学
    使用oracle虚拟机添加新硬盘
    将Lombok @Getter用于boolean 和Boolean 字段
    FPGA - ZYNQ 基于Axi_Lite的PS和PL交互
    Kubernetes学习笔记-保障集群内节点和网络安全(2)配置节点的安全上下文20220828
    安全加固:Eureka服务实例安全令牌配置全解析
    数据采集的基本方法?
  • 原文地址:https://blog.csdn.net/weixin_40461030/article/details/132835411
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号