Redis面试

Redis缓存

缓存一致性

选择Cache Aside Pattern模式,在更新数据库的同时更新缓存

设置过期时间TTL,相当于给缓存一致性加了一个兜底的方案,在正常更新缓存失败的情况下,可以利用过期清理的方案保证于数据库的一致性

数据库增删改--->redis只做删:

我们对数据库进行增删改的操作时,redis没必要同步的去做增删改,只需要做删除就行,可以减少对redis不必要的占用,也不影响整个效果。除非该数据是热点数据,查询频率高,才需要同步增删改,大多数的数据不需要。

删除redis和数据库增删改的顺序问题:

1.先操作缓存,再操作数据库--->并发安全问题:

例如线程1修改数据线程2查询数据。修改数据的线程1先来,删除redis数据,再去操作数据库,但当线程1还没来得及修改数据库时,来了查询数据的线程2,查到redis没数据(已被线程1删除),就去查询数据库查到旧的数据,将旧数据缓存到redis,于是线程1删除的数据白删了。然后线程1才修改完数据库的数据,会发现数据库和缓存的数据不一致。

2.先操作数据库,再删redis

也有可能导致并发安全问题,但是概率极低

缓存穿透

指客户端请求的数据在数据库中不存在,缓存无法生效,从而导致请求穿透缓存,直接打到数据库的问题(就是说,明知道数据库没有该数据,故该缓存也不可能有数据,则会直接打到数据库)

假如有大量的线程一直请求不存在的数据,就会直接打到数据库,给数据库带来巨大的压力,甚至数据库崩溃。

解决方案

1.缓存空对象

当请求一个不存在的数据,数据库中也没有,则以请求的这个参数为key(这里指的是将要查询的数据作为key而不是来查的这个“人”作为key),在redis中缓存一个空的值(可能是null或者标记),下次再来查询时,则会在redis中查到这个特殊的值,就不会让其请求数据库相当于给不存在的数据也建立了一个请求,避免大量不存在的请求打到数据库。

优点:简单方便

缺点:占用内存-->解决方法-->设置过期时间

2.布隆过滤

存在于redis和客户端请求之间

优点:内存占用小,没有多余的key 

缺点:实现复杂。存在误差,不存在则一定不存在但是不能说一定存在,误差概率很小

补充:缓存预热

在项目刚开始运行时,去大量的查询数据库,提前批量的写入缓存中,当后续用户访问时可以直接命中缓存而不用临时建立缓存。

缓存雪崩

是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量的请求到达数据库,带来巨大压力。

情况一大量的缓存key同时失效

解决方案:

在缓存预热的阶段,在不同的key的过期时间的基础上再加随机过期时间同时失效的概率降低

情况二Redis服务宕机

单点的Redis无法去避免,最佳方案是为其搭建集群,比如主从集群哨兵。哨兵可以监控主从集群的状态,当发现出现宕机时,可以重新选主,从而保证整个集群的高可用。即使这样也不能完全保证服务器不宕机,因此需要考虑宕机之后的解决方案

例如,当服务器宕机后,限制请求并发的量,减小数据库的压力。

其次,还可以进行降级策略,直接拒绝一部分请求,甚至可以对整个业务进行熔断阻止访问,缓存恢复之后再解除熔断。

给业务添加多级缓存,例如在浏览器上添加静态资源的缓存。

缓存击穿

也叫热点key问题,就是一个被高并发访问并且缓存重建业务比较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大冲击。

解决方案:

1.互斥锁

假设有一个线程查询时未命中,会想去进行缓存的重建(即查询数据库,查到的数据放入缓存的过程),但是为了避免无数的线程都去重建,要求对其加锁,只有获取锁成功的线程才能重建缓存数据,再释放锁。如果该线程没有释放锁,与此同时的其他线程无法获取锁也就无法重建缓存数据,需要休眠一会再重试。

特点:简单粗暴,但是如果重建的过程比较久,其他线程就需要等待,性能降低

2.监控数据

监控数据,实时调整:监控哪些数据是热门数据,实时的调整key的过期时长(将过期时长延长)。

Redis主从

主从同步原理

问题1:master是如何知道slave是第一次同步连接还是断开重连的

建立主从集群之前每个人都是master都有自己的replid。建立主从集群以后,主从的replid都变了变成了相同的replid。在第一次建立主从关系时,master会生成一个全新的replid,并且将该replid分享给每个slave。因此可以通过replid来进行判断是否是第一次来连接。

slave(此时还不是slave)尝试去成为slave,发出请求的同时还需要带上原本的replid,然后master根据其replid进行判断

replid不一致-->第一次来-->发送全部的数据

replid一致-->断开重连-->发送缺少的数据

问题2:如何发送全部数据

master执行bgsave(后台执行的命令,用于开启独立进程,把redis在内存中所有数据都持久化到硬盘中写到一个RDB文件里),生成RDB文件。也就是说RDB文件有master所有数据

此时,master只需要将该RDB文件发送给slave,slave将自己的数据清除把RDB文件加载到内存即可达到主从完全一致。

问题3:master如何知道slave缺失的是什么数据

offset相当于写入命令的量

将slave和master各自的offset做比较,看看缺失的哪部分命令,将命令发给slave即可实现增量同步

哨兵原理

思考:哨兵如何知道节点是否健康?哨兵应该选哪个为主?选主的角色转换是如何实现的?

1.哨兵如何知道节点是否健康?

心跳机制

2.哨兵应该选哪个为主?

3.选主的角色转换是如何实现的?

Redis内存回收

过期key处理

思考:Redis如何知道一个key是否过期?是不是TTL到期就立即删除?

1.Redis如何知道一个key是否过期?

dict和expires两个指针分别指向两个hash表。dict指向的表存放所有的键值对,expires指向的表里面的键是设置了过期时间的key值是key的到期时间

因此只需要拿expires指向表的key去查,就能拿到对应的到期时间,再将到期时间和当前时间进行对比就知道是否过期。

总结:在Redis中有两个hash表,一个记录的是原始的key-value,另外一个记录的是带有过期时间的key和它的到期时间,只需要拿它的key去查就知道是否过期。

2.是不是TTL到期就立即删除?

总结

内存淘汰策略

Redis数据持久化

redis之所以能够高速读写是因为它基于内存,但是也带来一个问题,在服务器宕机或者重启的情况下,内存里面的数据就会丢失。为了解决该问题,redis提供了持久化的技术来保证数据的持久性和可靠性

持久化方式:

1.RDB

  • 原理:RDB持久化是指在指定的时间间隔内内存中的数据集快照写入磁盘。实际操作过程是创建一个子进程(不是自己去做这件事,而是让子进程去做),先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

  • 节省空间:RDB文件是二进制的,通常比AOF文件更紧凑,因此可以节省磁盘空间。
  • 高性能:生成RDB快照时,Redis不会执行写入磁盘的操作,因此不会对性能产生很大影响。
  • 恢复速度快:RDB能够将数据集压缩存储在磁盘上,因此在恢复大数据集时比AOF更为迅速。
  • 数据备份简单:RDB文件非常适合用于数据备份,可以定时将RDB文件拷贝到其它存储介质上。

2.AOF

redis将自己执行的所有写入操作命令都记录下来,当redis重启之后,对所有写入命令进行回放以达到恢复数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值