Redis面试复习笔记(一)

一、谈谈你对redis的理解

redis是一个基于key-value存储结构的nosql开源数据库,它提供了String、Map、Set、ZSet、List等多种数据类型,根据这些数据类型,可以覆盖应用开发里面的大部分业务场景,比如说top10问题、好友关注列表、热点话题等等。由于redis本身是基于内存的一个数据库,并且在数据结构上做了大量的优化,所以IO的性能会比较好,在实际开发里面,我们会把它用在应用和数据库之间的一个分布式缓存中间件,并且它又是一个非关系数据库,它不存在表之间的关联、查询的一些问题,所以它可以很好的提升应用程序的数据IO效率。对于企业级的开发来说,它还提供了主从复制+哨兵,以及集群的方式去实现高可用,在redis集群里面通过hash槽的方式去实现了数据的分片,进一步提升了整个系统的性能和扩展性。

二、缓存击穿的原因和解决方法

原因:热点key过期、不存在的key被恶意高频地访问

解决办法:

1、热点KEY不设置过期时间,或者每一次访问的时候,都刷新过期时间;

2、空的数据也放到缓存里面;

3、key失效时请求数据库之前尝试去获取一个分布式锁,获取到锁的请求才访问数据库,获取到数据后再刷新key;

4、高频访问的key可以使用多级缓存,降低击穿造成的影响;

5、使用布隆过滤器,保存有效的key,访问具体key的时候,先访问布隆过滤器,如果在布隆过滤器中找不到,则说明数据库中也找不到。

三、缓存雪崩的原因和解决方法

原因:缓存中间件服务器宕机、大量key在同一时间过期

解决方法:

1、不设置过期时间;

2、设置失效时间时,添加一个随机时间;

四、redis集群的方式

1、主从集群

不提供容错和恢复功能,一旦master节点挂了,不会自动去选举出新的master,所以会导致无法写入的问题。

所以在高可用的结构里面,会加上一些哨兵节点,去实时的检测master节点的情况,一旦master节点发生了故障,就会从slave节点中选举出一个节点作为master。

加入哨兵也只是解决了故障恢复的问题,但是在线扩容的问题还是无法得到解决。

特点:一主多从

优点:读写分离,分担读的压力

缺点:无法在线扩容,读写压力受限于单机服务器的资源分配

2、redis cluster

这种集群方式相对于1中的主从复制+哨兵来说,解决了在线扩容问题

cluster实现了redis的分布式存储,和主从架构的其中一个不同点是,在cluster里面,每一个节点都存储不一样的数据。

cluster通过哈希槽去控制节点的访问,哈希槽中的每一个数字可以表示一个节点,范围为0-16384,在实际应用中,一般用一个哈希槽的范围去表示一个节点,节点里面可以通过主从这样的一个架构去实现故障恢复,当节点中的master宕机,会自动从slave节点中选出master。

特点:多主多从

缺点:节点里面的slave只作为冷备的一个用途,它只有在master宕机之后,才会工作

优点:实现了在线扩容,可以通过增加服务器去提升整个集群的读写性能

五、持久化机制

1、RDB

生成快照可以通过手动和自动去触发,手动是执行save或者bgsave命令,注意save会阻塞,导致服务中的其他命令无法执行。

自动触发可以通过配置redis.conf来实现自动执行bgsave,主从复制的时候也会自动触发。

优点:因为是二进制压缩文件,数据恢复的时候是顺序写入,速度快

缺点:因为是每隔一段时间触发RDB文件生成,所以数据的安全性比较差

2、AOF

redis服务执行命令的时候,会把这条命令写入到一个缓冲区里面,然后再写入到磁盘中的AOF文件中,而从缓冲区写入到磁盘文件这个操作是根据磁盘具体的刷盘策略来决定的。

由于aof是指令追加的方式存储到磁盘中的,会导致文件比较大,出现明显的IO问题,针对这种情况redis提供aof重写的方法,就是会把相同的指令进行压缩。

有三种刷盘策略可选:

第一种:同步回写,就是每一次命令操作刷一次盘

第二种:每秒回写,就是每一秒刷一次盘

第三种:由操作系统来决定什么时候刷盘

优点:可以实现实时的数据持久化,数据安全性比较高

缺点:数据恢复的时候要一条一条指令去执行,这个时候是随机写入,所以速度会比较慢

六、线程安全问题

需要根据两个方面去考虑,服务端和客户端。

服务端:因为在redis里面,执行指令的操作都是在主线程里面进行的,所以不存在线程安全的问题。有些人会说redis6.0提供了多线程模型,所以会有线程安全问题,其实是不对的,因为redis6.0提供的多线程模型是针对网络IO的一个模型,跟执行指令这一块是没有关系的。

客户端:在客户端层面中,由于存在多个客户端同时对一个key进行多个指令的操作,在这个情况中无法保证这一系列操作的原子性,因为在这个角度存在资源竞争的问题。

解决办法是客户端尽量只使用redis提供的原子指令,多个客户端访问同一个key的时候进行加锁,多个指令使用lua脚本去进行批量操作,从而实现批量操作的原子性。

全部评论
插眼
点赞
送花
回复
分享
发布于 2023-06-11 19:24 广东

相关推荐

点赞 19 评论
分享
牛客网
牛客企业服务