Redis经典100问

常规篇

0、什么是Redis?

  • Redis是一个使用C语言写成的,开源的高性能key-value非关系缓存数据库。
  • Redis的数据都基于缓存的,所以很快,每秒可以处理超过10万次读写操作,是已知性能最快的Key-Value DB。
  • Redis也可以实现数据写入磁盘中,保证了数据的安全不丢失。

1、Redis有哪些优缺点?

1.1 优点

  • 读写性能优异: 常规场景下Redis读的速度能达到11w次/s,写的速度达到8w次/s。
  • 支持数据持久化: 支持AOF和RDB两种持久化方式。
  • 支持事务: Redis的所有单个操作都是原子性的,不过本着简单高效的原则,Redis不支持事务回滚。
  • 数据结构丰富: 支持的类型有:string、hash、set、zset、list等数据结构。
  • 支持主从复制: 主机会自动将数据同步到从机,可以进行读写分离。

1.2 缺点

  • 内存限制: 容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
  • 健壮性稍弱: Redis不具备自动容错和恢复功能,主机从机的宕机都会导致前端部分读写请求失败,需要等待机器重启或者手动切换前端的IP才能恢复。
  • 可用性稍弱: 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
  • 扩容稍弱: Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂。

2、Redis为什么这么快?

  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)。
  • 数据结构简单,对数据操作也简单,Redis 中的数据结构是专门进行设计的;
  • 核心处理模块采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU,不用去考虑各种锁的问题。
  • 使用多路I/O 复用模型,非阻塞 IO。

3、Redis的应用场景?

  • 缓存: 将热点数据放到内存中,设置内存的最大使用量以及淘汰策略来保证缓存的命中率。
  • 分布式锁 在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。可以使用Redis自带的SETNX命令或者RedLock分布式锁实现。
  • 限流: 有三种限流方式,详细内容请点击这里
  • 计数器: 可以对String类型的key进行自增自减运算,从而实现计数器功能。
  • 会话缓存: 可以使用 Redis 来统一存储多台应用服务器的会话信息。当应用服务器不再存储用户的会话信息,也就不再具有状态,一个用户可以请求任意一个应用服务器,从而更容易实现高可用性以及可伸缩性。
  • 消息队列(发布/订阅功能): Redis的消息队列定位的是轻量级场景,重度场景建议使用kafka或者mq。
  • 其它: Redis数据类型Set可以实现交集、并集等操作,从而实现共同好友等功能。ZSet可以实现有序性操作,从而实现排行榜等功能。

4、Redis有哪些持久化方式?各自有什么优缺点?

  • 什么是持久化: 持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。
    Redis提供两种持久化机制RDB(默认,数据快照)和AOF机制(Append-only File,追加写)
  1. RDB是Redis默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为dump.rdb。通过配置文件中的save参数来定义快照的周期。
  • 优点:IO性能最大化,fork子线程异步处理,不影响主线程;文件保存到磁盘,容灾性好;相对于数据集大时,比 AOF 的启动效率更高。
  • 缺点:数据安全性低,RDB是间隔一段时间进行的持久化,会存在数据丢失可能。
  1. AOF持久化方式:是指所有的命令行记录以 redis 命令请 求协议的格式完全持久化存储)保存为aof文件。
  • 优点:数据安全,aof采用不同的刷盘策略,若采用always级别,则每执行一次命令,就记录一次aof日志;即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题;AOF可以采用rewrite模式,对日志进行定期合并重写。
  • 缺点:AOF文件比RDB文件大,且恢复速度慢;数据集大的时候,比rdb启动效率低。

5、Redis的过期键的删除策略是什么?

  • 立即过期: 每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
  • 惰性过期: 只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
  • 定期过期: 每隔一定的时间,会扫描 expires 字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。

6、Redis的内存用完了会发生什么?

  • 若配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容,否则Redis的写命令会返回错误信息(但是读命令还可以正常返回)。

7、Redis如何做内存优化?

  • 散列表: 可以好好利用Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的Key-Value可以用更紧凑的方式存放到一起。尽可能使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面。比如你的web系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的key,而是应该把这个用户的所有信息存储到一张散列表里面。

8、Redis事务的三个阶段是什么?

  • 事务开始:MULTI
  • 命令入队
  • 事务执行 EXEC
    事务执行过程中,如果服务端收到有EXEC、DISCARD、WATCH、MULTI之外的请求,将会把请求放入队列中排队。

9、描述下事务的四个特性以及redis对应支持情况

  • 原子性: 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
    • Redis由于不支持事务回滚,故无法保证其原子性。
  • 一致性: 事务前后数据的完整性必须保持一致。
    • Redis支持事务一致性。
  • 隔离性: 多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
    • Redis是单进程程序,并且它保证在执行事务时,不会对事务进行中断,事务可以运行直到执行完所有事务队列中的命令为止。因此,Redis的事务是总是带有隔离性的。
  • 持久性: 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
    • Redis由于是内存数据库,并且根据配置来选择RDB和AOF持久化策略,故无法保证持久性。

10、Redis是单线程的,如何提高多核CPU的利用率?

  • 可以在同一个服务器部署多个Redis的实例,并把他们当作不同的服务器来使用,在某些时候,无论如何一个服务器是不够的, 所以,如果你想使用多个CPU,你可以考虑一下分片(shard)。

11、缓存预热有哪些解决方案?

  • 缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!对应的解决方案有:
    • 直接写个缓存刷新页面,上线时手工操作一下;
    • 数据量不大,可以在项目启动的时候自动进行加载;
    • 定时刷新缓存;

12、缓存降级主要是指什么?

  • 背景: 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
  • 最终目的: 保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
  • 注意点: 在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别(info、warning、error、fatal)设置预案。
  • 常见做法: Redis出现问题,不去数据库查询,而是直接返回默认值给用户。

13、描述下热点数据和冷数据以及对应的热点数据问题如何处理?

  • 区别: 热点数据就是访问频率很高的数据;对于冷数据而言,大部分数据可能还没有再次访问到就已经被挤出内存,不仅占用内存,而且价值不大。
  • 热点数据问题: 通过缓存手段,减少数据库的压力,比如我们的微信公众号助手,点赞数,收藏数,分享数等是非常典型的热点数据,但是又不断变化,此时就需要将数据同步保存到Redis缓存,减少数据库压力。

14、Jedis与Redisson对比有什么优缺点?

  • Jedis是Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持。
  • Redisson实现了分布式和可扩展的Java数据结构,和Jedis相比,功能较为简单,不支持字符串操作,不支持排序、事务、管道、分区等Redis特性。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

15、在生成RDB期间,Redis可以同时处理写请求么?

  • 可以的,Redis 使用操作系统的多进程写时复制技术**COW(Copy On Write)**来实现快照持久化,保证数据一致性。
  • Redis在持久化时会调用glibc的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端请求。
  • 当主线程执行写指令修改数据的时候,这个数据就会复制一份副本,bgsave子进程读取这个副本数据写到RDB文件。
  • 这既保证了快照的完整性,也允许主线程同时对数据进行修改,避免了对正常业务的影响。

原理篇

1、一致性hash算法的原理是什么?

  • 一致性hash算法本质上也是一种取模算法,不过,不同于上边按服务器数量取模,一致性hash是对固定值2^32 取模。
  • hash环: 我们可以将这2^32 个值抽象成一个圆环⭕️,圆环的正上方的点代表0,顺时针排列,以此类推,1、2、3、4、5、6……直到2^32 - 1,而这个由2的32次方个点组成的圆环统称为hash环。
  • 服务器映射到hash环: 运用公式 hash(服务器ip)% 2^32 ,使用服务器IP地址进行hash计算,用哈希后的结果对2^32 取模,结果一定是一个0到2^32 - 1之间的整数,而这个整数映射在hash环上的位置代表了一个服务器,依次将node0、node1、node2三个缓存服务器映射到hash环上。
  • 对象key映射到hash环: 接着在将需要缓存的key对象也映射到hash环上,hash(key)% 2^32 ,从缓存对象key的位置开始,沿顺时针方向遇到的第一个服务器,便是当前对象将要缓存到的服务器。
  • 说明: 因为被缓存对象与服务器hash后的值是固定的,所以在服务器不变的条件下,对象key必定会被缓存到固定的服务器上。具体过程入图所示:

注:详细内容请点击这里

2、什么是IO多路复用?

  • IO多路复用模型是建立在内核提供的多路分离函数select基础之上的,使用select函数可以避免同步非阻塞IO模型中轮询等待的问题。
  • 使用select以后最大的优势是用户可以在一个线程内同时处理多个socket的IO请求。用户可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的。完整的流程图如下:

注:详细内容请点击这里

3、Redis是怎么使用事件驱动的?

  • 文件事件(fileEvent): Redis服务器通过套接字与客户端(或者其他Redis服务器)进行连接,而文件事件就是服务器对套接字操作的抽象。服务器与客户端(或者其他服务器)的通讯都会产生相应的文件事件,而服务器则通过监听并且处理这些事件来完成一些列网络通讯操作。
  • 时间事件(timeEvent): Redis服务器中的一些操作(比如serverCron函数)需要在给定的时间点执行,而时间事件就是服务器对着定时操作的抽象。

4、什么是RedLock?

  • Redis官方站提出了一种权威的基于Redis实现分布式锁的方式名叫Redlock。此种方式比原先的单节点的方法更安全。它可以保证以下特性:
    • 安全特性:互斥访问,即永远只有一个client能拿到锁;
    • 避免死锁:最终client都可能拿到锁,不会出现死锁的情况,即使原本锁住某资源的client crash了或者出现了网络分区;
    • 容错性:只要大部分Redis节点存活就可以正常提供服务;

5、Redis的虚拟内存机制是啥呢?

  • Redis直接自己构建了VM机制 ,不会像一般的系统会调用系统函数处理,会浪费一定的时间去移动和请求。
  • Redis虚拟内存机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。
  • 通过VM功能可以实现冷热数据分离,使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。

6、使用过Redisson嘛?说说它的原理

  • 背景:分布式锁可能存在锁过期释放,业务没执行完的问题。有些小伙伴认为,稍微把锁过期时间设置长一些就可以啦。其实我们设想一下,是否可以给获得锁的线程,开启一个定时守护线程,每隔一段时间检查锁是否还存在,存在则对锁的过期时间延长,防止锁过期提前释放。
  • 当前开源框架Redisson就解决了这个分布式锁问题。我们一起来看下Redisson底层原理是怎样的吧:
  • 只要线程一加锁成功,就会启动一个watch dog看门狗,它是一个后台线程,会每隔10秒检查一下,如果线程1还持有锁,那么就会不断的延长锁key的生存时间。
  • 因此,就是使用Redisson解决了锁过期释放,业务没执行完问题。

7、Redis的跳跃表的实现原理以及作用是什么?

  • 跳跃表是有序集合zset的底层实现之一。
  • 跳跃表支持平均O(logN),最坏 O(N)复杂度的节点查找,还可以通过顺序性操作批量处理节点。
  • 跳跃表实现由zskiplist和zskiplistNode两个结构组成,其中zskiplist用于保存跳跃表信息(如表头节点、表尾节点、长度),而zskiplistNode则用于表示跳跃表节点。
  • 跳跃表就是在链表的基础上,增加多级索引提升查找效率。

8、为什么Redis6.0之后改多线程呢?

  • Redis6.0之前,Redis在处理客户端的请求时,包括读socket、解析、执行、写socket等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。
  • Redis6.0之前为什么一直不使用多线程?使用Redis时,几乎不存在CPU成为瓶颈的情况, Redis主要受限于内存和网络。例如在一个普通的Linux系统上,Redis通过使用pipelining每秒可以处理100万个请求,所以如果应用程序主要使用O(N)或O(log(N))的命令,它几乎不会占用太多CPU。
  • redis使用多线程并非是完全摒弃单线程,redis还是使用单线程模型来处理客户端的请求,只是使用多线程来处理数据的读写和协议解析,执行命令还是使用单线程。
  • 这样做的目的是因为redis的性能瓶颈在于网络IO而非CPU,使用多线程能提升IO读写的效率,从而整体提高redis的性能。

注:详细内容请点击这里

9、什么是布隆过滤器以及作用是什么?

  • 定义:布隆过滤器是一种占用空间很小的数据结构,它由一个很长的二进制向量和一组Hash映射函数组成,它用于检索一个元素是否在一个集合中,空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
  • 原理:假设我们有个集合A,A中有n个元素。利用k个哈希散列函数,将A中的每个元素映射到一个长度为a位的数组B中的不同位置上,这些位置上的二进制数均设置为1。如果待检查的元素,经过这k个哈希散列函数的映射后,发现其k个位置上的二进制数全部为1,这个元素很可能属于集合A,反之,一定不属于集合A。

注:详细内容请点击这里

10、Redis压缩列表是什么以及如何设计的?

  • 压缩列表的最大特点,就是它被设计成一种内存紧凑型的数据结构,占用一块连续的内存空间,不仅可以利用 CPU 缓存,而且会针对不同长度的数据,进行相应编码,这种方法可以有效地节省内存开销。
  • 缺陷:不能保存过多的元素,否则查询效率就会降低;新增或修改某个元素时,压缩列表占用的内存空间需要重新分配,甚至可能引发连锁更新的问题。
  • 压缩列表是 Redis 为了节约内存而开发的,它是由连续内存块组成的顺序型数据结构,有点类似于数组。

注:详细内容请点击这里

架构篇

1、Redis持久化数据和缓存怎么做扩容?

  • 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。
  • 如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。

2、Redis线程模型是什么?

  • Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器(file event handler)。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
    • 文件事件处理器使用 I/O 多路复用(multiplexing)程序来同时监听多个套接字, 并根据套接字目前执行的任务来为套接字关联不同的事件处理器。
    • 当被监听的套接字准备好执行连接应答(accept)、读取(read)、写入(write)、关闭(close)等操作时, 与操作相对应的文件事件就会产生, 这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。
  • 虽然文件事件处理器以单线程方式运行, 但通过使用 I/O 多路复用程序来监听多个套接字, 文件事件处理器既实现了高性能的网络通信模型, 又可以很好地与 redis 服务器中其他同样以单线程方式运行的模块进行对接, 这保持了 Redis 内部单线程设计的简单性。

3、Redis哨兵机制是什么?

  • 哨兵是 Redis 的一种运行模式,它专注于对 Redis 实例(主节点、从节点)运行状态的监控,并能够在主节点发生故障时通过一系列的机制实现选主及主从切换,实现故障转移,确保整个 Redis 系统的可用性。他的架构图如下:
  • Redis哨兵具备的能力有如下几个:
    • 监控:持续监控master、slave是否处于预期工作状态。
    • 自动切换主库:当Master运行故障,哨兵启动自动故障恢复流程:从slave中选择一台作为新master。
    • 通知:让slave执行replicaof,与新的master同步;并且通知客户端与新master建立连接。

4、哨兵(Sentinel)模式如何判断主节点挂了?

  • 哨兵监控也是有集群的,会有多个哨兵进行监控,当判断发生故障的哨兵达到一定数量的时候才进行修复。一个健壮的部署至少需要三个哨兵实例。
    • 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他Sentinel实例发送一个PING命令
    • 如果一个实例(instance)距离最后一次有效回复PING命令的时间超过down-after-milliseconds选项所指定的值,则这个实例会被Sentinel标记为主观下线。
    • 如果一个Master被标记为主观下线,则正在监视这个Master的所有Sentinel要以每秒一次的频率确认Master的确进入了主观下线状态。
    • 当有足够数量的Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态,则Master会被标记为客观下线
    • 在一般情况下,每个Sentinel会以每10秒一次的频率向它已知的所有Master,Slave发送INFO命令
    • 当Master被Sentinel标记为客观下线时,Sentinel向下线的Master的所有Slave发送INFO命令的频率会从10秒一次改为每秒一次
    • 若没有足够数量的Sentinel同意Master已经下线,Master的客观下线状态就会被移除。若Master重新向Sentinel的PING命令返回有效回复,Master 的主观下线状态就会被移除。

5、什么是Redis Cluster集群模式?

  • Redis集群是一种分布式数据库方案,集群通过分片(sharding)来进行数据管理(「分治思想」的一种实践),并提供复制和故障转移功能。
  • 将数据划分为16384的slots,每个节点负责一部分槽位。槽位的信息存储于每个节点中。
  • 它是去中心化的,如图所示,该集群由三个Redis节点组成,每个节点负责整个集群的一部分数据,每个节点负责的数据多少可能不一样。
  • 三个节点相互连接组成一个对等的集群,它们之间通过Gossip协议相互交互集群信息,最后每个节点都保存着其他节点的slots分配情况。

6、说说Redis哈希槽的概念?哈希槽又是如何映射到 Redis 实例上呢?

  • 哈希槽类似于数据分区,每个键值对都会根据它的 key,被映射到一个哈希槽中,具体执行过程分为三大步:
    • 根据键值对的 key,使用 CRC16 算法,计算出一个 16 bit 的值;
    • 将 16 bit 的值对 16384 执行取模,得到 0 ~ 16383 的数表示 key 对应的哈希槽。
    • 根据该槽信息定位到对应的实例。键值对数据、哈希槽、Redis 实例之间的映射关系如下:

7、Redis集群会有写操作丢失吗?为什么?

  • Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。

8、Redis集群之间是如何复制的?

  • 采用异步复制,对应的流程图如下:

9、Redis集群最大节点个数是多少?为什么是这个数?

  • 16384个。
  • 每个节点会有心跳检测机制,ping/pong消息里会带上槽位信息,健康检测是频繁进行的,太大的话,报文会较大,影响带宽;而太小的话,会导致hash撞库,并且redis作者认为节点数一般不超过1000个,故权衡下来,取16384数量正合适。

注:详细内容请点击这里

10、Redis与Memcached有什么区别?

共同点: 两者都是非关系型内存键值数据库,现在公司一般都是用 Redis 来实现缓存,而且 Redis 自身也越来越强大了!

  • Memcached所有的值均是简单的字符串,Redis作为其替代者,支持更为丰富的数据类型。
  • Redis可以将长时间不用的key落盘,Memcached的数据则会一直在内存中,所以不适合存储大量数据。
  • Redis可以持久化其数据。

11、什么是RDB内存快照?

  • 在Redis执行「写」指令过程中,内存数据会一直变化。所谓的内存快照,指的就是Redis内存中的数据在某一刻的状态数据。
  • Redis跟这个类似,就是把某一刻的数据以文件的形式拍下来,写到磁盘上。这个快照文件叫做RDB文件,RDB就是Redis DataBase的缩写。
  • 在做数据恢复时,直接将 RDB 文件读入内存完成恢复。

12、Redis底层,使用的什么协议?

  • RESP,英文全称是Redis Serialization Protocol,它是专门为redis设计的一套序列化协议. 这个协议其实在redis的1.2版本时就已经出现了,但是到了redis2.0才最终成为redis通讯协议的标准。
  • RESP主要有实现简单、解析速度快、可读性好等优点。

13、Redis主从数据同步(主从复制)的过程?

  1. slave启动后,向master发送sync命令。
  2. master收到sync之后,执行bgsave保存快照,生成RDB全量文件。
  3. master把slave的写命令记录到缓存。
  4. bgsave执行完毕之后,发送RDB文件到slave,slave执行。
  5. master发送缓冲区的写命令给slave,slave接收命令并执行,完成复制初始化。
  6. 此后,master每次执行一个写命令都会同步发送给slave,保持master与slave之间数据的一致性。

方案篇

1、你知道有哪些Redis分区实现方案?

  • 客户端分区: 就是在客户端就已经决定数据会被存储到哪个redis节点或者从哪个redis节点读取。大多数客户端已经实现了客户端分区。
  • 代理分区: 意味着客户端将请求发送给代理,然后代理决定去哪个节点写数据或者读数据。代理根据分区规则决定请求哪些Redis实例,然后根据Redis的响应结果返回给客户端。redis和memcached的一种代理实现就是Twemproxy。
  • 查询路由(Query routing): 的意思是客户端随机地请求任意一个Redis实例,然后由Redis将请求转发给正确的Redis节点。Redis Cluster实现了一种混合形式的查询路由,但并不是直接将请求从一个Redis节点转发到另一个Redis节点,而是在客户端的帮助下直接redirected到正确的Redis节点。

2、如何使用Redis实现分布式锁?

  • 基于Redisson实现分布式锁,它具有以下特点:
    • 失败无限重试
    • 失败超时重试,自动续命
    • 超时自动释放锁
    • 超时重试,自动解锁
    • Watch Dog自动延时

注:详细内容请点击这里

3、如何解决Redis的并发竞争Key问题?

  • 乐观锁: watch 命令可以方便地实现乐观锁。watch 命令会监视给定的每一个key,当 exec 时如果监视的任一个key自从调用watch后发生过变化,则整个事务会回滚,不执行任何动作。不能在分片集群中使用
  • 分布式锁: 适合分布式场景
  • 时间戳: 适合有序场景,比如A想把key设置为1,B想把key设置为2,C想把key设置为3,对每个操作加上时间戳,写入前先比较自己的时间戳是不是早于现有记录的时间戳,如果早于,就不写入了
  • 消息队列: 串行化处理

4、分布式Redis是前期做还是后期规模上来了再做好?为什么?

  • 既然Redis是如此的轻量(单实例只使用1M内存),为防止以后的扩容,最好的办法就是一开始就启动较多实例。即便你只有一台服务器,你也可以一开始就让Redis以分布式的方式运行,使用分区,在同一台服务器上启动多个实例。
  • 一开始就多设置几个Redis实例,例如32或者64个实例,对大多数用户来说这操作起来可能比较麻烦,但是从长久来看做这点牺牲是值得的。
  • 这样的话,当你的数据不断增长,需要更多的Redis服务器时,你需要做的就是仅仅将Redis实例从一台服务迁移到另外一台服务器而已(而不用考虑重新分区的问题)。一旦你添加了另一台服务器,你需要将你一半的Redis实例从第一台机器迁移到第二台机器。

5、什么是Redis缓存穿透以及对应的解决方案是什么?

  • 定义: 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,造成缓存穿透。
  • 解决办法: 使用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

6、什么是Redis缓存雪崩以及对应的解决方案是什么?

  • 定义: 如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。
  • 解决办法:
    • 加锁排队:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待;
    • 数据预热:可以通过缓存reload机制,预先去更新缓存,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀;
    • 双缓存策略:Cache1为原始缓存,Cache2为拷贝缓存,Cache1失效时,可以访问Cache2,Cache1缓存失效时间设置为短期,Cache2设置为长期。
    • 失效时间随机:在缓存的时候给过期时间加上一个随机值,这样就会大幅度的减少缓存在同一时间过期。

7、什么是Redis缓存击穿以及对应的解决方案是什么?

  • 定义: 缓存在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
  • 解决办法: 用分布式锁控制访问的线程,如:使用redis的setnx互斥锁先进行判断,这样其他线程就处于等待状态,保证不会有大并发操作去操作数据库。

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

  1. 背景: 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题。
  2. 结论: 没办法做到数据库与缓存绝对的一致性,可以做到最终一致性,缓存系统适用的场景就是非强一致性的场景。
  3. 常规解决措施:
    • 缓存延时双删:写请求 -> 删除缓存 -> 更新数据库 -> 休眠一会儿,再删除缓存。
    • 删除缓存重试机制:若删除缓存失败,可以进行重试多删除几次,确保数据正常删除。
    • 给key设置过期时间,达到最终数据一致。

注:详细内容请点击这里

9、Redis常见性能问题和解决方案?

  • Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件。如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次;
  • 为了主从复制的速度和连接的稳定性, Master 和 Slave 最好在同一个局域网内;
  • 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3…

10、Hash冲突怎么办?

  • Redis通过链式哈希解决冲突:也就是同一个桶里面的元素使用链表保存。但是当链表过长就会导致查找性能变差可能,所以Redis为了追求快,使用了两个全局哈希表。用于rehash操作,增加现有的哈希桶数量,减少哈希冲突。
  • 开始默认使用「hash表1」保存键值对数据,「hash表2」此刻没有分配空间。当数据越来越多触发rehash操作,则执行以下操作:
    • 给「hash表2」分配更大的空间分区实现方案;
    • 将「hash表1」的数据重新映射拷贝到「hash表2」中;
    • 释放「hash表1」的空间。
  • 值得注意的是,将hash表1的数据重新映射到hash表2的过程中并不是一次性的,这样会造成Redis阻塞,无法提供服务。
  • 而是采用了渐进式rehash,每次处理客户端请求的时候,先从「hash表1」中第一个索引开始,将这个位置的所有数据拷贝到「hash表2」中,就这样将rehash分散到多次请求过程中,避免耗时阻塞。

11、如何实现数据尽可能少丢失又能兼顾性能呢?

  • 重启Redis时,我们很少使用rdb来恢复内存状态,因为会丢失大量数据。我们通常使用AOF日志重放,但是重放AOF日志性能相对rdb来说要慢很多,这样在Redis实例很大的情况下,启动需要花费很长的时间。
  • Redis4.0为了解决这个问题,带来了一个新的持久化选项——混合持久化。将rdb文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。
  • 于是在Redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志就可以完全替代之前的AOF全量文件重放,重启效率因此大幅得到提升

12、怎么实现Redis的高可用?

Redis 实现高可用有三种部署模式:主从模式,哨兵模式,集群模式。

  • 主从模式: 主从模式中,Redis部署了多台机器,有主节点,负责读写操作,有从节点,只负责读操作。从节点的数据来自主节点,实现原理就是主从复制机制。
  • 哨兵模式: 由一个或多个Sentinel实例组成的Sentinel系统,它可以监视所有的Redis主节点和从节点,并在被监视的主节点进入下线状态时,自动将下线主服务器属下的某个从节点升级为新的主节点。但是呢,一个哨兵进程对Redis节点进行监控,就可能会出现问题(单点问题),因此,可以使用多个哨兵来进行监控Redis节点,并且各个哨兵之间还会进行监控。
  • 集群模式: Cluster集群模式是在Redis3.0加入的,实现了Redis的分布式存储。对数据进行分片,也就是说每台Redis节点上存储不同的内容,来解决在线扩容的问题。并且,它也提供复制和故障转移的功能。
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文晓武

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值