当前位置 : 主页 > 编程语言 > 其它开发 >

2022年-C#中高级开发工程师面试题【Redis篇】

来源:互联网 收集:自由互联 发布时间:2022-06-16
心之所向,勇往直前! 学习不能只靠面试题,又不能不背面试题 正文 1. Redis是单线程还是多线程? 单线程 + IO多路复用(一个线程监听多个套接字,触发事件,排入队列) 2.Redis为什么这

心之所向,勇往直前!
学习不能只靠面试题,又不能不背面试题

正文

   1. Redis是单线程还是多线程?

    单线程 + IO多路复用(一个线程监听多个套接字,触发事件,排入队列)

 

   2. Redis为什么这么快?

    a. 基于内存操作数据

    b. 单线程,避免了上下文创建的开销

       c. 多路IO复用

     d. Redis使用全局的Hash表实现Key的存储,检索时间复杂度为O(1)

       e. 高效的底层数据结构(简单动态字符串SDS,双向链表,压缩列表,哈希表,跳表和整数数组)

 

   3. Redis常见的数据类型有哪些?

    String、List、Hash、Set、ZSet(非重复有序集合)

 

   4. Redis和Memcache的区别? 

    a. Redis支持更多的数据类型

    b. Redis支持RDB和AOF两种模式的数据持久化

    c. Redis支持高可用的解决方案(主从、哨兵、Cluster)

 

   5. Redis的应用场景有哪些? 

    a. 缓存数据

    b. 热点数据(访问统计、排行榜、好友推荐)

    c. 分布式锁(setnx)

 

   6. Redis的能否持久化数据,具体用什么方式? 

    能,Redis有RDB和AOF两种持久化机制

    RDB(快照):某个时间点执行备份,会Fork一个子进程执行操作

    AOF(追加日志):每次写完数据后会把操作指令写入日志文件,会Fork一个子进程执行操作

 

   7. 能详细说说RDB模式吗?

     a. RDB模式下,Redis会将键值对数据写到dump.rdb文件中,以二进制的格式储存,默认使用RDB持久化

    b. 支持自动和手动两种模式,使用手动的save模式时会阻塞主线程,bgsave和自动模式会Fork一个子进程来对数据集进行备份,子进程和主进程是共享同一份数据,因此在主进程在复制时发生修改,会执行写时复制,创建副本进行修改

    c. 在要恢复的数据量较大的时候性能比AOF好

    d. 由于RDB不是秒级备份操作,出现宕机时会丢失数据

    

   8. 能详细说说AOF模式吗?

     a. AOF模式下,Redis会将每一次指令追加到缓冲区,然后写到文本文件中

    b. 有三种模式可以选择:always(总是)、everysec(每秒)、no(操作系统来决定什么时候保存保存)

    c. 比RDB可靠性高,但是在数据集比较大时恢复比较慢

 

   9. Redis的各数据类型操作命令

    参考资料

 

   10. Redis是怎样实现主从同步的?

    a. slave在宕机重启后发送sync命令

    b. master收到命令后执行bgsave,fork一个子进程生成RDB文件,如果此时主库产生了修改命令,则会将修改命令记录到缓冲区

    c. master将RDB文件以及缓冲区命令先后发送给slave

    d. 主从数据最终一致

 

   11. 如何避免Redis主从同步时从库会清空数据?

    尽量使用部分同步机制,避免全量同步

    a. 第一次链接无法避免全量同步,因此可以选择访问量少的时候进行

    b. offset偏移量记录超出时也会全量同步,可以配置增加复制缓冲区的大小(默认1M),增加命中率

 

   12. 说说Redis的重同步机制?

    a. master和slave各自记录一个偏移量值offset,和服务器ID

    b. master会把最近的写命令记录在缓冲区(1M),在slave重新连接时根据偏移量发送命令同步,如果offset不在缓冲区中,则会执行全量同步

    c. 当slave的服务器ID和master的ID不一致时,也会执行全量同步

 

   13. 你能举例说说Redis的几种数据类型的应用场景吗?

     string:缓存、计数器、分布式锁、分布式token

     hash:用户信息记录

     list:最新的热点数据,如新闻,通知

     set:好友关系、标签、点赞、抽奖

     zset:排行榜

     参考资料

 

   14. 什么是缓存穿透?

     缓存穿透是用户请求了redis以及数据库都没有的数据,频繁的无效请求对数据库造成压力

     a. 可以在接口层增加参数校验 + 登录授权校验(避免匿名攻击)

     b. 可以将数据缓存下来并设置一个较短的过期时间,避免短时间内被重复请求数据库

     c. 可以使用布隆过滤器(可以判断出值一定不存在)

 

   15. 什么是缓存击穿?

     缓存击穿时在某一个时间点内,热key失效导致大量请求打到数据库造成压力

     a. 可以设置热key永不过期

     b. 使用互斥锁,抢到锁的用户才可以去访问数据库,然后重新再将值写到缓存中

 

   16. 什么是缓存雪崩?  

     缓存雪崩是某一时间内,大量的key同时失效,导致请求打到数据库造成压力

     a. key的过期时间设置随机,避免短时间内大量key同时失效

     b. 使用互斥锁,抢到锁的用户才可以去访问数据库,然后重新再将值写到缓存中

     c. 设置双重缓存,缓存1过期后获取缓存2,缓存2的过期时间可相对设置长一些

     d. 使用定时任务定时刷新缓存

 

   17. 什么是缓存预热?

     在系统功能上线前,手动写入缓存,避免上线后用户直接访问到数据库

   

   18. 什么是布隆过滤器?

     布隆过滤器可以看做是一个二进制数组,本质是二进制向量和随机函数的映射,当key使用一个或多个hash算法得出对应的数组下标,标记为1,因此可以判断出某个key一定不存在。

     a. 布隆过滤器不可以删除元素(因为hash碰撞的原因,不同的key经过计算后可能得出相同的hash)

     b. 容错率越小,需要的储存空间越大

     c. 当插入的数量 > 容量时会触发扩容,默认为2倍

     d. 用用场景:黑名单、爬虫URL去重、缓存穿透、

 

   19. Redis的Key过期策略有哪些(Redis如何处理过期的Key)?

     Key过期后不会被立马删除,过期策略仅针对有设置过期时间的Key,设置了过期时间的Key会存放在一个独立的字典中

     a. 被动策略:在用户访问Key时,redis会检测一次过期时间,如果过期则删除key。(存在如果永远没有访问Key就会一直占用内存的问题)

     b. 主动策略:每10s随机选择20个设置了过期时间的Key,删除过期Key,如果过期的Key占了25%以上,则会继续重复执行该策略

 

   20. Redis的Key淘汰策略有哪些(Redis如何处理过期的Key)?   

     淘汰策略可以仅针对设置了过期时间的Key,也可以针对所有的Key

     a. lru算法:随机取样(默认5个)最久没有使用的Key进行淘汰。具体机制为:使用一个hash表(查询)和双向链表(插入、删除)来维护数据,最新的数据会在头部,最久的在尾部被删除

     b. lfu算法:随机取样(默认5个)最长时间没有使用的Key进行淘汰。具体机制为:维护两个双向链表记录访问频率、kv,找到相同频率的节点将kv写入节点的链表中,每次移除最尾部的Key

 

   21. 你参与的项目有应用过Redis的高可用方案吗?(主从同步)

     a. 一主多从,主写从读,降低服务器读压力

     b. 级联多从,每个slave也可以部署多个slave,这种方案可以避免master重启后runid变化导致所有主多从方案下所有slave同时全量同步造成服务器压力的问题

 

   22. 你是怎么解决主从同步延迟的(数据不一致)

     先确定是什么原因导致的延迟(网络原因、大量主从复制)

     a. 如果是非核心业务不追求及时性,可忽略

     b. 部分核心业务对数据时效有要求的,可选择读master,其他业务读slave

     c. 如果是网络原因就提升网络、大量全量复制就确定是不是复制缓冲区不够

  

   23. 你参与的项目有应用过Redis的高可用方案吗?(哨兵模式) 

     a. 哨兵是特殊的redis节点

     b. 哨兵每10s向master发送一次命令获取节点信息,记录slave节点

     c. 哨兵间通过Pub/Sub消费订阅模式使用特定的__sentinel__:hello通道向主从节点发送消息,因此可以保持通信以及交换信息

     d. 哨兵模式建议至少需要3个

     e. 参考资料

 

   24. 哨兵模式是如何进行故障检测的?

      a. 哨兵每10秒通过发送Ping命令检测主节点的健康状态,可配置down-after-miliseconds确定主管宕机的超时时间

     b. PING命令发送成功后,设置last_ping_time为当前时间。如果收到回复,设置last_pong_time为当前时间,确认节点正常运行

     c. 如果只有1台哨兵则为主观宕机会直接选举slave为master,存在多台哨兵时需要达成客观宕机(即多台哨兵均认为master宕机,哨兵数量可配置,超过半数以上的哨兵数量)才会选举slave成为主节点

     d. 哨兵选举后会发送slave of no one命令关闭slave复制功能,通知其他slave变更master节点,当旧的master重连后会自动变更为slave

 

   25. 哨兵模式在故障转移时是如何实现Leader选举的

     a. 当哨兵节点判断master宕机后,会把自身的纪元+1并发送命令Sentinel is-master-down-by-addr询问其他哨兵节点进行投票,最后对票数进行统计

     b. 当票数 > 哨兵节点/2+1 && 票数 > 法定票数时节点可被选举为Leader

     c. 选举失败时,将会重新进行选举

     d. 选举过程中,redis服务将不可用

 

   26. 哨兵模式在故障转移时是如何实现Master选举的?

      a. 由Leader执行故障转移,排除不符合条件的slave节点(优先级=0、5秒内未回复、主观宕机或与处于断线状态的从节点)

     b. 节点选择层次为:优先级最大 > 复制偏移量最大 > RunId最小

      c. 主节点选举完成后,哨兵Leader发送slaveof NO ONE指令将从节点升级为主节点,此时从节点会重置信息并开始执行持久化重写操作

      d. 哨兵Leader在过程中每秒询问从节点,当接收到升级成功信号后,开始遍历所有从节点更改对应的Master信息为新升级的Master

 

   27. 如何解决脑裂问题?

     脑裂是由于网络原因(哨兵和master可能不在同一个网络分区)导致哨兵无法感知master导致重新选举了master,此时原master仍然能保持写入,将会造成大量数据丢失

     a. 配置min-replicas-to-write 1:连接master的最少slave数量

     b. 配置min-replicas-max-lag 10:slave连接master最大延迟时间

     c. 根据以上配置,如果出现故障且不满足要求,master会拒绝写入从而降低数据丢失造成的损失

 

   27. 删除Key会阻塞线程吗?

      a. 短时间内操作删除大量Key会阻塞

     b. 删除大Key会阻塞,具体根据Key的Value大小决定影响程度

 

   28. 如何避免删除大Key导致的阻塞?

      a. 使用SCAN命令,分批获取数据删除

       Hash:hscan + hdel

       List:ltrim

       Set:sscan + srem

       ZSet:zscan + zsrem

     b. unlink命令

 

   29. 如何使用Redis实现分布式锁?

      a. set key value NX PX 10 :使用SetNx设置一个客户端特有值value(可以是客户端id或者uuid),10秒(一定时间)后自动过期,如果不存在该key则设置成功,否则失败

      b. 业务逻辑完成后,执行删除:

        get key:先获取key判断是否与当前客户端匹配

        del key:删除key

      c. 针对b的操作,使用lua脚本保证原子性

      d. 针对过期时间是预估的,有可能业务未执行完锁已被释放,可以运行备用线程检测锁的时间,即将过期时对锁进行续时

 

   30. 你是如何保证Redis和数据的一致性的?

       a. 延时双删

      b. 订阅binlog

 

 

结语

  本篇到此结束,如果有任何疑问或者指正,请发表在评论区。

上一篇:滴滴退市了...
下一篇:没有了
网友评论