Redis 本质上是一个 Key-Value 类型的内存数据库,由于它有丰富的数据结构等特点,导致了使用它的速度,远远的超过了 Memcached。于是乎,现在面试问 Memcached 的很少,问 Redis 的则非常的多。今天抽个时间给大家整理了一些常见的,高频率的 Redis 面试题。希望能够对所有读者有所帮助!
1、Redis 是什么?它的优缺点有哪些?
Redis 是一个 key-value 存储系统。和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和 hash(哈希类型)。
这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,Redis 支持各种不同方式的排序。与 Memcached 一样,为了保证效率,数据都是缓存在内存中。区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了 Master-Slave(主从)同步。
Redis 是一个高性能的 key-value 数据库。 Redis 的出现,很大程度补偿了 Memcached 这类 key/value 存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-Value DB。
Redis 的出色之处不仅仅是性能,Redis 最大的魅力是支持保存多种数据结构,此外单个 value 能存非常多的数据,不像 memcached 只能保存 1MB 的数据,因此 Redis 可以用来实现很多有用的功能。
比方说用他的 List 来做 FIFO 双向链表,实现一个轻量级的高性 能消息队列服务,用他的 Set 可以做高性能的 tag 系统等等。
另外 Redis 也可以对存入的 Key-Value 设置 expire 时间,因此也可以被当作一 个功能加强版的 Memcached 来用。 Redis 的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此 Redis 适合的场景主要局限在较小数据量的高性能操作和运算上。
Redis 支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得 Redis 可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
2、Redis 相比 memcached 有哪些优势?
Memcached 所有的值均是简单的字符串,Redis 作为其替代者,支持更为丰富的数据类型;Redis 的速度比 Memcached 要快;Redis 可以持久化其数据,其他的有点在上面的第一题中也有提及,我就不在重复写了。
3、Redis 支持的数据结构有哪些?
字符串 String、字典 Hash、列表 List、集合 Set、有序集合 SortedSet。剩下的如:HyperLogLog、Geo、Pub/Sub、Redis Module,BloomFilter,RedisSearch,Redis-ML 也都可以讲一讲。
4、Redis 的全称是什么?
Remote Dictionary Server。
5、说说 Redis 分布式锁的使用过程是怎样的?
先拿 setnx 来争抢锁,抢到之后,再用 expire 给锁加一个过期时间防止锁忘记了释放。但是这个过程有一个致命的问题,如果在 setnx 之后执行 expire 之前进程意外 crash 或者要重启维护了。那这个锁就永远得不到释放了。所以,应该同时把 setnx 和 expire 合成一条指令来使用。
6、说说 Redis 的几种数据淘汰策略?
- noeviction:禁止淘汰数据。
- allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
- volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
- allkeys-random: 回收随机的键使得新添加的数据有空间存放。
- volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
- volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
7、Redis 官方为什么不提供 Windows 版本?
因为目前 Linux 版本已经相当稳定,而且用户量很大,开发 windows 版本,反而会带来兼容性等问题。
8、如何找出以某个固定的已知的前缀开头的 key?比如,10 亿个里面找出 10w 个。
使用 keys 指令可以扫出指定模式的 key 列表。但是在线上,这个命令一般会被禁止了。因为它是一个阻塞命令。
所以,推荐使用 scan 指令,scan 指令可以无阻塞的提取出指定模式的 key 列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用 keys 指令长。
9、一个字符串类型的值能存储最大容量是多少?
512M
10、如果有大量的 key 需要设置同一时间过期,一般需要注意什么?
如果大量的 Key 过期时间设置的过于集中,到过期的那个时间点,Redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。
11、Redis 集群方案应该怎么做?都有哪些方案?
codis 是开源的,目前用的最多的集群方案,基本和 twemproxy 一致的效果,但它支持在节点数量改变情况下,旧节点数据可恢复到新 hash 节点。
redis cluster 3.0 自带的集群,特点在于他的分布式算法不是一致性 hash,而是 hash 槽的概念,以及自身支持节点设置从节点。
在业务代码层实现,起几个毫无关联的 redis 实例,在代码层,对 key 进行 hash 计算,然后去对应的 redis 实例操作数据。 这种方式对 hash 层代码要求比较高,考虑部分包括,节点失效后的替代算法方案,数据震荡后的自动脚本恢复,实例的监控等等。
12、bgsave 做镜像全量持久化的原理是什么?
fork 和 cow。fork 是指 redis 通过创建子进程来进行 bgsave 操作,cow 指的是 copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
13、Pipeline 有什么好处,为什么要用 pipeline?
可以将多次 IO 往返的时间缩减为一次,前提是 pipeline 执行的指令之间没有因果相关性。使用 redis-benchmark 进行压测的时候可以发现影响 redis 的 QPS 峰值的一个重要因素是 pipeline 批次指令的数目。
14、Redis 的同步机制了解么?
Redis 可以使用主从同步,从从同步。第一次同步时,主节点做一次 bgsave,并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制节点,复制节点接受完成后将 rdb 镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
15、是否使用过 Redis 集群,集群的原理是什么?
Redis Sentinal 着眼于高可用,在 master 宕机时会自动将 slave 提升为 master,继续提供服务。
Redis Cluster 着眼于扩展性,在单个 redis 内存不足时,使用 Cluster 进行分片存储。
16、Jedis 与 Redisson 对比有什么优缺点?
Jedis 是 Redis 的 Java 实现的客户端,其 API 提供了比较全面的 Redis 命令的支持;
Redisson 实现了分布式和可扩展的 Java 数据结构,和 Jedis 相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等 Redis 特性。Redisson 的宗旨是促进使用者对 Redis 的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。
17、说说 Redis 哈希槽的概念?
Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
18、Redis 集群会有写操作丢失吗?
Redis 并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。
19、Redis 集群如何选择数据库?
Redis 集群目前无法做数据库选择,默认在 0 数据库。
20、怎么理解 Redis 事务?
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
通常使用 MULTI、EXEC、DISCARD、WATCH 这几个命令操作事务。
21、什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?
缓存穿透:一般的缓存系统,都是按照 key 去缓存查询,如果不存在对应的 value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的 key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
避免方法:
- 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。
- 对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。
缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。
避免方法:
- 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。
- 做二级缓存,A1 为原始缓存,A2 为拷贝缓存,A1 失效时,可以访问 A2,A1 缓存失效时间设置为短期,A2 设置为长期。
- 不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀
以上,先总结了一些高频的 Redis 面试题。如果你还需要更多的面试题,请加我微信好友:xttblog。
: » 高频率的Redis面试题分享
原创文章,作者:端木书台,如若转载,请注明出处:https://blog.ytso.com/252135.html