Redis常见面试题(附答案)

Redis

redis是一个基于内存的key-value数据库,主要可以用于数据库存储数据,数据持久化,缓存,集群。

Redis4.0之前是单线程,所以没有线程安全问题;

Redis4.0之后提供了多线程,仅针对于后台一些功能【主从复制、持久化.......】;

Redis6.0之后提供了多线程,仅针对于网络传输

Redis的多线程默认是关闭的,除非达到瓶颈,否则不用开

1.Redis的五种数据类型及应用场景

值的五种类型:

String:key,value

Hash:key;key1,value1;key2,value2...

list:key,list 有序

set:key,list 无序,不重复

zset:key,score,list 。 Set是无序的集合,Zset是有序的集合。

应用场景:

  • String --- 验证码、分布式session、计数器incr(文章阅读数、点赞数,将值 + 1)、缓存热点数据

  • hash --- 购物车

  • list --- 队列

  • set --- 微信朋友圈

  • zset --- 排行榜

2.Redis持久化机制

redis中的数据全部保存在内存中,如果突然宕机,数据就会全部丢失.为了防止这种事情发生,我们需要一种机制保证在宕机发生之后,我们重启服务,内存中的数据还可以恢复,这就是redis的持久化机制. 对应产生的数据文件为dump.rdb

  redis提供了三种持久化机制分别为RDB(Redis DataBase)方式,AOF(Append Only File)方式和混合模式.

持久化机制:

1.RDB(默认持久化模式):

会根据配置的规则进行定时快照备份优点

快照数据以二进制存储、文件小、恢复速度快

缺点

耗费时间,耗费性能,会丢失一定的数据,不可控

原理

Redis 会在某一时刻触发并将内存中所有的数据以二进制的方式保存在一个 dump.rdb 文件里,这也是 Redis 默认的持久化方式 。

持久化策略:

redis持久化需要条件触发:可以修改conf文件中配置save的参数 “ save <seconds><changes>” 如果我配置成了 save 60 10000 ,那就是代表如果在 60s 内执行了 10000 条修改命令,就会触发RDB持久化 .

手动触发:客户端执行save命令

besave命令: Redis 是单线程的,因此 save 命令在做持久化的时候时候会阻塞其他命令的执行,属于同步执行 。bgsave 则会从主线程中另外 fork 出一个子线程进行持久化操作,从而不会阻塞其他命令的执行,属于异步执行

上面讲的自动触发持久化也是通过 bgsave 的方式来进行的

2.AOF(默认关闭):

AOF持久化就是Redis在持久化数据的时候会把修改数据的命令通过追加的方式保存到 aof 文件中,在宕机恢复的时候通过执行 aof 文件中的命令来恢复数据以日志的形式记录key发送变化的指令;

优点

数据以命令的形式存储,数据不容易丢失。文件会重写,去除无用指令,优化数据最终得到的结果即可。

缺点

AOF文件可能会被篡改,文件、恢复速度

持久化策略:

appendfsync always: 每次有新命令追加到 AOF 文件时就执行一次 fsync,数据持久化非常慢,也非常安全

appendfsync everysec: 每秒 fsync 一次,足够快,并且在故障时也只会丢失 1 秒钟的数据,这个是redis默认的持久化策略

appendfsync no: 从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择

如果在持久化的时候要想要在持久化的速度和数据安全之间来权衡的话,可以选择第二种

RDB+AOF

AOF + aof文件压缩时以RDB去存储(二进制存储

不持久化

持久化:把数据保存在磁盘上

数据恢复:先恢复AOF,再补充RDB

 

3.混合模式(RDB+AOF 推荐使用)

3.Redis淘汰策略

Redis数据存储在内存,如果内存满了会触发淘汰策略

淘汰策略

  • volatile-lru: 在内存不足时,Redis会在设置过了生存时间**的key**中干掉一个最近最少使用的key.key1:10m 只用1次 key2:10m只用了2次(建议使用这种)

  • allkeys-lru:在内存不足时,Redis会在全部的key中干掉一个最近最少使用的key。

  • volatile-lfu: 在内存不足时,Redis会在设置过了生存时间的key中于掉一个最少频次使用的key。使用10个key,key1用了2次 key2 用了1次

  • allkeys-lfu:在内存不足时,Redis会在全部的key中干掉一个最少频次使用的key

  • volatile-random: 在内存不足时,Redis会在设置过了生存时间的key中随机干掉一个。

  • allkeys-random:在内存不是时,Redis会在全部的key中随机干掉一个。

  • volatile-ttl:在内存不是时,Redis会在设置过了生存时间的Key中干掉一个剩余生存时间最少的key。

  • noeviction:在内存不足时,Reids对写操作进行报错,对读操作可以执行

4.Redis 过期键的删除策略

  • 定时删除:在设置键的过期时间的同时,创建一个定时器 timer。让定时器在键的过期时间来临时,立即执行对键的删除操作。

  • 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。

  • 定期删除:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。

5.Redis的高可用性

主从模式:

从节点设置了主节点后,slave通过master节点建立socket连接,每隔1秒执行一次。连接成功后从节点会创建一个专门处理复制工作的事件处理器,用于命令传播以及接收RDB文件等。

职责:主节点负责写,从节点负责读

数据同步:

  • 全量复制

  • 增量辅助:通过offset 来定位需要复制后数据的位置

哨兵模式:

职责:

为了提升主从架构的可用性,用来监控主从架构是否可用

选举:

哨兵监控主节点宕机,通知其他哨兵,确认主节点宕机了,通知从节点选举

谁的数据多,谁当主节点;如果一样多,谁的数据新,谁当主节点

集群模式(cluster):

主节点负责写,从节点只负责数据的同步,会根据key进行hash运行,得到对应的槽位,把数据放进去

6.分布式锁

传统锁:

  • Synchronized 是 Jvm 中的关键字,没办法手动释放锁

  • Lock 是 Java 类库中的api,可以手动释放锁

 

分布式锁:

 

分布式锁的实际应用 --- 热点数据重建问题:

为什么要加锁?

热点数据因为其高访问量的缘故,为了提升性能,应该尽量减少对数据库的访问,不必每一次都直接查询数据库,可以使用redis作为缓存机制。当redis中没有热点数据时就访问数据库,若redis中存在热点数据,则直接从redis中获取即可。但存在特殊情况,如果在访问数据库之后,将数据存入redis之前,这时另一个进程抢走了cpu的执行权,此时redis中任然没有数据。那么此进程又将直接对数据库进行访问,这时就应该就整个进程加上一个锁。

 

为什么要加分布式锁?为什么不能用传统锁?

传统锁,synchronized锁只能作用于JVM之中,如果是集群部署,传统锁就失效了,这个时候就需要使用分式锁。

 

分布式锁使用实例

其中加入uuid,解决释放锁的问题,保证线程只释放自己线程上的锁。

7.Redis使用问题

 

1、缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对用的value,就应该去后端系统查找(比如DB数据库)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

解决:

对查询结果为空的情况进行缓存,缓存时间设置短一点,或者该key对应的数据insert之后清理缓存。

对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该Bitmap过滤。比如:布隆过滤器

2、击穿

某一个热点数据的key突然过期,造成大量请求直达数据库

解决:

分布式锁、热点数据永不过期、限流

3、缓存雪崩

当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来很大的压力,导致系统崩溃。

解决:随机过期时间、热点数据永不过期

8.缓存与数据库数据一致性

  1. 先更新数据库,再删除缓存,虽然会有短暂的不一致情况,但最终会一直的,最终会保证数据的一致性

  2. 加锁,把更新数据库,再删除缓存的操作当成一个原子性操作,给这个操作加锁,性能较差

  3. 延迟双删

  4. 基于mysql binlog日志进行异步更新缓存 --- canal

9.Redis的读写是单线程的,为什么那么快?

  1. 单线程,没有线程切换开销

  2. 纯内存操作

  3. IO多路复用技术【NIO】,NIO是面向缓冲的非阻塞IO,多路复用是指同时使用不阻塞的方式处理多个客户端的请求。其中多路是指不同的客户请求,复用则指redis单线程

10.Redis做异步队列

使用List结构作为队列, rpush 生产消息,lpop 消费消息 。 pub/sub 主题订阅者模式,可以实现1:N 的消息队列。

11.Redis做延迟队列

使用 sortedset,拿时间戳作为score,消息内容作为 key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询进行处理。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、什么是 Redis? 2、Redis 相比 memcached 有哪些优势? 3、Redis 支持哪几种数据类型? 4、Redis 主要消耗什么物理资源? 5、Redis 的全称是什么? 6、Redis 有哪几种数据淘汰策略? 7、Redis 官方为什么不提供 Windows 版本? 8、一个字符串类型的值能存储最大容量是多少? 9、为什么 Redis 需要把所有数据放到内存中? 10、Redis 集群方案应该怎么做?都有哪些方案? 11、Redis 集群方案什么情况下会导致整个集群不可用? 12、MySQL 里有 2000w 数据,Redis 中只存 20w 的数据, 如何保证 Redis 中的数据都是热点数据? 13、Redis 有哪些适合的场景? 14、Redis 支持的 Java 客户端都有哪些?官方推荐用哪个? 15、RedisRedisson 有什么关系? 16、Jedis 与 Redisson 对比有什么优缺点? 17、Redis 如何设置密码及验证密码? 18、说说 Redis 哈希槽的概念? 19、Redis 集群的主从复制模型是怎样的? 20、Redis 集群会有写操作丢失吗?为什么? 21、Redis 集群之间是如何复制的? 22、Redis 集群最大节点个数是多少? 23、Redis 集群如何选择数据库? 24、怎么测试 Redis 的连通性? 25、Redis 中的管道有什么用? 26、怎么理解 Redis 事务? 27、Redis 事务相关的命令有哪几个? 28、Redis key 的过期时间和永久有效分别怎么设置? 29、Redis 如何做内存优化? 30、Redis 回收进程如何工作的? 31、Redis 回收使用的是什么算法? 32、Redis 如何做大量数据插入? 33、为什么要做 Redis 分区? 34、你知道有哪些 Redis 分区实现方案? 35、Redis 分区有什么缺点? 36、Redis 持久化数据和缓存怎么做扩容? 37、分布式 Redis 是前期做还是后期规模上来了再做好?为 什么? 38、Twemproxy 是什么? 39、支持一致性哈希的客户端有哪些? 40、Redis 与其他 key-value 存储有什么不同? 41、Redis 的内存占用情况怎么样? 42、都有哪些办法可以降低 Redis 的内存使用情况呢? 43、查看 Redis 使用情况及状态信息用什么命令? 44、Redis 的内存用完了会发生什么? 45、Redis 是单线程的,如何提高多核 CPU 的利用率? 46、一个 Redis 实例最多能存放多少的 keys?List、Set、 Sorted Set 他们最多能存放多少元素? 47、Redis 常见性能问和解决方案? 48、Redis 提供了哪几种持久化方式? 49、如何选择合适的持久化方式? 50、修改配置不重启 Redis 会实时生效吗?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值