美文网首页
Redis面试篇

Redis面试篇

作者: 小驴小驴 | 来源:发表于2021-11-12 15:54 被阅读0次

    Redis篇

    一、Redis单线程为什么快?

    1. 网络层面:

      在操作系统层面使用了操作系统提供的Epoll函数,并且在Epoll模型中也只是使用同一个线程去接受请求与处理请求,这有点类似于IO模型中的单Reactor单线程模型。

      也就是因为在取操作与处理是单线程的,那么对数据的操作自然也就不需要添加很多的锁来保护共享资源。因此操作自然没有线程上下文切换与加锁的耗时。

    2. 架构方面:

      1. 数据完全存储在内存中,不涉及到磁盘IO(当然了,这里先撇开数据持久化的问题)

      2. Redis内部的数据结构,如:sds(int、embstr、raw)、hashtable、ziplist、quicklist、skiplist等优秀的数据结构

      3. Redis很多数据类型提供了很多小的优化

        • hashtable它底层是dict的数据结构去实现的,它的扩容阈值就与普通的hash不一致,redis的dict它是扩容会更早,这样就可以减少dict结构中的链表结构的查询时间复杂度O(n)
        • 包括dict在扩容的时候,它是渐进性的rehash的过程,以减少单次rehash的耗时过久
        • 比如在ziplist与hashtable底层都记录了length长度,因此在调用scard、llen函数时,操作时间复杂度为O(1),而不需要全盘查询计数

    二、Redis 持久化

    Redis持久化主要有AOF与RDB两种方式

    1. RDB

      RDB更像是Redis备份的一种快照方式,RDB可以灵活的在配置文件中配置RDB的触发时机,当开始RDB时,Redis进程会fork出一个子进程,由子进程完成数据快照的持久化工作,当新RDB文件创建并写入完毕之后,会删除旧版的RDB文件,以新文件代替旧文件。

      优点:文件较小、恢复时间快,适合主从同步的异地备份,包括向主从模式的首次同步也主要是依赖RDB文件(之后同步则会依赖主机发送命令给从机)。

      缺点:

      • 可能会丢失一段时间的数据,如果配置不得当的话
      • 但是若配置的RDB触发时间过于紧凑,那么就会经常性的fock出子进程进行数据同步写入磁盘,是个非常大的消耗。而且数据集越大,fock子进程的的速度就会越慢,导致阻塞主线程,虽然AOF也需要fock出子进程,但是AOF可以控制fsync的调用频率,即控制了写磁盘的速率。
    2. AOF

      AOF不同于RDB,AOF会将每次操作的命令记下,然后以fync的频率将命令持久化至磁盘,AOF提供三种策略将命令持久化至磁盘:

      • 每秒fsync一次,这是效率与备份达到平衡的状态,最多丢失1s的数据(默认)
      • 从不sync,将数据交给了操作系统,由操作系统决定是否写入磁盘,容易丢数据
      • 每次新命令都会进行fsync至磁盘,速度最慢,但是最安全

      优点:AOF不太容易丢失数据,如果丢失数据可能也只是很短暂的时间,写磁盘以Append-Only的方式进行追加,这比随机写磁盘效率要高几倍不止。AOF命令更容易读懂。

      缺点:

      • AOF文件过大(Redis通过Rewrite方式去不断进行AOF文件重写)

    三、Redis过期机制

    一定要分清楚过期机制与内存淘汰机制的区别

    Redis过期机制有两种方式:主动模式、被动模式

    主动模式:在查询数据的时候判断当前key是否过期,若过期则进行删除

    被动模式:redis尽量以1s10次的频率去抽查20个key,判断是否过期,过期则删除,若当次过期的key超过了25%,则重复进行。

    算法:

    Redis采用绝对时间进行过期,而未采用相对时间进行过期,这一点原因也非常容易想到,推荐看一个算法:时间轮算法【https://zhuanlan.zhihu.com/p/356647675

    四、Redis在主从模式下如何过期

    因为Rediskey的过期并不是采用相对时间而是采用了绝对时间点进行过期,那么假设在主从redis所在的服务器时钟并不同步,那么就会导致主从的数据无法到达一致性,因此Redis的从机不会进行数据的删除,而是等待主机在删除之后,将DEL命令写入AOF并且发送给从机进行执行。

    五、Redis内存淘汰机制

    当Redis中的数据量达到了配置中的maxmemeory时(在64位操作系统中,该配置为0标识没有内存限制,在32位系统中,Redis默认为3GB大小),就会根据所配置的策略进行数据回收

    常见的策略有:

    • noeviction
    • allkeys-lru(最近最少使用,LRU算法是通过)
    • volatile-lru
    • allkeys-random
    • volatile-random
    • volatile-ttl
    • volatile-lfu(使用频率最少)
    • allkeys-lfu

    六、Redis事务

    相关关键字:
    watch、multi、exec、discard

    Redis事务只支持编译错误的事务回滚,并不支持运行时错误的事务回滚。

    编译错误:如命令拼写错误

    运行时错误:如操作命令与操作数据类型不相符合

    关于Redis为什么不支持回滚

    官网回答:不应该将开发中出现的问题留到生产环境,包括编译、运行时所执行的命令。

    个人理解:在MySQL中实现事务的回滚是通过undolog来进行事务回滚的,那么本身是一个用来做缓存,数据都存放在内存中的中间件速度势必会遭受到影响。

    七、Redis主从复制原理

    主从复制分为增量同步与全量同步,流程如下:

    每个Slave与Master都会有一个Replication id:offset这样的一个偏移量。当某个slave因为短暂的掉线重连之后,会发送psync并且携带自身的offset消息偏移量,而master也会记录offset的偏移量,并且在master的命令缓冲区中会保存起始偏移量,缓存区中保存着起始偏移量之后的所有命令,如果slave传递过来的offset在偏移量所包含的区域中,那么就会进行增量同步,master会将slave offset之后的命令发送给slave执行。

    但假设slave传递来的offset没有被master缓存区所包含,那么就会进行全量同步。在进行全量同步时,master主进程会fock出一个子进程进行RDB文件的生成,最终异步的将RDB文件发送给slave,而slave也有一项配置,在RDB加载进内存之前可否使用slave旧数据进行对外服务。

    当然了在全量同步的时候,master会缓冲之后的命令,用做当slave保存了rdb文件之后的增量更新。

    在新版本的Redis主从复制中,

    psync与sync的区别:

    sync是redis老版本的同步数据的协议,但是不能支持部分重同步,因此在新版中使用的都是psync协议。

    八、缓存雪崩、缓存穿透、缓存击穿

    • 缓存雪崩

      原因:缓存雪崩主要是因为大量的key在同一时刻过期而导致的大量请求打到数据库

      解决方案:

      • 打底解决肯定是要通过分布式锁来进行解决
      • 为每个key进行过期的时候随机增加一点时间,从而避免大量key同时过期
      • key永不过期但是这种方式是最不成熟的,这会导致redis内存压力过大
    • 缓存穿透

      原因:由于一些不合法的请求,比如请求一些数据库中根本不会存在(redis中自然也就不会存在)的数据。

      解决方案:

      • 增加接口校验
      • 对于一些非法的请求可以添加一些假数据缓存到redis

    相关文章

      网友评论

          本文标题:Redis面试篇

          本文链接:https://www.haomeiwen.com/subject/ltrozltx.html