ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Redis常见面试题

2022-02-05 12:34:59  阅读:133  来源: 互联网

标签:面试题 缓存 过期 Redis 常见 redis socket01 key 节点


一.Redis 支持的数据类型有哪些?

基本数据类型

  • String:存放的是k-v键值对。如:set k v;
    • 使用场景:常规计数,缓存等
  • List:有序,可重复。如:lpush mylist v1 v2 v3;
    • 使用场景:Redis的list是每个子元素都是String类型的双向链表, 可以通过push和pop操作从列表的头部或者尾部 添加或者删除元素,这样List即可以作为栈和队列。
  • Set:无序,不可重复。如:sadd myset v1 v2 v3;
    • 使用场景:交集:一些共同关注,共同喜好,二度好友(共同好友)都可以使用。
  • Hash:在 Redis中哈希类型是指值本身是一种键值对结构,如 value={{field1,value1},……{fieldN,valueN}}。如:hmset myhash k1 v1 k2 v2 k3 v3
    • 使用场景:存储对象,存储一些复杂的k-v信息
  • zSet:有序,不可重复。虽然set是无序的,但是zSet就是为了让set有序。如:zadd myset 1 v1 2 v2 3 v3 
    • 使用场景:排行榜。   

三大特殊的数据类型

  • Geospatial:这个功能可以将用户给定的地理位置信息(经纬度)储存起来, 并对这些信息进行操作(计算两地的距离,范围等)。
    • 使用场景:地图,附件的人...
  • HyperLogLog:可以存储不重复的数据,并且占用很小的内存。虽然set也可以,但是占用空间大。如:pfadd myhyper 1 3 5 6 7 4 
    • 每个 HyperLogLog 只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。
    • 使用场景:适合浏览量一类的业务。
  • BitMap位图:存放是/否的操作,如果把true/false放在数据库中,占用空间大。BitMap采用二进制01110010101001...进行存储。如:setbit mybit 7 1;//比如第7天是否打卡
    • 使用场景:存放登录/未登录,打卡/未打卡,活跃/不活跃这样的数据
二.RDB和AOF机制

它们都是redis进行持久化的方式。

  • RDB:(redis database)
    • 在指定的时间间隔内将内存中的数据集快照写入磁盘(dump.rdb)。 恢复时将快照文件直接读到内存里,它会fork一个子进程来进行持久化,不会影响主进程的性能。
    • 优点:效率高,因为fork一个子进程进行IO操作,不影响主进程。
    • 缺点:安全性不高 
      • 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改
      • Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑。
    • 同步机制:redis会自动进行持久化
      •  save 60 10  //在redis.config中手动设置:60秒内修改10次
      • 执行flushall 命令的时候
      • 退出redis.server的时候
  • AOF (append only file)
    • 以日志的形式来记录每一个"写/删除"的命令。但是只追加文件不可以修改文件,redis启动的时候会重新加载appendonly.aof,重新执行所有的命令,用来恢复数据
    • 优点:安全性高
      • 数据安全性高,发生宕机后,不会破坏已经存在的内容
      • 内部采用rewrite模式,定期对AOF文件进行重写,以达到压缩的目的
    • 缺点:效率不高
      • AOF文件比RDB文件要大很多,并且每次启动重新执行写的指令,效率就低。
    • 同步机制: 不同步;每秒同步一次;每次写入时同步
  • 并存:
    • redis支持同时开启两种方式,默认优先载入aof文件来恢复数据,因为数据完整性高。 rdb作为备份。  
三.过期键删除策略

redis的过期策略是指:key过期了,redis如何在内部把它删除。

  • 惰性过期:只有在使用key的时候,才判断key是否过期,过期清除。不使用的时候就算是过期了,也一直保存在内存中。
    • 可以节省CPU资源,但对内存不友好。
  • 定时过期:不是redis的策略,指给每一个key都配上定时器。到时间了自动清除key。
    • 可以节省内存,但是对CPU不友好,因为得维护每一个定时器。
  • 定期过期:每隔一段时间,会扫描一定数量的expires字典中的key,删除过期的key。
    • 是对以上两者的一个折中方案,平衡内存和CPU的最高性能。

redis默认同时使用了惰性过期和定期过期两种策略

四.线程模型

线程模型:

  • 多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO多路复用程序会监听多个 socket,会将产生事件的 socket 放入队列中排队,事件分派器每次从队列中取出一个 socket,根据 socket 的事件类型交给对应的事件处理器进行处理。

 一次客户端与redis完整通信过程

  • 建立连接
    1. 首先,redis 服务端进程初始化的时候,会将 server socket 的 AE_READABLE 事件与连接应答处理器关联。
    2. 客户端 socket01 向 redis 进程的 server socket 请求建立连接,此时 server socket 会产生一个 AE_READABLE 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该 socket 压入队列中。
    3. 文件事件分派器从队列中获取 socket,交给连接应答处理器。
    4. 连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 AE_READABLE 事件与命令请求处理器关联。
  •  执行一个set请求
    1. 客户端发送了一个 set key value 请求,此时 redis 中的 socket01 会产生 AE_READABLE 事件,IO 多路复用程序将 socket01 压入队列,
    2. 此时事件分派器从队列中获取到 socket01 产生的 AE_READABLE 事件,由于前面 socket01 的 AE_READABLE 事件已经与命令请求处理器关联,
    3. 因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 socket01 的 key value 并在自己内存中完成 key value 的设置。
    4. 操作完成后,它会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。
    5. 如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 AE_WRITABLE 事件,同样压入队列中,
    6. 事件分派器找到相关联的命令回复处理器,由命令回复处理器对 socket01 输入本次操作的一个结果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。

 

redis单线程快的原因?

  • 纯内存操作。
  • 核心是基于非阻塞的 IO 多路复用机制。
  • C 语言实现,语言更接近操作系统,执行速度相对会更快。
  • 单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。
  • 总结:就像对于一个请求来说,如果业务逻辑复杂,使用多线程效率就高,用户也可以及时得到回应.。但是请求中如果业务逻辑简单(就像redis,就仅仅是对key进行读写操作),但是请求量大的话, 单线程效率就要高。
 五.缓存雪崩,缓存击穿,缓存穿透的区别?
  • 缓存雪崩:指缓存(redis)同一时间,大面积的失效。所有请求都到了数据库,相当于redis整个不能用了。
    • 比如:redis重启的时候,开始redis中没有任何数据;或者缓存数据同一时间失效; 这时所有请求需要访问数据库,那一刻相当于缓存雪崩,整个redis不能用了。 同时访问大量数据
    • 解决方案:
      • 设置随机过期时间,避免统一时间点同时过期
      • 缓存预热:比如对于重启的时候,提前把一些数据放到缓存中, 让redis一启动就加载了热点数据
      • 互斥锁:加锁,访问数据库的请求只能有一条。
  • 缓存击穿:是指访问缓存中没有,但是数据库中有的数据。与缓存雪崩不同的是,它是同时访问同一条热点数据。而不是大量的数据。同时访问同一数据
    • 解决方案:
      • 设置热点数据永不过期,但是也需要维护(定期删除)
      • 互斥锁
  • 缓存穿透:同时大量访问缓存中和数据库中都不存在的数据,一般就是被恶意攻击。
    • 解决方案:
      • 接口层面添加校验,比如查询的id不符合数据库中的范围,或者用户权限不够。直接拦截
      • 缓存空对象,把该数据的key存在缓存中,值设为null。这样可以防止反复用同一个id暴力攻击
      • 使用布隆过滤器,这是redis自带的。它将所有可能的数据存放在足够大的bitmap中,一个一定不存在的数据就会被这个bitmap拦截掉,避免数据库的查询压力      
六.redis事务

既然是事务,就需要保证ACID。

  • 原子性(A):事务中单条命令才保证原子性,整个事务并不保证原子性。因为事务不支持回滚
  • 一致性(C):Redis舍弃了回滚的设计,基本上也就舍弃对数据一致性的有效保证。
  • 隔离性(I):redis单线程天然的隔离性
  • 持久性(D):采用RDB和AOF两种方式实现持久化

实现:Redis事务的三个阶段

  • 开始事务 (multi)
  • 命令入队 (命令),采用FIFO (先进先出)
  • 执行事务 (exec)

注意:事务中如果出现命令语法错误(相当于编译时错误),所有命令就不会执行。 事务中如果出现逻辑错误(相当于运行时错误),错误语句不执行,其他命令正常执行。

事务中用到的其他命令:

  • watch:相当于加了一个乐观锁,更新时判断。
  • unwatch:释放乐观锁。但是每次事务结束(无论成功与否)会自动释放乐观锁,不需要手动执行该命令
  • discard:事务中途放弃事务,命令都不执行   
七.redis集群

redis的集群方案?  四种模式各有优缺点,可根据实际场景进行选择。

  • 主从模式
    • 指将一台Redis服务器的数据,复制到其他的Redis服务器。 数据的复制是单向的,只能由主节点到从节点。
    • Master以写为主,可读;Slave以读为主,不能写。 实现读写分离。
    • 缺点:不能自动故障转移。
  • 哨兵模式
    • 基于主从复制模式,哨兵本身就是redis一个实例,用来监视其他的实例。主节点宕机,采用选老大的方式处理故障,实现自动故障转移。
    • 缺点:不能在线扩容。
  • redis Sharding模式(客户端分片)
    • 客户端通过哈希算法将数据的key进行散列,映射到不同的redis节点中。Jedies就支持 Sharding功能。解决了在线扩容问题
    • 缺点:大量的处理放在客户端,导致数据大。
  • redis cluster模式(服务端分片)
    • 是redis Sharding模式的升级版,将集群分为不同的卡槽(0~16383),每个节点有一定数量的卡槽。 每一节点既是主节点,也是从节点,相互依赖。解决了扩容问题
    • 缺点:对于像批量操作,事务操作等的支持性不够好

 

哨兵模式选老大的算法?

  • 哨兵通过发送命令,等待Redis服务器响应。如果主机宕机,哨兵1先检查到这个信息, 但是不会马上进行选举。这个过程称为主观下线。
  • 当其他的哨兵也检查到主机宕机,那么哨兵之间会进行投票选取新的老大,选取成功之后,会通过发布订阅模式,让各个从节点切换主机,这个过程成为客观下线。
  • 注意:如果已经客观下线,就算主节点已经恢复,只能作为新的主节点的从节点

 

Cluster如何实现故障转移

  • Redis 集群节点采用 Gossip 协议来广播自己的状态以及自己对整个集群认知的改变。比如一个节点发现某个节点失联了 (PFail),它会将这条信息向整个集群广播,其它节点也就可以收到这点失联信息。
  • 如果一个节点收到了某个节点失联的数量 已经达到了集群的大多数,就可以标记该节点为确定下线状态 (Fail),然后向整个集群广播,强迫其它节点也接收该节点已经下线的事实,并立即对该失联节点进行主从切换。

 

主从复制的原理?

  • 全量复制
    • 主节点进行RDB或者AOF,然后将持久化文件通过网络发送给从节点,从节点开始启动的时候进行读取,此时从节点是同步的,不能进行数据访问(因为也没有数据),需要消耗IO资源。
  • 增量复制
    • 每次主节点更新数据,会发送给从节点,从节点根据偏移量进行增量复制。
    • 注意:因为IO非常消耗资源,每次增量进行持久化的时候,会把更新的数据放在主节点的一个叫做 复制积压缓存区的地方,发送给从节点。这样就不至于每次增量复制进行io操作。

上图相关问题:

  • runid:每一个redis实例都有一个id,区别身份。比如主节点发送给从节点就会把自己的id发送过来。主节点宕机了,这个不能使用增量复制。    
  • 什么时候会由增量复制变为全量复制?  
    • runid不匹配(比如主节点宕机了,不是之前那个了),或者复制积压缓存区放不下。 

 

 

寄语:你所浪费的今天是昨天死去的人奢望的明天;你所厌恶的现在,是未来的你回不到的曾经   ---哈佛大学校训

 线程模型参照文章:https://www.cnblogs.com/mrmirror/p/13587311.html

标签:面试题,缓存,过期,Redis,常见,redis,socket01,key,节点
来源: https://www.cnblogs.com/monkey-xuan/p/15864052.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有