学习【Redis高级篇】这一篇就够了

1. 分布式缓存

1-1. Redis持久化

RDB持久化

RDB全称 Redis Database Backup file(Redis数据备份文件),也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。快照文件称为RDB文件,默认是保存在当前运行目录

RDB持久化在四种情况下会执行:

  • 执行save命令
  • 执行bgsave命令
  • Redis停机时
  • 触发RDB条件时

1)save命令

执行下面的命令,可以立即执行一次RDB:

在这里插入图片描述

save命令会导致主进程执行RDB,这个过程中其它所有命令都会被阻塞。只有在数据迁移时可能用到。

2)bgsave命令

下面的命令可以异步执行RDB:

在这里插入图片描述

这个命令执行后会开启独立进程完成RDB,主进程可以持续处理用户请求,不受影响。

3)停机时

Redis停机时会执行一次save命令,实现RDB持久化。

4)触发RDB条件

Redis内部有触发RDB的机制,可以在redis.conf文件中找到(保持默认即可),格式如下:

# 900秒内,如果至少有1个key被修改,则执行bgsave , 如果是save "" 则表示禁用RDB
save 900 1  
save 300 10  
save 60 10000 

# 是否压缩 ,建议不开启,压缩也会消耗cpu,磁盘的话不值钱
rdbcompression yes

# RDB文件名称
dbfilename dump.rdb  

# 文件保存的路径目录
dir ./ 

RDB原理

当 bgsave 执行时,主进程会 fork(fork()是unix和linux这种操作系统的一个api) 一个子进程,子进程共享主进程的内存数据,完成fork后子进程读取内存数据并写入 RDB 文件。

当子进程读取内存数据写入 RDB 文件时,主进程可以继续进行工作,依靠的是 copy-on-write 技术。

  • 当主进程执行读操作时,直接访问共享内存即可。
  • 当主进程执行写操作时,则会在内存中拷贝一份数据,对拷贝的数据执行写操作,这样不会影响到子进程读取的内存数据。

在这里插入图片描述

如果不使用copy-on-write会怎么样?

  • 不使用copy-on-write,就意味着子进程在进行写RDB文件时,主进程可以修改子进程要读取的内存数据,那么就无法保证某一时刻数据的一致性。
  • 比如,在某一时刻k1 : 1,k2:2,子进程将k1写入到RDB文件后,此时主进程对k2进行了修改,子进程再读取k2就不是2了,造成了数据不一致问题。

RDB缺点:

  • 两次RDB之间写入数据有丢失风险。

AOF持久化

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。(由主进程先写入到缓冲区,之后由后台线程将缓冲区中的数据写入到AOF文件

在这里插入图片描述

AOF配置

AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF:

# 是否开启AOF功能,默认是no
appendonly yes
# AOF文件的名称
appendfilename "appendonly.aof"
# 表示每执行一次写命令,立即记录到AOF文件
appendfsync always 
# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
appendfsync everysec 
# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
appendfsync no

在这里插入图片描述

AOF文件重写

因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行 bgrewriteaof 命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。

在这里插入图片描述

Redis会在触发阈值时自动去重写AOF文件(开启子进程执行)。阈值也可以在redis.conf中配置:

# AOF文件比上次文件 增长超过多少百分比则触发重写
auto-aof-rewrite-percentage 100
# AOF文件体积最小多大以上才触发重写 
auto-aof-rewrite-min-size 64mb 

RDB与AOF对比

RDB和AOF各有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

如果两者同时开启,会优先执行AOF文件

在这里插入图片描述

总结

RDB:

  • RDB是一种快照持久化方法,它会在指定的时间间隔内生成数据的完整快照。
  • 适合于灾难恢复,可以很方便的被迁移到另一个数据中心。
  • RDB在保存快照时速度快,恢复时也非常迅速,适合用作备份
  • 最后一次快照之后的数据可能会丢失,因为这部分数据还没有被写入快照。

AOF:

  • AOF记录每一个写命令到AOF文件
  • AOF提供了更好的数据安全性,可以配置为每秒同步一次,或者每写入一条命令就同步一次。
  • AOF文件通常会比RDB文件更大,且恢复速度可能会更慢,但可以通过AOF文件重写进行压缩。
  • AOF在系统崩溃时能最大化数据恢复,最多只丢失几秒钟的数据。

如果需要快速恢复且可以接受少量数据丢失RDB可能是更好的选择。

如果数据的完整性非常关键且可以接受较慢的恢复速度,则应该使用AOF。

在很多场景下,结合使用RDB和AOF能提供更为可靠的数据保护机制。

1-2. Redis主从集群

单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。

在这里插入图片描述

假设有A、B两个Redis实例,如何让B作为A的slave节点?

B节点执行命令:slaveof(replicaof) A的IP A的port

全量同步

在这里插入图片描述

简述全量同步的流程?

  • slave节点首先请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB文件,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

增量同步

在这里插入图片描述

主从优化

在这里插入图片描述

总结

简述全量同步和增量同步区别?

  • 全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个将命令发送给slave。
  • 增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave

什么时候执行全量同步?

  • slave节点第一次连接master节点时
  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

什么时候执行增量同步?

  • slave节点重启后,并且在repl_baklog中能找到offset时

1-3. Redis哨兵

Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。

哨兵的结构如图:

在这里插入图片描述

哨兵作用

  • 监控:Sentinel 会不断检查您的 master 和slave是否正常工作(每隔1s发送 ping 命令,查看是否有回应)
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

集群监控原理

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

  • 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线
  • 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

在这里插入图片描述

集群故障恢复原理

一旦发现master故障,sentinel需要在salve中选择一个作为新的master,选择依据是这样的:

  • 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  • 如果slave-prority一样,则判断slave节点的offset值越大说明数据越新,优先级越高
  • 最后是判断slave节点的运行id大小,越小优先级越高。
  • 也就是挑选一个延迟最小、优先级最高且数据最完整的节点来晋升为新的主节点

当选出一个新的master后,该如何实现切换呢?

流程如下:

  • sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
  • sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  • 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

在这里插入图片描述

RedisTemplate访问哨兵

在Sentinel集群监管下的Redis主从集群,其节点会因为自动故障转移而发生变化,Redis的客户端必须感知这种变化,及时更新连接信息。Spring的RedisTemplate底层利用lettuce实现了节点的感知和自动切换。

1、依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2、配置Redis的sentinel地址

在配置文件application.yml中指定redis的sentinel相关信息:

spring:
  redis:
    sentinel:
      master: mymaster # 在sentinel.coinfig文件中设置的主节点的名称
      nodes:
        - 192.168.150.101:27001
        - 192.168.150.101:27002
        - 192.168.150.101:27003

3、配置读写分离

@Bean
public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
    return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
}

这个bean中配置的就是读写策略,包括四种:

  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica
  • REPLICA:从slave(replica)节点读取
  • REPLICA _PREFERRED:优先从slave(replica)节点读取,所有的slave都不可用才读取master

总结

Sentinel的三个作用是什么?

  • 监控:监控每个节点的健康状态,也就是每隔1s向每个节点发送ping命令
  • 故障转移:如果master节点故障,Sentinel会从从节点中挑选一个延迟最小、优先级最高且数据最完整的节点来晋升为新的主节点
  • 通知:当集群发生故障转移时,会将最新信息推送给Redis的客户端

Sentinel如何判断一个redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没有响应则认为是主观下线
  • 如果大多数sentinel都认为实例主观下线,则判定客观下线

故障转移原理?

  • 如果master节点故障,Sentinel会从从节点中挑选一个延迟最小、优先级最高且数据最完整的节点来晋升为新的主节点

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点的配置,添加slaveof 新master

1-4. Redis分片集群

在这里插入图片描述

散列插槽

集群伸缩

故障转移

2. 多级缓存

在这里插入图片描述

2-1. 浏览器客户端缓存

2-2. nginx缓存

2-3. Redis缓存

2-4. 本地进程缓存

3. Redis最佳实践

3-1. 如何设计优化的Key

Redis的Key虽然可以自定义,但最好遵循下面的几个最佳实践约定:

  • 遵循基本格式:[业务名称]:[数据名称]:[id]
  • 长度不超过44字节(Redis 4.0+)、Redis 4.0 以下的,长度不超过39字节
  • 不包含特殊字符

例如:我们的登录业务,保存用户信息,其key可以设计成如下格式:

在这里插入图片描述

这样设计的好处:

  • 可读性强
  • 避免key冲突
  • 方便管理
  • 更节省内存: key是string类型,底层编码包含int、embstr和raw三种。embstr在小于44字节使用,采用连续内存空间,内存占用更小。当字节数大于44字节时,会转为raw模式存储,在raw模式下,内存空间不是连续的,而是采用一个指针指向了另外一段内存空间,在这段空间里存储SDS内容,这样空间不连续,访问的时候性能也就会收到影响,还有可能产生内存碎片

3-2. 拒绝BigKey

推荐值:

  • 单个key的value小于10KB
  • 对于集合类型的key,建议元素数量小于1000

3-3. 恰当的数据类型

在这里插入图片描述

在这里插入图片描述

3-3. 批处理优化

批量处理的方案:

  • 原生的 MSET 等操作
  • Pipeline 批处理

注意事项:

  • 批处理时不建议一次携带太多命令
  • Pipeline的多个命令之间不具备原子性
  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
黑马Redis高级是一个关于Redis高级应用的教程。在这个教程中,涉及到了创建文件和目录的操作,以及配置Redis实例的过程。在创建文件和目录的步骤中,可以使用以下命令: 1. 创建文件和目录: - 创建redis目录:cd /home && mkdir redis - 在redis目录下创建myredis1、myredis2和myredis3目录:mkdir /home/redis/myredis1, mkdir /home/redis/myredis2, mkdir /home/redis/myredis3 - 在myredis1、myredis2和myredis3目录分别创建myredis.conf配置文件和data目录:touch /home/redis/myredis1/myredis.conf, mkdir /home/redis/myredis1/data, touch /home/redis/myredis2/myredis.conf, mkdir /home/redis/myredis2/data, touch /home/redis/myredis3/myredis.conf, mkdir /home/redis/myredis3/data - 创建mysentinel1、mysentinel2和mysentinel3目录:mkdir /home/redis/mysentinel1, mkdir /home/redis/mysentinel2, mkdir /home/redis/mysentinel3 2. Redis实例信息如下: - IPPORT角色 - 10.13.164.55:7001 master - 10.13.164.55:7002 master - 10.13.164.55:7003 master - 10.13.164.55:7004 slave - 10.13.164.55:7005 slave - 10.13.164.55:7006 slave 根据这些信息,你可以按照上述步骤创建文件和目录,并配置Redis实例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [黑马Redis6高级](https://blog.csdn.net/D_boj/article/details/131712945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值