Redis进阶知识点(可学习,可复习,可面试)

小威要向诸佬学习呀 发表于 2022/06/08 16:51:02 2022/06/08
【摘要】 面试中常问的问题,本篇文章介绍的非常详细哟,来看看你都知道哪些吧

声明:
这篇文章主要讲解了面试中常问到的几个问题,主要是redis的缓存,持久化,和缓存中遇到的几个难题和解决方式。介绍的比较详细,很适合小白。
同时刚学完或者准备面试的大佬也可以看看哟
如果文章中有什么不准确或者需要改进的地方,请在评论区留言或者私聊哦。
在这里先感谢各位小伙伴了
在这里插入图片描述

🚗 redis缓存

在这里插入图片描述

🚓缓存概念及作用

缓存就是数据交换的缓冲区(称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存(数据库)中找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行

作用:
降低后端负载
提高读写效率,降低响应时间

解释:当用户第一次查询数据库中的数据时,会访问数据库,因为这个时候没有缓存,当访问数据库后,读取的数据就存在了缓存中,下次用户再查询数据时从缓存中查询即可。从缓存中查询数据是比访问数据库的速度快的多的。同时当改变数据库中的数据后,也可同步改变缓存中相应的数据。
并且当很多用户同时访问数据库时,数据库很可能崩溃,因此我们可以把数据库中的数据移到缓存中,这样一部分用户在访问数据库时,可以直接从缓存中获取数据。
在这里插入图片描述

🚓缓存更新策略

  1. 内存淘汰
    内存淘汰策略不需要自己维护,它是利用Redis的内存淘汰机制,当内存不足的时候自动淘汰大部分数据,下次查询时再更新查询。
    优点:无维护成本
    缺点:一致性差
  2. 超时剔除
    给缓存数据添加TTL时间当缓存的数据到期后会自动删除缓存,下次查询时再更新缓存。
    维护成本低
    一致性一般
  3. 主动更新
    需要程序员自己编写业务逻辑,在修改数据库的同时,更新缓存
    优点:一致性好
    缺点:维护成本高

当需求为低一致性需求时:使用内存淘汰机制。
当需求为高一致性需求时:使用主动更新机制,并以超时剔除作为兜底方案。

在这里插入图片描述

🚓主动更新策略

一般来说,缓存有以下三种模式:

Cache Aside 更新模式 :由缓存的调用者,在更新数据库时同时更新缓存。
Read/Write Through 更新模式 :先更新缓存,缓存负责同步更新数据库
Write Behind Caching 更新模式: 先更新缓存,缓存定时异步更新数据库

🚕Cache Aside Pattern

在很多情况下,此更新模式都是很适合的,因此在这里详细讲解这种更新模式。
在操作缓存和数据库时是先操作缓存还是先操作数据库呢?
此时先给出答案:

先操作数据库,在操作缓存比较合适

第一种情况
在这里插入图片描述
刚开始缓存和数据库中的数据都是10

  1. 线程1删除缓存。此时缓存中无数据,数据库中的数据为10
  2. 线程2查询缓存,因为缓存中没有数据,所以无法命中缓存,只能从数据库中查询,查询数据为10
  3. 线程2将查询到的数据10写入到缓存中,此时数据库中数据为10,缓存中数据为10
  4. 线程1此时更新数据库中的数据,将值改为20。所以这就造成了数据库和缓存中的数据不一致。

在这里插入图片描述

第二种情况
在这里插入图片描述
刚开始数据库中的数据为10,假设缓存数据过期失效

  1. 线程1查询缓存,由于缓存失效,所以查询数据库。
  2. 此时线程2突然要更新数据库,将数据改为20。
  3. 此时线程2删除缓存,由于缓存中没有数据,因此删了个寂寞😂😂😂
  4. 这时线程1再把数据写入缓存,此时写入缓存的数据是10。这就造成了缓存和数据库中的数据不一样,缓存中的数据为10,数据库中的数据为20。

虽然第二种情况会造成缓存和数据库中的数据不一样,但是这种情况发生的概率是微乎其微的。
因为写入缓存的速度是要快于更新数据库操作的,所以线程1查询数据库后,几乎不会等线程2更新数据库完数据库后再写入缓存。并且这种情况还要在缓存失效的前提下才能发生,所以第二种在整体上胜出第一种
因此还是先操作数据库再操作缓存比较合适

在这里插入图片描述

🚕Read/Write Through Pattern

Read Through 模式就是在查询操作中更新缓存,也就是说,当缓存失效的时候,Cache Aside 模式是由调用方负责把数据加载入缓存,而 Read Through 则用缓存服务自己来加载
Write Through 模式和 Read Through 相仿,不过是在更新数据时发生。当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后由缓存自己更新数据库(这是一个同步操作)。

🚕Write Behind Caching Pattern

Write Behind Caching 更新模式就是在更新数据的时候,只更新缓存,不更新数据库,而我们的缓存会异步地批量更新数据库。这个设计的好处就是直接操作内存速度快。因为异步,Write Behind Caching 更新模式还可以合并对同一个数据的多次操作到数据库,所以性能的提高是相当可观的。
但其带来的问题是,数据不是强一致性的,而且可能会丢失。另外,Write Behind Caching 更新模式实现逻辑比较复杂,因为它需要确认有哪些数据是被更新了的,哪些数据需要刷到持久层上。只有在缓存需要失效的时候,才会把它真正持久起来。
在这里插入图片描述

🚗缓存穿透

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,所以不能从缓存上面取到客户端想要的数据,并且这些请求都会打到数据库上,导致数据库短时间内承受大量的请求而崩溃
而解决缓存穿透的方案通常有两种:
1.缓存空对象
从缓存上取不到数据,在数据库中也取不到,这时可以把key-value键值对写成key-null键值对,并且设置有效时间(设置短一些)。这样可以防止带有恶意的用户频繁地用一个值来攻击数据库。
在这里插入图片描述

优点:实现简单,便于维护
缺点:需要消耗额外的内存;
并且可能造成短期的不一致

2.布隆过滤器
过滤器,顾名思义,就是不让某些请求通过,不放行某些恶意的请求。
在缓存中,采用布隆过滤器,将可能存在的数据哈希到足够大的bitmap上,如果客户端请求的数据不存在,布隆过滤器会拒绝客户端的请求,如果存在则会放行请求,再去查询缓存,按步骤执行后面的操作
在这里插入图片描述
在这里插入图片描述

🚗缓存雪崩

缓存雪崩是指在同一时间段内大量的缓存key同时失效或者Redis服务器宕机,导致大量的请求到达数据库,给数据库带来巨大的压力而使得数据库崩掉。
缓存雪崩的解决方案有以下几种:
1.给不同的Key的TTL值添加随机值(如1-5分钟随机),防止同一时间段内大量数据发生过期的现象
2.不给缓存设置失效时间,让它永久有效
3.利用Redis集群提高服务的可用性。将热点的key放到不同的节点上。
4.可以考虑加锁(最多使用)或者队列的方式来保证不会有大量的线程对数据库一次性读写,从而避免了key失效时大量的并发请求落到存储系统上

🚗缓存击穿

缓存击穿问题也叫热点Key问题,是一个被高并发访问并且缓存创建业务较复杂的key突然失效了,缓存中没有数据但数据库中有数据,并发用户无数的请求访问读缓存不能读到数据,又同时去数据库里查询数据,这无数的请求会瞬间给数据库带来巨大的冲击导致数据库压力过大。

缓存击穿和缓存雪崩很相似,但不同的是,缓存击穿是指客户端并发查同一条数据,缓存雪崩是指不同的数据都过期了,很多数据都查不到而去数据库中查询。

解决方案:
1.加互斥锁
加互斥锁只允许一个线程重建缓存,其他线程等待上锁的线程重建缓存步骤执行完,释放锁后,其他线程再重新从缓存上获取数据

优点:
没有额外的内存消耗;
保证了一致性;
实现起来比较简单

缺点:
线程需要等待,性能受到影响;
还可能出现死锁的风险

2.逻辑过期
给每个value设置一个过期时间,当发现超过逻辑过期时间后,会使用单独的线程去更新缓存。
但从缓存层面上来看,确实没有设置过期时间,所以不会出现热点key过期后产生的问题,也就是“物理”不过期。

优点:
线程无须等待,性能较好
缺点:
不能保证一致性;
有额外的内存消耗;
实现起来比较复杂

在这里插入图片描述

🚙redis持久化

首先需要了解什么是持久化。持久化就是把内存中的数据写到磁盘中去,防止服务器宕机造成内存中的数据丢失
redis持久化的方式有两种,一种是RDB持久化,一种是AOF持久化。
在这里插入图片描述

🚙RDB持久化

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

Redis内部有触发RDB的机制,它的命令举例如下:
save命令
Reids save命令执行一个同步保存操作,将当前Redis实例的所有数据快照(snapshort)已RDB文件的方式保存到磁盘
bgsave命令
bgsave执行后,会立刻返回OK,Redis 会fork一个子进程,原来的redis主进程继续执行后续操作,新fork的子进程负责将数据保存到磁盘,然后退出

save 900 1 表示900秒内,如果有至少一个key被修改,则执行bgsave

如果是 save " ",表示禁用RDB

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件。
fork采用的是copy-on-write技术:
当主进程执行读操作时,访问共享内存;
当主进程执行写操作时,则会拷贝一份数据,执行写操作。
在这里插入图片描述

RDB方式bgsave的基本流程:
1.fork主进程得到一个子进程,共享内存空间
2.子进程读取内存数据并写入新的RDB文件
3.用新RDB文件替换旧的RDB文件。

在这里插入图片描述

RDB方式的优缺点

优点:
(1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备。
(2)RDB对redis对外提供读写服务的时候,影像非常小,因为redis 主进程只需要fork一个子进程出来,让子进程对磁盘io来进行rdb持久化
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。

缺点:
(1)如果redis要故障时要尽可能少的丢失数据,RDB没有AOF好,例如1:00进行的快照,在1:10又要进行快照的时候宕机了,这个时候就会丢失10分钟的数据。
(2)fork子进程、压缩、写出RDB文件都比较耗时。RDB每次fork出子进程来执行RDB快照生成文件时,如果文件特别大,可能会导致客户端提供服务暂停数毫秒或者几秒

在这里插入图片描述

🚙 AOF持久化

AOF全称为Append Only File(追加文件)。Redis处理的每一个写命令都会记录在AOF文件,可以看做是命令日志文件。当重启Redis时会重新将持久化的日志中文件恢复数据。
由于AOF记录的是命令,所以AOF文件比RDB文件大得多。并且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。

如:
set num Tom;
set name Jack;
set name Lucy;
最后记录的name是Lucy

也可以通过执行bgrewriteof命令,可以让AOF文件执行重写功能,用最少的命令达到相同的效果

如 mset Tom Jack Lucy;

当然AOF的命令记录的频率也可以通过redis.conf文件来配

  1. Always 同步刷盘,可靠性高,几乎不会丢失数据,就是会影响性能
  2. everysec 每秒刷盘,性能适中,最多丢失1秒的数据
  3. no 由操作系统控制,性能是最好的,但可靠性比较差,可能丢失大量数据

优点:

1.保存数据安全,AOF持久化可以配置appendfsync属性为always,每进行一次操作,命令就会被记到AOF文件中
2.如果在写文件时突然服务器宕机,可以用redis-check-aof工具解决一致性问题。
3.AOF 机制的 rewrite 模式。AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令。

缺点

1.AOF文件较大,并且恢复速度慢(因为恢复时需要执行一遍命令才能恢复)
2.数据集大的时候,比RDB启动效率低。

在这里插入图片描述

🚙RDB和AOF持久化的对比

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

持久化方式:
RDB定时对整个内存做快照;而AOF记录每一次执行的命令
数据完整性:
RDB不完整,两次备份之间会丢失数据;AOF相对完整,取决于刷盘策略;
文件大小:
RDB会有压缩,文件体积小;而AOF记录命令,文件体积很大
宕机恢复速度:RDB很快;而AOF慢,因为要执行一遍命令;
数据恢复优先级:
RDB低,因为数据完整性不如AOF,AOF高,因为数据完整性更高。
系统资源占用:
RDB占用高,大量CPU和内存消耗;而AOF占用低,主要是磁盘IO资源,但AOF重写时会占用大量CPU和内存资源
使用场景:
RDB在可以容忍几分钟的数据丢失,追求更快的启动速度时使用比较合适;
AOF主要在对数据安全性要求较高时比较常见。

在这里插入图片描述

文章到这里就结束了,**下一篇会介绍Redis其他的重点内容。**如Redis哨兵,Redis主从等面试中的重点内容。
如果文章中有需要改进的地方还请大佬指正🤞🤞🤞
再次感谢各位小伙伴儿的支持👏👏👏
在这里插入图片描述

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:cloudbbs@huaweicloud.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。