博主制作不易,感谢宝子们支持,有问题可以私我哦!
(一)redis开篇
(二)缓存穿透(恶意攻击)
缓存穿透:查询一个不存在的数据,mysql查询不到数据也不会直接写入缓存,就会导致每次请求都查询数据库
缓存空数据
解决方案一:缓存空数据,查询返回的数据为空,然后把这个空结果进行缓存
优点:简单
缺点:消耗内存,可能会发生不一致的问题
解决方案二:布隆过滤器
优点:内存占用较少
缺点:实现复杂,存在误判
布隆过滤器
bitmap(位图):相当于是一个以(bit)位为单位的数组.数组中每个单元只能存储二进制数0或1
布隆过滤器的作用:布隆过滤器可以检索一个元素是否在一个集合中
下面为误判的情况
缓存穿透面试题总结
(三)缓存击穿
缓存击穿:给某一个key设置了过期时间,当key过期的时候,恰好这个时间点对这个key有大量的并发请求过来,这些并发请求可能会瞬间把DB压垮
解决方案一:互斥锁(强一致,性能差)
解决方案二:逻辑过期(不需要等待锁)(高可用,性能优)
缓存击穿面试题总结
(四)缓存雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力
解决方案
(1)给不同的Key的TTL(过期时间)添加随机值
(2)利用Redis集群提高服务的可用性(服务宕机)(哨兵模式,集群模式)
(3)给缓存业务添加降级限流策略(服务宕机)(ngxin或者spring cloud gateway)(降级可以作为系统的保底策略,适用于穿透,击穿,雪崩)
(4)给业务添加多级缓存(Guava或者Caffeine)
缓存雪崩面试题总结
(五)双写一致
双鞋一致性:当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致
读操作:缓存命中,直接返回;缓存未命中查询数据库,写入缓存,设定超时时间
写操作:延迟双删
问题来了:我们是先删除缓存还是先删除数据库呢(都会出现脏数据的情况)
问题来了:为什么要删除两次缓存呢(降低脏数据的情况)
问题来了:为什么要要是双删呢(极大的控制了脏数据的风险)
双写一致的解决方案
读写锁方案(保证强一致性但是性能不高)(Redisson)
写入缓存的数据一定是读多写少,我们可以加锁
共享锁:读锁readLock,加锁之后,其他线程可以共享读操作
排它锁:独占锁writeLock,加锁之后,阻塞其他线程读写操作
异步通知方案:保证数据的最终一致性(延时一致)
基于Canal的异步通知方案(延时一致)
对于业务代码几乎是零侵入
数据发生变化是护记录到BINLOG日志文件中,利用canal中间件,那不行修改业务代码,伪装为mysql的一个从结点,canal通过读取binlog数据更新缓存
双写一致面试题总结
(六)持久化
RDB持久化
RDB也被叫做Redis数据快照,简单来说就是把内存中的所有数据都记录到磁盘中,当Redis实例故障重启后,从磁盘读取快照文件,恢复数据
Redis内部有触发RDB的机制,可以再redis.conf文件中找到格式
RDB执行原理
bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据.完成fork后读取内存数据并写入RDB文件.fork采用的是copy-on-write技术:
当主进程执行2读操作时,访问共享内存;
当主进程执行写操作时,则会拷贝一份数据,执行写操作.
AOF执行原理
AOF追加文件,Redis处理的每一个命令都会记录在AOF文件中,可以看做是命令日志文件
AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF
AOF的命令记录的频率也可以通过redis.conf文件来配置
因为AOF是记录命令,AOF文件会比RDB文件大得多,而且AOF会纪录对同一个key的多次写操作,但是值有最后一次的写操作才有意义,通过执行bgrewriteaof命令可以让AOF文件执行重写功能,,以最少的命令达到相同效果
Redis也会在触发阈值是自动去重写AOF文件,阈值也可以在redis.conf中配置
RDB与AOF对比
RDB和AOF都有各自的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用
RDB | AOF | |
---|---|---|
持久化方式 | 定时对整个内存做快照 | 纪录每一次的执行命令 |
数据完整性 | 不完整,两次备份之间会丢失 | 相对完整,取决于刷盘策略 |
文件大小 | 会有压缩,文件体积小 | 记录命令,文件体积很大 |
宕机恢复速度 | 很快 | 满 |
数据恢复优先级 | 低,因为数据完整性不如AOF | 高,因为数据完整性更高 |
系统占用资源 | 高,大量cpu和内存消耗 | 低,只要是磁盘io资源,但AOF重写时会占用大量cpu和内存资源 |
使用场景 | 可以容忍分钟的数据丢失,追求更快的启动速度 | 对数据安全性要求较高(常见) |
持久化面试题总结
(七)数据过期策略
Redis对数据设置数据的有效时间,数据过期以后,就需要将数据从内存中删除,可以按照不同的规则进行删除,这种删除规则被称之为数据的过期策略
惰性删除策略
惰性删除:设置该key过期事件后,我们不去管他,当需要该key时,我们在检查是否过期,如果过期,及删掉他,繁殖返回该key
优点:对CPU友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查
缺点:对内存不友好,如果一个key已经过期,但是一致没有使用,那么该key就会一直存在内存中,内存永远不会释放
定期删除策略
定期删除:每隔一段时间,我们就对一些key进行检查,删除里面过期的key(重一定数量的数据库中取出一定数量的随机key进行检查,并删除其中过期的key)
定期清理有两种模式:
(1)slow模式是定时任务,执行频率默认10hz,每次不超过25ms,已通过修改配置文件redis.conf的hz选项来调整这个次数
(2)FAST模式执行频率不固定,但两次间隔不低于2ms,每次耗时不超过1ms
优点:可以通过限制删除操作执行的时长和频率来减少删除操作对CPU的影响,另外定期删除也能有效释放过期键占用的内存
缺点:难以确定删除操作执行的时长和频率
Redis的过期删除策略:惰性删除+定期删除两种策略进行配合使用
过期策略面试题总结
(八)数据淘汰策略
数据淘汰策略:当Redis中的内存不够时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则就被称之为内存的淘汰策略
Redis支持8中不同的淘汰策略
(1)noeviction:不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略
(2)volatile-ttl:对设置了TTL的key,比较key的剩余TTL值,TTL越小约越先被淘汰
(3)allkeys-random:对全体key,随机进行淘汰
(4)volatile-random:对设置了TTL的key,随机进行淘汰
(5)allkeys-lru:对全体key,基于LRU算法进行淘汰(最近最少使用)
(6)volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰(最近最少使用)
(7)allkeys-lfu:对全体key,基于LFU算法进行淘汰(最少频率使用)
(8)volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰(最少频率使用)
数据淘汰策略--使用建议
(1)优先使用allkeys-lru策略,充分利用LRU算法优势,把最近最常访问的数据留在缓存中,如果业务有明显的冷热数据区分,建议使用
(2)如果业务中数据访问频率差别不大,没有明显冷热数据区分,建议使用allkeys-random,随机选择淘汰
(3)如果业务中有置顶的需求,可以使用volatile-lru策略,同时置顶数据不设置过期时间,这些数据就一直不被删除,会淘汰其他设置过期时间的数据
(4)如果业务中有短时高频访问的数据,可以使用allkeys-lfu或volatile-lfu策略
数据淘汰策略面试题总结
由于篇幅过长 本片分两篇博客发布,感谢宝子们!!!
标签:知识点,缓存,AOF,过期,Redis,就够,内存,key,数据 From: https://blog.csdn.net/weixin_70367240/article/details/141141466