【Redis】2. Redis持久化、主从与哨兵架构详解

目录

RDB、AOF及混合持久化详解

Redis数据备份策略

Redis主从架构及原理详解 

Redis哨兵高可用架构


RDB、AOF及混合持久化详解

重度依赖Redis缓存集群的架构(例如大型购物网站),当Redis集群出现事故,且没有做Redis持久化的时候,会引起“缓存雪崩”的问题。

持久化的实现:RDB、AOF及混合持久化

RDB快照(snapshot)

【Redis】2. Redis持久化、主从与哨兵架构详解_第1张图片

 这种机制在redis内存比较大(例如好几个G)的情况,是很耗费时间的。且当在执行rdb的save持久化操作时,会阻塞正常的redis请求

修改save配置(redis.conf):

【Redis】2. Redis持久化、主从与哨兵架构详解_第2张图片

【Redis】2. Redis持久化、主从与哨兵架构详解_第3张图片

dump文件无法直接阅读。

bgsave命令(后台执行持久化save操作),称为写时复制机制(COW, Copy-On-Write)

save与bgsave对比
命令 save bgsave
IO类型 同步 异步
是否阻塞redis其他命令 否(生成一个子进程进行调用fork函数时会有短暂阻塞)
时间复杂度 O(n) O(n)
优点 不会消耗额外内存 不阻塞客户端请求
缺点 阻塞客户端请求 需要fork子进程,消耗内存

 

AOF(append-only file)

修改数据(Redis 执行一个改变数据集的命令时的每一条指令记录进文件appendonly.aof中(先写入os cache,每隔一段时间 fsync到磁盘),这种持久化方式,在redis挂掉重启后,更有利于数据集恢复/重建(重新依次执行aof中记录的指令)

配置redis.conf

【Redis】2. Redis持久化、主从与哨兵架构详解_第4张图片

 AOF持久化策略配置:

【Redis】2. Redis持久化、主从与哨兵架构详解_第5张图片

 AOF重写

 在redis执行命令过程中有很多重复低效的命令,例如不断地INCR 同一条数据;因此产生了AOF重写优化机制,即定期根据内存的最新数据重新生成aof文件

【Redis】2. Redis持久化、主从与哨兵架构详解_第6张图片

 手动重写aof文件命令:bgrewriteaof

RBD和AOF:生产环境rbd和aof同时开启的情况下,redis会优先使用aof进行数据集恢复,原因是aof更不容易丢失数据,虽然恢复数据集的执行速度上不如rdb文件快,但数据安全性更高。

 Redis混合持久化

前提:已开启aof持久化方式(可以关掉rdb持久化方式关闭,即注释掉save 配置)

混合持久化AOF文件结构如下:每次执行aof重写时,会将重写那一刻的数据集以rdb文件格式存入到aof文件中,后续写入的数据集修改命令仍然以aof格式追加在appendonly.aof中。这种方式既能提升性能,又能保证数据安全性

【Redis】2. Redis持久化、主从与哨兵架构详解_第7张图片

 混合持久化配置:

【Redis】2. Redis持久化、主从与哨兵架构详解_第8张图片

Redis数据备份策略

1. 写crontab定时调度脚本,每小时都copy一份rdb或aof的备份到一个目录中去,仅仅保留最近48 小时的备份

2. 每天都保留一份当日的数据备份到一个目录中去,可以保留最近1个月的备份

3. 每次copy备份的时候,都把太旧的备份给删了

4. 每天晚上将当前机器上的备份复制一份到其他机器上,以防机器损坏

Redis主从架构及原理详解 

主节点:写数据;

从节点:备份数据,读操作

主从复制全量复制流程图(slave第一次链接上master,并发的slave请求,master只会bgsave一次):

【Redis】2. Redis持久化、主从与哨兵架构详解_第9张图片

主从复制(部分复制、断点续传)流程图:

【Redis】2. Redis持久化、主从与哨兵架构详解_第10张图片 主从复制风暴:是指有很多slave并发发送复制命令,导致主节点压力过大

优化主从架构:

【Redis】2. Redis持久化、主从与哨兵架构详解_第11张图片

 redis主从架构搭建,配置从节点操作:

1、复制一份redis.conf文件,命名为redis6380.conf

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

port 6380

pidfile /var/run/redis_6380.pid # 把pid进程号写入pidfile配置的文件

logfile "6380.log"

dir ./redisdata/port6380 # 指定数据存放目录,启动从节点前,要保证这个文件夹已新建,否则启动会失败

3、配置主从复制

replicaof 192.168.1.4 6379 # 从本机6379的redis实例复制数据,Redis 5.0之前使用slaveof

replica‐read‐only yes # 配置从节点只读

4、启动从节点

src/redis‐server redis6380.conf

5、连接从节点

redis‐cli ‐p 6380

6、测试在6379实例上写数据,6380实例是否能及时同步新修改数据

主节点6379:

【Redis】2. Redis持久化、主从与哨兵架构详解_第12张图片

从节点6380:

 【Redis】2. Redis持久化、主从与哨兵架构详解_第13张图片

 Java项目中使用Jedis链接redis server


    redis.clients
    jedis
    2.9.0

普通链接访问:代码略。。。

管道执行:一次性发送多个请求而不用等待服务器的响应,待所有命令都发送完后再一次性读取服务的响应。目的是减少连接redis server的网络开销,其命令执行并不具有原子性,也就是当一组命令执行过程中,有命令执行失败,并不会中止后续命令的执行。(代码略)

        管道执行的缺点是:当打包的命令太多时,消耗redis server的内存越多。

lua脚本执行:lua脚本执行具有原子性,且也能减少网络开销。(代码略)

Redis哨兵高可用架构

【Redis】2. Redis持久化、主从与哨兵架构详解_第14张图片

 哨兵服务不提供读写服务,仅仅用来监控主节点,当主节点不可用时,选举出新的主节点返回给客户端(redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)

配置:

1、复制一份sentinel.conf文件

cp sentinel.conf sentinel‐26379.conf

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

port 26379

daemonize yes

pidfile "/var/run/redis‐sentinel‐26379.pid"

logfile "sentinel-26379.log"

dir ./sentineldata        #这个目录在启动sentinel之前须新建好,否则无法启动

# sentinel monitor master‐redis‐name master‐redis‐ip master‐redis‐port quorum。quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 + 1),master才算真正失效

sentinel monitor mymaster 192.168.0.60 6379 2

# mymaster这个名字随便取,客户端访问时会用到

3、启动sentinel哨兵实例

src/redis‐sentinel sentinel‐26379.conf

4、查看sentinel的info信息

src/redis‐cli ‐p 26379

127.0.0.1:26379>info

可以看到Sentinel的info里已经识别出了redis的主从

5、可以自己再配置两个sentinel,端口26380和26381,注意上述配置文件里的对应数字都要修改

查看sentinel-26379.conf文件:

【Redis】2. Redis持久化、主从与哨兵架构详解_第15张图片

 哨兵模式验证:哨兵的spring-boot整合Redis链接代码


   org.springframework.boot
   spring-boot-starter-data-redis


   org.apache.commons
   commons-pool2

配置

【Redis】2. Redis持久化、主从与哨兵架构详解_第16张图片

 在demo(代码略)中,写一个while(true)接口,持续往redis中set数据,并get出来。

package com.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {

    private static final Logger logger = LoggerFactory.getLogger(IndexController.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 测试节点挂了哨兵重新选举新的master节点,客户端是否能动态感知到
     *
     * @throws InterruptedException
     */
    @RequestMapping("/test_sentinel")
    public void testSentinel() throws InterruptedException {
        int i = 1;
        while (i<=300){
            try {
                stringRedisTemplate.opsForValue().set("sentinel666"+i, "sentinelTest"+i); //jedis.set(key,value);
                System.out.println("设置key:"+ "sentinel666"+i);
                i++;
                Thread.sleep(1000);
            }catch (Exception e){
                logger.error("错误:", e);
            }
        }
    }

}

程序运行起来后,关闭redis server主节点,此时程序报错time out 3seconds() 

【Redis】2. Redis持久化、主从与哨兵架构详解_第17张图片

报错一段时间后,哨兵选举新的主节点,并发给client端重新链接。且可以看到,key并没有丢失

【Redis】2. Redis持久化、主从与哨兵架构详解_第18张图片

 重新启动6379 redis server,查看哨兵conf文件,可以看到主节点已被替换成6380

【Redis】2. Redis持久化、主从与哨兵架构详解_第19张图片

【Redis】2. Redis持久化、主从与哨兵架构详解_第20张图片

 

你可能感兴趣的:(分布式框架,redis,架构,lua)