Redis常见面试题

Redis中有哪些数据结构?分别有哪些典型的应用场景?

  1. 字符串:可以用来做最简单的数据,可以缓存简单的字符串,也可以缓存son格式的字符串,Redis分布式锁(setnx)的实现利用了这种数据结构,还可以实现计数器(setex)、session共享、分布式ID。
  2. hash表:可以用来存储一些key-value对,更适合用来存储对象。
  3. 列表:Redis的列表通过命令的组合,既可以当作栈,也可以当作队列来使用,用来缓存一些消息流数据(如微信公众号、微博等)。
  4. 集合:和列表类似,也可以存储多个元素,但是不能重复,可以用来求多个集合的并、交、差集。
  5. 有序集合:有序集合可以设置顺序,通过分数来实现,可以用来做排行榜功能。

Redis分布式锁底层怎么实现的?

  1. 首先要用到setnx来保证,如果key不存在才能获取到锁(返回1),如果key存在,则获取不到锁(返回0)。
setnx lock uuid
  1. 然后还有用到lua脚本,用来保证redis操作的原子性。
-- lua删除锁
-- keys和args都是集合类型参数,分别是key和uuid
-- 如果对应的value等于传入的uuid
if redis.call('get',keys[1]) == args[1]
   then
   -- 执行删除操作
      return redis.call('del',keys[1])
   else
   -- 不成功,返回0
      return 0
end
  1. 同时可以设置监听器来监听锁是否到期,到期可以进行续约。
  2. 还可能会出现某个redis节点挂掉的情况,可以采用红锁来同时向N/2+1个节点申请锁,都申请到才证明获取锁成功,这样就算其中某个节点挂掉了,锁也不能被其他客户端获取到。
  • 红锁(redLock)是redis官方提出的一种分布式锁的算法。

Redis过期键的删除策略

Redis是key-value型数据结构,我们可以设置Redis中缓存的key的过期时间。有两种处理方式,惰性过期和定期过期。

  • 惰性过期:只有访问一个key时,才判断这个key是否过期,过期则清除。该策略可以最大化节省CPU资源,缺点是比较浪费内存。极端情况下可能会出现大量过期的key没有被再次访问,浪费大量内存。
  • 定期过期:每隔一定时间,会扫描一定数量的expires字典中的key,并清除其中已过期的key。(expires字典会保存所有设置了过期时间的key的过期时间数据)
    Redis中同时使用了惰性过期和定时过期两种策略。

什么是RDB和AOF?(简述Redis的持久化机制)

两者都是Redis提供的持久化策略。因为redis是内存数据库,它将自己的数据存储在内存中,一旦redis服务器进程停止,redis服务器中的数据就会丢失。使用持久化机制将内存中的数据保存到磁盘中,来避免数据的丢失。

  • RDB:Redis DataBase,将某个时间点上redis中的数据保存到一个RDB文件中,该文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时redis中的数据。

    手动触发:

    • redis提供了两个命令来创建RDB文件。一个是save,save命令会阻塞Redis服务器进程,直到RDB文件创建完成为止,期间服务器不能处理任何命令请求。
    • 另一个是bgsave,bgsave命令会fork一个子进程,由子进程负责创建RDB文件,服务器进程可以继续处理命令请求。底层采用的是COW(CopyOnWrite写时拷贝策略),以保证持久化时数据不会出错。

    自动触发:

    • save m n:通过修改redis.conf中的save选项,来让服务器自动执行bgsave命令。在m秒内,如果有n个键发生改变,则自动触发持久化,通过执行bgsave执行,如果设置多个,只要满足其一就会触发。
    • flushall:会生成内容为空的dump.rdb来替换当前文件,实际操作是清空redis所有数据库。要是不小心执行了这个命令,只要还设置了AOF,就可以恢复。打开aof文件,将flushall命令删除掉。
    • 主从同步:全量同步时会自动触发bgsave命令,生成rdb发送给从节点。
  • AOF:Append Only File,以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录(appendonly.aof)。
    默认情况下,AOF持久化功能是关闭的,如果要打开,将redis.conf中的appendonly选项修改为yes。
    如果Redis服务器开启了AOF持久化功能,那么Redis服务器在启动时会优先载入AOF文件。
    • 所有写命令追加到AOF缓冲区中。
    • AOF缓冲区根据对应的策略向硬盘进行同步操作。
    • 随着AOF文件越来越大,需要定期对AOF进行重写,达到压缩目的。
    • 当Redis重启时,可以加载AOF文件进行数据恢复。
  • 比较RDB和AOF
    • 实现方式上,RDB相当于快照,AOF是用日志记录redis执行过的所有写操作。
    • 文件体积上,RDB记录的是结果,而AOF记录的是过程,所以AOF文件会有体积越来越大的问题,redis提供了AOF重写功能来减小AOF文件体积。
    • 安全性方面,AOF更新的频率要更高,如果发生机器故障,AOF持久化丢失的数据要比RDB丢失的数据更少。
    • 优先级方面,redis服务器启动时,AOF文件的加载优先级高于RDB文件。

简述Redis事务实现

Redis是一个key-value型数据库,是数据库就要提供事务支持,事务是为了保证ACID(原子性、一致性、持久性、隔离性)特性。不同于Mysql的是,在原子性方面,Mysql提供了回滚机制(rollback),而Redis没有。一致性方面,Redis也可以对出错的事务进行恢复。持久性方面,Redis提供了两种持久化机制。隔离性方面,Redis的单线程机制保证了这一点。
Redis提供了watch命令,可以用来监控每一个key。

  1. 事务开始:
    multi命令的执行,标志着一个事务的开始。multi命令会将客户端状态的flags属性中打开REDIS_MULTI标识来完成的。
  2. 命令入队:
    当一个客户端切换到事务状态之后,服务器会根据这个客户端发送来的命令来执行不同的操作。如果客户端发送的命令为mutil、exec、watch、discard中的一个,立即执行这个命令,否则将命令放入一个事物队列里面,然后向客户端返回Queued回复。
    • 如果客户端发送的命令为EXEC、DISCAED、WATCH、MULTI四个命令的其中一个,那么服务器立即执行这个命令。
    • 如果客户端发送的是四个命令以外的其他命令,那么服务器并不立即执行这个命令。
      首先检查该命令的语法是否正确,如果不正确,服务器会在客户端状态(redisClient)的flags属性关闭REDIS_MULTI标识,并且返回错误信息给客户端。
      如果正确,将这个命令放入一个事务队列里面,然后向客户端返回QUEUED回复。
      事务队列是按照FIFO的方式保存入队的命令。
  3. 事务执行:
    客户端发送EXEC命令,服务器执行EXEC命令逻辑。
    • 如果客户端状态的flags属性不包含REDIS_MULTI标识,或者包含REDIS_DIRIY_CAS或者REDIS_DIRIY_EXEC标识,那么就直接取消事务的执行。
    • 否则客户端处于事务状态(flags有REDIS_MULTI标识),服务器会遍历客户端的事务队列,然后执行事务队列中的所有命令,最后将结果全部返回给客户端。
  • watch命令是一个乐观锁,可以为Redis事务提供CAS行为,可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。
  • multi命令用于开启一个事务,它总是返回OK。multi执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会被立即执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。
  • exec:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。当操作被打断时,返回null。
  • 通过调用discard,客户端可以清空事务队列,并放弃执行事务,并且客户端会从事务状态中退出。
  • unwatch命令可以取消watch对所有key的监控。

Redis和Mysql如何保证数据一致?

有以下三种办法:

  1. 先更新Mysql,在更新Redis,如果更新Redis失败,可能仍然不一致。
  2. 先删除Redis中的缓存数据,再更新Mysql,再次查询的时候将数据添加到缓存中,这种方案可以解决方法一的问题,但是在高并发下性能较低,而且仍然会出现数据不一致的问题,比如线程1删除了Redis缓存数据,正在更新Mysql,另外一个线程在查询,就又会将Mysql中的老数据查到Redis中。
  3. 延时双删,步骤是:先删除Redis缓存数据,再更新Mysql,延迟几百秒再删除Redis缓存数据,这样就算在更新Mysql时,有其他线程读了Mysql,把老数据读到了Redis中,那么也会被删除掉,从而保证数据的一致性。

Redis单线程快的原因?(Redis的线程模型?)

  • (重点)单线程快的原因:(1)纯内存操作 (2)核心是基于非阻塞的IO多路复用机制 (3)单线程避免了多线程的频繁上下文切换带来的性能问题
  • 在java中为了提高响应速度,会采用多线程,那么Redis为什么要采用单线程呢?对Redis的操作不需要阻塞,CPU不需要进行频繁的上下文切换,如果采用多线程,反而浪费资源。而Java进行IO时会发生阻塞,此时占着CPU就等于浪费了资源,不如先切换到其他线程。
  • (Redis多路复用器的简述)Redis基于Reactor模式开发了网络事件处理器、文件处理器。是单线程的,它采用IO多路复用机制来同时监听多个Socket,根据Socket上的事件类型来选择对应的事件处理器 来处理这个事件。可以实现高性能的网络通信模型,又可以跟内部的其他单线程的模块进行对接,保证了redis内部线程模型的简单性。

Redis的集群策略,原理和优缺点分别是什么?

在开发测试环境中,我们一般搭建Redis单实例。但是在生产环境下,如果对可用性、可靠性要求较高,就要引入Redis集群方案。
Redis支持三种集群方案:

  1. 主从模式:这种模式比较简单,主库(master)可以读写,并且会和从库(slave)进行数据同步。
write/read
read
Sync
Sync
read
Clients
Redis Master
Redis Slave
Redis Slave

优点:

  • master能自动同步到slave,可以进行读写分离。
  • master、slave之间的同步以非阻塞的方式进行。

缺点:

  • 不具备自动容错与恢复功能。master或slave的宕机都可能导致客户端请求失败,需要等待重启或手动切换客户端IP才能恢复。
  • 存在数据不一致问题。若master在没有同步完数据前发生宕机,就会导致数据不一致。
  • Redis容量受限于单机配置。
  1. 哨兵模式:这种模式在主从的基础上新增了哨兵节点,当哨兵发现主节点宕机,会在从库中选择一个库作为主库,另外哨兵也可以做集群,从而可以保证某一个哨兵结点宕机后,还有其他哨兵结点可以继续工作,这种模式可以比较好的保证Redis集群中的高可用,但是不能很好的解决Redis容量上限问题。
One
Sync
Sync
Sync
moniter
Two
sentinal-1
sentinal-2
...
sentinal-3
Redis Slave
Redis Master
Redis Slave
Redis Slave
Clients
VIP/DNS

优点:

  • 哨兵模式基于主从复制模式,有主从模式的所有优点。
  • 系统可用性更高。哨兵模式下,master挂掉后,哨兵会从slave中选举出新的master。

缺点:

  • Redis的容量受限于单机配置。
  • 需要额外的资源来启动sentinel进程,实现相对复杂。
  1. Cluster模式:这是用的比较多的模式,它支持多主从,这种模式会按照key进行槽位的分配,可以使得不同的key分散到不同的主节点上,利用这种模式可以使得整个集群支持更大的数据容量,同时每个主节点可以拥有自己的多个从节点,若该主节点宕机,会从它的从节点中选举一个新的主节点。

优点:

  • 无中心架构,数据按照slot分布在多个结点。
  • 集群中的每个节点都是平等的关系,每个节点都保存各自的数据和整个集群的状态。我们只需要连接其中任意一个结点,就可以获取到其他节点的数据。
  • 能够实现自动故障转移,节点之间通过gossip协议交换状态信息,用投票机制实现slave到master的角色转换。

缺点:

  • 客户端实现复杂,要缓存插槽映射信息并及时更新,提高了开发难度。
  • 数据通过异步复制,不能保证数据的强一致性。
  • slave只充当冷备,不能缓解读压力。

总结:
Redis共有三种集群方案。

其中主从复制能实现读写分离,但是不能自动故障转移。

哨兵模式基于主从复制模式,能实现自动故障转移,达到高可用,但与主从复制模式一样,不能在线扩容,容量受限于单机配置。

cluster模式通过无中心化架构,实现分布式存储,可进行在线扩容,也能高可用,但对于批量操作、事务操作等的支持性不够好。

Redis主从复制的核心原理?

Created with Raphaël 2.3.0 从服务器收到slaveof命令 第一次执行复制 向master发送psync master返回fullresync {runid} {offset} runid表示主节点的运行id,offset表示当前主节点的复制偏移量 执行全量同步 向master发送psync {runid} {offset} runid是上一次主节点的运行ID,offset 是当前从节点的复制偏移量 master返回continue 执行增量同步 yes no yes no

通过执行slaveof命令或设置slaveof选项,让一个服务器去复制另一个服务器的数据。主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步到从数据库。而从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库,而一个从数据库只能拥有一个主数据库。

全量复制:

  • 主节点通过bgsave命令fork子进程进行RDB持久化,该过程是非常消耗CPU、内存(页表复制)、硬盘IO的。
  • 主节点通过网络将RDB文件发送给从节点,对主从节点的带宽都会带来很大的消耗。
  • 从节点清空老数据、载入新RDB文件的过程是阻塞的,无法响应客户端的命令;若从节点执行bgrewriteof,也会带来额外的消耗。

部分复制:

  • 复制偏移量:执行复制的双方,主从节点,分别会维护一个复制偏移量offset。
  • 复制积压缓冲区:主节点内部维护了一个固定长度的、先进先出(FIFO)队列,作为复制积压缓冲区,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。
  • 服务器运行ID(runid):每个Redis节点,都有其运行ID,运行ID由节点在启动时自动生成,主节点会将自己的运行ID发送给从节点,从节点会将主节点运行ID存起来。从节点Redis断开重连的时候,就是根据运行ID来判断同步的进度:
    • 如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用部分复制(到底能不能部分复制还要看offset和复制积压缓冲区的情况)。
    • 如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的Redis节点并不是当前的主节点,只能进行全量复制。

缓存穿透、缓存击穿、缓存雪崩分别是什么?

缓存中存放的大多都是热点数据,目的就是防止请求可以直接从缓存中获取到数据,而不用访问Mysql。

  1. 缓存雪崩:若缓存中某一时刻大批热点数据同时过期,那么就可能导致大量请求直接访问Mysql,解决的办法是在过期时间上增加一点随机值,另外通过搭建一个高可用的Redis集群也是防止缓存雪崩的有效手段。
  2. 缓存击穿:和缓存雪崩类似,缓存击穿是指某一个热点key突然失效,也导致了大量请求直接访问Mysql数据库,这就是缓存击穿。解决方案就是考虑这个热点key不设置过期时间。
  3. 缓存穿透:假如某一时刻访问redis的大量key都在redis中不存在(比如黑客故意伪造的一些乱七八糟的key),那么也会数据库造成压力,这就是缓存穿透。解决办法是使用布隆过滤器,它的作用就是若它认为一个key不存在,那么这个key就肯定不存在,所以可以在缓存之前加一层布隆过滤器来拦截不存在的key。

布隆过滤器原理,优缺点?

位图:int[10],每个int类型的整数是4 * 8 = 32bit,则int[10]一共有320bit,每个bit非0即1,初始化时都是0 。

添加数据时,将数据进行hash运算得到hash值,对应到bit位,将该bit位改为1,hash函数可以定义多个,一个数据添加会将多个(hash函数个数)bit改为1,多个hash函数的目的是减少hash碰撞的概率

查询数据:hash函数计算得到hash值,对应到bit中,若有一个为0,则说明数据可能在bit中

优点:

  • 占用内存小
  • 增加和查询元素的时间复杂度为:O(K),(K为哈希函数的个数,一般比较小),与数据量大小无关。
  • 哈希函数相互之间没有关系,方便硬件并行运算。
  • 布隆过滤器不需要存储元素本身,在某些对保密要求比较严格的场合有很大优势。
  • 数据量很大时,布隆过滤器可以表示全集。
  • 使用同一组散列函数的布隆过滤器可以进行交、并、差运算。

缺点:

  • 误判率,即存在假阳性(false position),不能准确判断元素是否在集合中。
  • 不能获取元素本身。
  • 一般情况下不能从布隆过滤器中删除元素。

CAP理论,BASE理论

CAP理论是分布式的基础,在一个分布式系统中包含三个部分,一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),这三个部分最多只能同时满足两个。分区容错性必须要保证,那么就要在一致性和可用性中做出选择。

  • 一致性('C):同一时刻,分布式系统中所有结点的数据都是相同的。
  • 可用性(A):在合理时间范围内,系统是否能够正常响应客户端的读写请求。
  • 分区容错性('P):当分布式系统中的一部分节点或者网络分区故障后,系统仍能够正常提供服务。
方案说明
CP放弃A(可用性),系统如遇到网络故障,那么受到影响的服务需要等待一定时间,系统在该时间段不可用
AP放弃C(一致性),放弃数据的强一致性,只求实现数据的最终一致性。

CAP

BASE是Basically Available(基本可用)、Soft state(软状态)和Eventually Consistent(最终一致性)

BASE理论是对CAP中一致性和可用性权衡的结果,其来源于大规模互联网系统分布式实践的总结,是基于CAP定理逐步演化而来的。BASE理论的核心思想是:即使无法做到强一致性,但每个应用都可以根据自身业务特点,采用适当的方式来使系统达到最终一致性。

基本可用:

  • 响应时间上的损失:正常情况下,处理用户请求需要0.5s返回结果,但是由于系统出现故障,处理用户请求的时间变为3s。
  • 系统功能上的损失:正常情况下,用户可以使用系统的全部功能,但是由于系统访问量突然剧增,系统的部分非核心功能无法正常使用。

软状态:数据同步允许一定的延迟

最终一致性:系统中所有额数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态,不要求实时

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值