• Redis面试题


    String类型的底层数据结构、存储方式、扩容方式?

      底层数据结构:SDS,简单动态字符串(Simple Dynamic String),它是一个带有长度信息的字节数组

      存储方式:embstr和raw,当字符串长度比较短的时候使用embstr,长度超过44字节时使用raw方式存储

      扩容方式:长度小于1MB时,扩容使用加倍策略,内存超过1MB时,每次多分配1MB的空间(字符串最大长度为512MB)

    Redis的持久化机制?有几种方式?优缺点?

     redis 的持久化机制,会将数据写入内存的同时,异步的慢慢的将数据写入磁盘文件里,进行持久化。

     有两种方式:RDB 持久化机制,是对 redis 中的数据执行周期性的持久化。需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行 RDB 持久化。

                           AOF 机制对每条写入命令作为日志,以 append-only 的模式写入一个日志文件中,在 redis 重启的时候,可以通过回放 AOF 日志中的写入指令来重新构建整个数据集。

     RDB的优缺点:

                         优点:对外依然提供读写服务,影响非常小,可以让redis保持高性能。相对于AOF重启和恢复redis进程速度更快。

                         缺点:会造成数据部分丢失(一般同步机制5分钟一次,在这五分钟内宕机会造成数据丢失),数据文件很大,会造成服务延迟。

     AOF的优缺点:

                        优点:可以保证数据不丢失,性能高,不影响客户端读写,可以对误操作进行紧急修复。

                        缺点:支持的写 QPS 会比 RDB 支持的写 QPS 低,因为要实时进行数据同步

     解决方案:

                        用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。

                    

    为什么 redis 单线程模型也能效率这么高?

     1.Redis是基于内存的,内存的读写速度非常快;

     2.Redis是单线程的,省去了很多上下文切换线程的时间;

     3.Redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。

    4.数据结构也帮了不少忙,Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。

    对IO模型的了解,了解哪些IO模型?

      IO的过程主要包含了两个阶段:

           第一阶段,等待数据准备好,

           第二阶段,将数据从内核空间拷贝到应用程序地址空间

      第一个阶段阻塞即为阻塞IO,不阻塞直接返回则为非阻塞IO

      第二个阶段阻塞则为同步IO,不阻塞则为异步IO

      多路复用IO其实是通过轮询机制来负责多个socket

    既然Redis是单线程的,那么它如何利用多核呢?

    可以通过开启多个Redis实例来利用多核

    redis 过期策略?

      定期删除+惰性删除。

      定期删除:redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。

      惰性删除:在获取某个key时,会检测这个key是否设置了过期时间,如果已过期则进行删除,不返回数据。

    redis 内存淘汰机制?

      noeviction: 内存不足时写入数据,直接报错

      allkeys-lru:内存不足时写入数据,移除最近最少使用的 key(最常用)

      allkeys-random:内存不足时写入数据,随机删除某个key

      volatile-lru:内存不足时写入数据,在设置过期时间的键空间中,移除最近最少使用的key

      volatile-random:内存不足时写入数据,在设置过期时间的键空间中,随机删除某个key

      volatile-ttl:内存不足时写入数据,在设置过期时间的键空间中,移除过期时间短的key

    如何保证缓存与数据库的双写一致性?

      读请求和写请求串行化,串到一个内存队列里去。串行化可以保证一定不会出现不一致的情况,但是它也会导致系统的吞吐量大幅度降低,用比正常情况下多几倍的机器去支撑线上的一个请求

    缓存雪崩?缓存穿透?

       缓存雪崩:

            在某一个时间点,缓存数据集中失效,所有请求直接打到了数据上,导致服务崩溃。解决方案:设置缓存失效的时间点尽量避免重叠,热门数据时间长些,冷门数据时间短些

       缓存穿透:

            先查询缓存,缓存为null去查询数据库,数据库也为null,不写入缓存,导致请求会一直请求数据库。

            解决方案:数据库也为null时,也写入为“”的缓存数据,过期时间尽量短些。互斥锁:在第一个请求去查询数据时加上互斥锁,其余请求都被阻塞,直到锁被释放

        Redis挂掉了怎么办?

          设置本地缓存+限流(hystrix)。redis持久化,重启后自动从磁盘上加载数据,快速恢复缓存数据。

    redis 集群模式的工作原理?

    自动将数据进行分片,每个 master 上放一部分数据提供内置的高可用支持。在 redis cluster 架构下,每个 redis 要放开两个端口号,比如一个是 6379,另外一个就是 加1w 的端口号,比如 16379。
    16379 端口号是用来进行节点间通信的,也就是 cluster bus 的东西,cluster bus 的通信,用来进行故障检测、配置更新、故障转移授权。

    cluster bus 用了另外一种二进制的协议,gossip 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。

    分布式寻址都有哪些算法?了解一致性 hash 算法吗?

      hash 算法(大量缓存重建):

        根据key,首先计算 hash 值,然后对节点数取模,打在不同的 master 节点上。一旦某一个 master 节点宕机,所有请求过来,都会基于最新的剩余 master 节点数去取模,尝试去取数据。这会导致大部分的请求过来,全部无法拿到有效的缓存,导致大量的流量涌入数据库

      一致性 hash 算法(自动缓存迁移)+ 虚拟节点(自动负载均衡):    

       一致性 hash 算法将整个 hash 值空间组织成一个虚拟的圆环,整个空间按顺时针方向组织,下一步将各个 master 节点(使用服务器的 ip 或主机名)进行 hash。这样就能确定每个节点在其哈希环上的位置。

       来了一个 key,首先计算 hash 值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,遇到的第一个 master 节点就是 key 所在位置。

       在一致性哈希算法中,如果一个节点挂了,受影响的数据仅仅是此节点到环空间前一个节点(沿着逆时针方向行走遇到的第一个节点)之间的数据,其它不受影响。增加一个节点也同理。

  • 相关阅读:
    tab切换与表格展示
    ajax
    api
    slice() 方法
    iframe跳转
    快排序
    【问题排查】cpu占用过高排查
    LOJ6013 负载平衡 [最小费用最大流]
    随机序列 [思维题, 组合数]
    P1777 帮助 [状压dp]
  • 原文地址:https://www.cnblogs.com/BounceGuo/p/13950302.html
Copyright © 2020-2023  润新知