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 所在位置。

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

原文地址:https://www.cnblogs.com/BounceGuo/p/13950302.html