Redis面试详解

面试后端开发的职位,相信大家经常被问到有关redis问题。Redis作为缓存系统的代表很有必要弄熟搞懂,无论是在工作当中还是求职面试过程中都是大有裨益的,本文将详细介绍一些redis的一些典型问题,并给出了一些参考解答。
  由于作者水平有限,可能会有存在一些问题,欢迎大家不吝批评指教。文中参考了网友的一些资料,在这里先他们表示感谢。本文全文约4000字,阅读完大概需要10分钟时间。

常见问题

Redis性能为什么高?
单线程的redis如何利用多核cpu机器?
Redis的缓存淘汰策略?
Redis如何持久化数据?
Redis有哪几种数据结构?
Redis集群有哪几种形式?
有海量key和value都比较小的数据,在redis中如何存储才更省内存?
如何保证redis和DB中的数据一致性?
如何解决缓存穿透和缓存雪崩?
如何用redis实现分布式锁?

问题参考列表

Redis性能为什么高?

Redis是key-value存储的nosql数据库,具有以下一些性质,使其性能优异。

  1. 完全基于内存操作,绝大多数操作都在内存中完成,非常高效。
  2. 内部采用多路I/O复用模型,非阻塞式IO。Redis会根据系统情况优先调用高效的IO复用模型,例如linux的epoll多路IO函数;
  3. 数据结构和数据操作简单,redis中的数据结构是专门进行设计的;
  4. 处理请求模块采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  5. 关于底层模型为了更有效的通讯,redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

单线程的redis如何利用多核cpu机器?

  Redis的数据读取和处理性能非常强大,对于一般服务器配置,cpu都不会是性能瓶颈。Redis的性能瓶颈主要集中在内存和网络方面。举例来说,运行在一台普通的Linux机器上至少能处理50万并发请求。所以使用的redis命令多为O(N)、O(log(N))时间复杂度,那么基本上不会出现cpu瓶颈的情况。
  但是如果你确实需要充分使用多核cpu的能力,那么需要在单台服务器上运行多个redis实例(主从部署/集群化部署),并将每个redis实例和cpu内核进行绑定来实现充分利用多核CPU。

Redis的缓存淘汰策略?

Redis缓存淘汰策略与Redis键的过期删除策略并不完全相同,前者是在Redis内存使用超过一定值的时候(一般这个值可以配置)使用的淘汰策略;而后者是通过定期删除+惰性删除两者结合的方式进行内存淘汰的。
有六种缓存淘汰策略:

  1. volatile-lru:从已设置过期时间的数据中挑选最近最少使用的数据淘汰;
  2. volatile-ttl:从已设置过期时间的数据中挑选将要过期的数据淘汰;
  3. volatile-random:从已设置过期时间的数据中任意选择数据淘汰;
  4. allkeys-lru:从数据集中挑选最近最少使用的数据淘汰;
  5. allkeys-random:从数据集中任意选择数据淘汰;
  6. no-enviction(驱逐):禁止驱逐数据

注意这里的6种机制,volatile和allkeys都会对已设置过期时间的数据集淘汰数据。allkeys会从全部数据集淘汰数据,后面的lru、ttl以及random是三种不同的淘汰策略,再加上一种no-enviction永不回收的策略。

Redis如何持久化数据?

Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命令之后将命令记录下来。两种持久化方式可以单独使用,但是通常会将两者结合使用。
1、RDB方式
RDB方式的持久化是通过快照的方式完成的。当符合某种规则时,会将内存中的数据全量生成一份副本存储到硬盘上,这个过程称作”快照”。举例来说,根据配置规则进行自动快照流程:

  • 用户执行SAVE, BGSAVE命令;
  • 执行FLUSHALL命令;
  • 执行复制(replication)。

2、AOF方式
在使用Redis存储非临时数据时,一般都需要打开AOF持久化来降低进程终止导致的数据丢失,AOF可以将Redis执行的每一条写命令追加到硬盘文件中,这一过程显然会降低Redis的性能,但是大部分情况下这个影响是可以接受的,另外,使用较快的硬盘能提高AOF的性能。

Redis有哪几种数据结构?

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

Redis集群有哪几种形式?

redis有三种集群方式:主从复制,哨兵模式和集群。 详细内容参见:Redis集群管理方式

有海量key和value都比较小的数据,在redis中如何存储才更省内存?

可以考虑通过大幅减少key的数量来降低内存的消耗。
实现:在客户端通过分组将海量的key根据一定的策略映射到一组hash对象中,由于value较小,故hash类型的对象会使用占用内存较小的ziplist编码。
例如:如存在100万个键,可以映射到1000个hash中,每个hash保存1000个元素。

如何保证redis和DB中的数据一致性?

大多情况下,缓存策略是:读缓存,读取不到就读数据库然后同步到缓存中。
问题出现场景
在并发访问中,不论是先写库,再删除缓存;还是先删缓存,再写库,都有可能出现数据不一致的情况
1、在并发中是无法保证读写的先后顺序的,如果删掉了缓存还没来得及写库,另一个线程就过来读取发现缓存为空就去数据库读取并写入缓存,此时缓存中为脏数据。
2、如果先写了库,再删除缓存前,写库的线程宕机了,没有删除掉缓存,则也会出现数据不一致情况。
3、如果是redis集群,或者主从模式,写主读从,由于redis复制存在一定的时间延迟,也有可能导致数据不一致。
双删 + 超时
在写库前后都进行redis.del(key)操作,并且设定合理的超时时间。这样最差的情况是在超时时间内存在不一致,当然这种情况极其少见,可能的原因就是服务宕机。此种情况可以满足绝大多数需求。
当然这种策略要考虑redis和数据库主从同步的耗时,所以在第二次删除前最好休眠一定时间,比如500毫秒,这样毫无疑问又增加了写请求的耗时。

如何解决缓存穿透和缓存雪崩?

缓存雪崩:是指缓存同一时间大面积的失效,瞬间请求全落到数据库上,造成数据库短时间内承受大量请求而崩掉。
解决方案:缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
一般并发量不是特别多的时候,使用最多的解决方案是加锁排队。给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。

缓存穿透: 是指缓存和数据库中都没有的数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。

解决方案

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  • 采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap拦截掉,从而避免了对底层存储系统的查询压力
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值