分布式缓存(redis)

文章详细介绍了Redis的两种持久化方案:RDB(数据快照)和AOF(追加文件),以及它们的优缺点和执行机制。此外,还讨论了Redis的主从架构和数据同步过程,包括全量同步和增量同步,以及哨兵系统在监控和故障恢复中的作用。最后,提到了缓存问题,如缓存穿透、缓存击穿和缓存雪崩,及其解决方案。
摘要由CSDN通过智能技术生成

Redis 持久化的方案

1、RDB 持久化

       -- RDB ( Redis Database Backup file) redis 数据备份文件
        也叫数据快照,即将缓存数据 写入到磁盘,当 redis 重启 后,会重新加载这些数据,存储数据的文件就是 RDB,存储在redis 的运行目录下

       -- 执行时机
        ① 执行 save 命令  (命令执行时,其他所有的命令都会阻塞,直到该命令执行完毕)
        ② 执行 bgsave 命令  ( bg 是后台运行,不会影响其他命令,是开启了子线程做处理)
        ③ 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主进程得到一个子进程,共享内存空间

                ②,子进程读取内存数据并写入新的RDB文件

                ③,用新RDB文件替换旧的RDB文件

        -- RDB会在什么时候执行?save 60 1000代表什么含义?

                ①,默认是服务停止时

                ②,代表60秒内至少执行1000次修改则触发RDB

        -- RDB的缺点?

                ①,RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险

                ②,fork子进程、压缩、写出RDB文件都比较耗时

2、AOF 持久化

        AOF : Append Only File (追加文件) ,redis 处理的每一个写命令都会记录到 AOF 文件中,相当于一份 操作日志
        由于是记录操作,容易造成历史无意义操作浪费资源,所以需要做重写处理,
可以通过手动操作命令 bgrewriteaof 重写,也可以配置阈值自动重写

AOF 默认关闭,需要在 redis.conf 中配置开启

    # 是否开启AOF功能,默认是no

appendonly yes

    # AOF文件的名称

appendfilename "appendonly.aof"


# 表示每执行一次写命令,立即记录到AOF文件 
#(同步刷盘,可靠性高,几乎不丢失数据,性能影响大)

appendfsync always 

# 写命令执行完先放入AOF缓冲区,然后表示每隔1秒将缓冲区数据写到AOF文件,是默认方案
# (每秒刷盘,性能始终,最多丢失1秒数据)

appendfsync everysec 

# 写命令执行完先放入AOF缓冲区,由操作系统决定何时将缓冲区内容写回磁盘
# (操作系统控制,性能最好,可靠性较差,可能丢失大量数据)

appendfsync no

# AOF文件比上次文件 增长超过多少百分比则触发重写

auto-aof-rewrite-percentage 100

# AOF文件体积最小多大以上才触发重写 

auto-aof-rewrite-min-size 64mb 

 RDB 和 AOF 对比

 

Redis 集群 (主从架构)

        目的在于提高 redis 的并发能力,实现读写分离

 数据同步

        全量同步:对全部数据同步(master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。 )
        增量同步:同步master和slave存在差异的数据,一般是首次全量同步之后才用的方式(slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave )
        偏移量: offset ,指的是 slave 落后于 master 的数据,也是slave 即将要同步的数据

        主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点,
replid 是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid

什么时候执行全量同步?

  • slave节点第一次连接master节点时

  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

什么时候执行增量同步?

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时

        同步流程:

  • slave节点请求增量同步

  • master节点判断replid,发现不一致,拒绝增量同步

  • master将完整内存数据生成RDB,发送RDB到slave

  • slave清空本地数据,加载master的RDB

  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave

  • slave执行接收到的命令,保持与master之间的同步

主从同步优化
        

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。

  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO

  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步

  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

    哨兵 Sentinel

        作用:监控,哨兵会通过不断地 ping master 和 slave 是否正常运行
                自动故障恢复,如果master 出现故障,哨兵会选择一个 slave 变成 新的master,在此之后,如果旧的master恢复,旧的master会变成slave
                通知,哨兵充当客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给redis客户端

主观下线:一个哨兵发现某个redis实例没及时响应

客观下线:多个哨兵(最好是一半)发现同一个实例下线

集群故障恢复原理

  • 首先会判断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节点

项目中配置 哨兵集群
        yml 中配置:

 spring:
  redis:
    sentinel:
      master: mymaster
      nodes:
        - 192.168.150.101:27001
        - 192.168.150.101:27002
        - 192.168.150.101:27003

 可以在启动类中配置bean 

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

ReadFrom.REPLICA_PREFERRED : 读写策略
其包括:

  • MASTER:从主节点读取

  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取replica

  • REPLICA:从slave(replica)节点读取

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

散列插槽

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,

数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分

  • key中不包含“{}”,整个key都是有效部分

Redis 判断 key 在哪个实例的流程:

  • 将16384个插槽分配到不同的实例

  • 根据key的有效部分计算哈希值,对16384取余

  • 余数作为插槽,寻找插槽所在实例即可

使用相同的key有效部份,可以将相同类型的数据保存到同一个实例中

缓存问题

缓存穿透

​ 指缓存中没有数据,数据库中也没有数据(黑客攻击)

解决方案一:缓存空对象,即对于在数据库中和缓存中都不存在的数据,第一次读取到为null时,在缓存中就存一个空值。读取缓存的时候,如果缓存中存在,且为空对象,直接返回即可。

解决方案二:使用布隆过滤器,所谓布隆过滤器,我们可以理解其为一个集合,这个集合只存储数据的key而不存储数据值,主要用来判断一个key存在还是不存在。布隆过滤器的介绍见数学之美:布隆过滤器 - 知乎

缓存击穿

​ 指定key的数据在数据库中存在,数据在redis中已经过期了,在高并发场景下,同一个key对应的数据会从数据库被多次读取,数据库压力过大

解决方案:热点数据不过期

缓存雪崩,所谓缓存雪崩,大量key同时过期

解决方案:随机过期时间


删除策略

1.定时删除

        ​ key过期就删除,以时间换空间

2.惰性删除

​          下次get时删除,以空间换时间

3.定期删除

        ​ 每秒钟给出一定时间来进行随机扫描,扫描到过期的key就删除,如果过期的key占比比较多,那么下次还是扫描该数据库

逐出策略

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值