金三银四面试题之Redis篇
1. 谈谈Redis的应用场景?
- Token令牌的生成;
- 短信验证码Code;
- 缓存查询数据;
- 网页计数器;
- 分布式锁;
- 延迟操作;
2. Redis为什么这么快?
纯内存操作;
单线程操作,避免了频繁的上下文切换;
采用了非阻塞 I/O 多路复用机制;
基于跳跃表进行数据的增删改,效率非常高;
3. Redis为什么能够抗高并发?
Redis底层采用NIO中的多路IO复用机制,能够非常好的支持高并发,从而保证线程安全问题;Redis单线程,也就是底层采用一个线程维护多个不同的客户端的IO操作。但是NIO在不同的操作系统上实现方式有所不同,在windows操作系统使用select实现轮训,时间复杂度是为o(n),而且还存在空轮训的情况,效率非常低,其次是默认对轮训的数据有一定限制,所以支持上万的TCP连接非常难。在Linux操作系统采用epoll实现事件驱动回调,不会存在空轮训的情况,只对活跃的socket连接实现主动回调,这样在性能上有大大的提升,时间复杂度为o(1)。
4. Redis中有哪些数据结构?
String(最大容量512MB)、List、Hash、Set、Sorted Set。
5. 全量同步和增量同步有什么区别?
全量同步:就是每天定时(避开高峰期)或者采用一个周期实现将数据拷贝到一个地方也就是RDB存储。
增量同步:比如采用对行为的操作实现对数据的同步,也就是AOF。
全量与增量的比较:增量同步比全量同步更加消耗服务器的内存,但是能够更加的保证数据的同步。
6. RDB与AOF实现持久化的区别?
Redis提供了两种持久化的机制,分别为RDB、AOF实现,RDB采用定时(全量)持久化机制,但是服务器因为某种原因宕机后可能数据会丢失,AOF是基于数据日志操作实现的持久化,所以AOF采用增量同步的方案。
7. 如何解决MySQL和Redis的数据一致性问题?
方式1:直接清除Redis的缓存,重新读取数据库即可;
方式2:使用mq异步订阅mysql的binlog文件,实现增量同步;
方式3:使用alibaba的canal;
8. Redis的内存淘汰策略有哪些?
noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
allkeys-lru:在主键空间中,优先移除最近未使用的key。(推荐)
volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
allkeys-random:在主键空间中,随机移除某个key。
volatile-random:在设置了过期时间的键空间中,随机移除某个key。
volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。
9. 谈谈Redis的事务操作?
开启事务,提交事务,取消事务(Redis中没有回滚事务)。
10. 谈谈Redis的主从复制?
单个Redis如果因为某种原因宕机的话,可能会导致Redis服务不可用,可以使用主从复制实现一主多从,主节点负责写的操作,从节点负责读的操作,主节点会定期将数据同步到从节点中,保证数据一致性的问题。该主从同步方式存在如果从节点非常多的话,会导致对主节点同步多个从节点压力非常大,可以采用树状类型解决该问题。
主从复制数据同步的过程
- Redis从节点向主节点建立socket连接
- Redis采用全量或者增量的形式将数据同步给从节点
11. Redis主从复制有什么缺点?
如果主节点存在了问题,整个Redis环境是不可以实现写的操作,需要人工更改配置变为主操作
如何解决该问题:使用哨兵机制可以帮助解决Redis集群主从选举策略。
12. 谈谈Redis的哨兵机制?
Redis的哨兵机制就是解决主从复制存在缺陷(选举问题),解决问题保证我们的Redis高可用,实现自动化故障发现与故障转移。
哨兵机制原理
- 哨兵机制每个10s时间只需要配置监听主节点就可以获取当前整个Redis集群的环境列表,采用info 命令形式。
- 哨兵不建议是单机的,最好每个Redis节点都需要配置哨兵监听。
- 哨兵集群原理是如何:多个哨兵都执行同一个主的master节点,订阅到相同都通道,有新的哨兵加入都会向通道中发送自己服务的信息,该通道的订阅者可以发现新哨兵的加入,随后相互建立长连接。
- Master的故障发现 单个哨兵会向主的master节点发送ping的命令,如果master节点没有及时的响应,哨兵会认为该master节点为“主观不可用状态”会发送给其他都哨兵确认该Master节点是否不可用,当前确认的哨兵节点数>=quorum(可配置),会实现重新选举。
13. 谈谈Redis Cluster集群?
传统Redis集群存在的问题:Redis哨兵集群模式,每个节点都保存全量同步数据,冗余的数据比较多;而在Redis Cluster模式中集群中采用分片集群模式,可以减少冗余数据,缺点就是构建该集群模式成本非常高。
Redis3.0开始官方推出了集群模式 RedisCluster,原理采用hash槽的概念,预先分配16384个卡槽,并且将该卡槽分配给具体服务的节点;通过key进行crc16(key)%16384 获取余数,余数就是对应的卡槽的位置,一个卡槽可以存放多个不同的key,从而将读或者写转发到该卡槽的服务的节点。 最大的优点:动态扩容、缩容。
14. 缓存穿透、缓存击穿、缓存雪崩有什么区别?
缓存穿透:缓存穿透是指使用不存在的key进行大量的高并发查询,导致缓存无法命中,每次请求都要都要穿透到后端数据库查询,使得数据库的压力非常大,甚至导致数据库服务压死;
解决方案:
- 接口层实现api限流、用户授权、id检查等 黑名单和白名单;
- 从缓存和数据库都取不到数据的话,一样将数据库空值放入缓存中,设置30s有效期避免使用同一个id对数据库攻击压力大;
- 使用布隆过滤器
缓存击穿:在高并发的情况下,当一个缓存key过期时,因为访问该key请求较大,多个请求同时发现缓存过期,因此对多个请求同时数据库查询、同时向Redis写入缓存数据,这样会导致数据库的压力非常大;
解决方案:
- 使用分布式锁
- 保证在分布式情况下,使用分布式锁保证对于每个key同时只允许只有一个线程查询到后端服务,其他没有获取到锁的权限,只需要等待即可;这种高并发压力直接转移到分布式锁上,对分布式锁的压力非常大。
- 使用本地锁,使用本地锁与分布式锁机制一样,只不过分布式锁适应于服务集群、本地锁仅限于单个服务使用。
- 软过过期,设置热点数据永不过期或者异步延长过期时间;
缓存雪崩:缓存雪崩指缓存服务器重启或者大量的缓存集中在某个时间段失效,突然给数据库产生了巨大的压力,甚至击垮数据库的情况。
解决思路:对不用的数据使用不同的失效时间,加上随机数
15. 什么是布隆过滤器?
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定。链表、树、散列表(又叫哈希表,Hash table)等等数据结构都是这种思路。但是随着集合中元素的增加,我们需要的存储空间越来越大。同时检索速度也越来越慢,上述三种结构的检索时间复杂度分别为:O(n), O(log n), O(n/k)。
布隆过滤器的原理是,当一个元素被加入集合时,通过K个Hash函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。
布隆过滤器最大的问题:就是可能会存在一个误判的问题,如果向误判概率越低,则二进制数组会越大,同时也会非常占用空间。(布隆过滤器加强版–布谷鸟过滤器)