Redis经典口试题
本篇文章简单先容一些 Redis 常见的口试题。Redis 是什么?
Redis,英文全称是Remote Dictionary Server(长途字典服务),是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可长期化的日记型、Key-Value数据库,并提供多种语言的API。
与MySQL数据库差别的是,Redis的数据是存在内存中的。它的读写速度非常快,每秒可以处理高出10万次读写操作。因此redis被广泛应用于缓存,别的,Redis也常常用来做分布式锁。除此之外,Redis支持变乱、长期化、LUA 脚本、LRU 驱动变乱、多种集群方案。
Redis 是一个开源的、基于内存的键值存储体系,通常用作数据库、缓存和消息中心件。它支持多种数据结构,如字符串、哈希、列表、聚集、有序聚集等。
Redis 的数据范例有哪些?
Redis 支持以下主要数据范例:
[*]字符串(String):最根本的范例,可以存储字符串、整数或浮点数。
[*]哈希(Hash):键值对的聚集,得当存储对象。
[*]列表(List):字符串列表,按照插入次序排序,支持在头部或尾部插入元素。
[*]聚集(Set):无序且唯一的字符串聚集。
[*]有序聚集(Sorted Set):类似于聚集,但每个元素关联一个分数,用于排序。
除此之外另有 Geospatial、Hyperloglog、Bitmap 等
https://i-blog.csdnimg.cn/direct/d9910815ef044f349e83fd73f638e527.png
Redis 的常见应用场景有哪些?
Redis 的常见应用场景包罗:
[*]缓存:加速数据访问,减轻数据库压力。
[*]会话存储:存储用户会话信息(可以使用哈希、String大概Sorted Set实现)。
[*]排行榜:使用有序聚集实实际时排行榜(使用的是Sorted Set这个数据范例,Sorted Set 底层维护了一个 socre 字段,通过这个字段可以)。
[*]消息队列:使用列表或发布订阅功能实现消息队列(Redis 着实最开始就是用来做消息队列的,但是由于 Redis 实现的消息队列比力简单,而且Redis 的缓存太好用了,就渐渐的用的越来越少,其他的 MQ 也很好用)。
Redis 长期化(Redis 包管数据不丢失)
Redis 的长期化机制
Redis 提供了两种长期化机制:
[*]RDB(Redis DataBase)长期化:快照方式长期化,将某一个时候的内存数据,以二进制的方式写入磁盘;
[*]AOF(Append Only File)长期化:文件追加长期化,记载全部非查询操作下令,并以文本的情势追加到文件中;
[*]肴杂长期化:RDB + AOF 肴杂方式的长期化,Redis 4.0 之后新增的方式,肴杂长期化是联合了 RDB 和 AOF 的长处,在写入的时间,先把当前的数据以 RDB 的情势写入文件的开头,再将后续的操作下令以 AOF 的格式存入文件,如许既能包管 Redis 重启时的速度,又能减低数据丢失的风险。
RDB 长期化:
长处:
[*]速度快:相对于 AOF 长期化方式,RDB 长期化速度更快,因为它只必要在指定的时间隔断内将数据从内存中写入到磁盘上。
[*]空间占用小:RDB 长期化会将数据生存在一个压缩的二进制文件中,因此相对于 AOF 长期化方式,它占用的磁盘空间更小。
[*]规复速度快:因为 RDB 文件是一个完备的数据库快照,所以在 Redis 重启后,可以非常快速地将数据规复到内存中。
[*]可靠性高:RDB 长期化方式可以包管数据的可靠性,因为数据会在指定时间隔断内自动写入磁盘,纵然 Redis 历程瓦解大概服务器断电,也可以通过加载迩来的一次快照文件规复数据。
缺点:
[*]数据大概会丢失:RDB 长期化方式只能包管数据在指定时间隔断内写入磁盘,因此如果 Redis 历程瓦解大概服务器断电,从末了一次快照生存到瓦解的时间点之间的数据大概会丢失。
[*]实时性差:因为 RDB 长期化是定期实行的,因此从末了一次快照生存到当前时间点之间的数据大概会丢失。如果必要更高的实时性,可以使用 AOF 长期化方式。
所以,RDB 长期化方式适适用于对数据可靠性要求较高,但对实时性要求不高的场景,如 Redis 中的备份和数据规复等。
AOF 长期化:
长处:
[*]数据不轻易丢失:AOF 长期化方式会将 Redis 实行的每一个写下令记载到一个文件中,因此纵然 Redis 历程瓦解大概服务器断电,也可以通过重放 AOF 文件中的下令来规复数据。
[*]实时性好:由于 AOF 长期化方式是将每一个写下令记载到文件中,因此它的实时性比 RDB 长期化方式更好。
[*]数据可读性强:AOF 长期化文件是一个纯文本文件,可以被人类读取和理解,因此可以方便地举行数据备份和规复操作。
缺点:
[*]写入性能略低:由于 AOF 长期化方式必要将每一个写下令记载到文件中,因此相对于 RDB 长期化方式,它的写入性能略低。
[*]占用磁盘空间大:由于 AOF 长期化方式必要记载每一个写下令,因此相对于 RDB 长期化方式,它占用的磁盘空间更大。
[*]AOF 文件大概会出现破坏:由于 AOF 文件是不停地追加写入的,因此如果文件破坏,大概会导致数据无法规复。
所以,AOF 长期化方式适适用于对数据实时性要求较高,但对数据巨细和写入性能要求相对较低的场景,如必要对数据举行实时备份的应用场景。
肴杂长期化:
Redis 肴杂长期化是指将 RDB 长期化方式和 AOF 长期化方式联合起来使用,以充分发挥它们的上风,同时制止它们的缺点。
它的优缺点如下:
长处:
肴杂长期化联合了 RDB 和 AOF 长期化的长处,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时联合 AOF 的长处,有减低了大量数据丢失的风险。
缺点:
[*]实现复杂度高:肴杂长期化必要同时维护 RDB 文件和 AOF 文件,因此实现复杂度相对于单独使用 RDB 或 AOF 长期化方式要高。
[*]可读性差:AOF 文件中添加了 RDB 格式的内容,使得 AOF 文件的可读性变得很差;
[*]兼容性差:如果开启肴杂长期化,那么此肴杂长期化 AOF 文件,就不能用在 Redis 4.0 之前版本了。
所以,Redis 肴杂长期化方式适适用于,必要分身启动速度和减低数据丢失的场景。但必要注意的是,肴杂长期化的实现复杂度较高、可读性差,只能用于 Redis 4.0 以上版本,因此在选择时必要根据实际情况举行衡量。
Redis 集群
Redis 实现高可用
Redis 通过主从复制和哨兵机制实现高可用:
[*]主从复制:主节点将数据同步到从节点,从节点可以处理读请求,减轻主节点压力。
[*]哨兵机制:监控主从节点的状态,自动举行故障转移和主节点推举。
[*]Redis Cluster:将数据分布在差别的服务区上,以此来低落体系对单主节点的依赖。
如果读写都存在一台呆板上,那么单点摆设一旦宕机,就不可用了。为了实现高可用,通常的做法是,将数据库复制多个副本以摆设在差别的服务器上,此中一台挂了也可以继续提供服务。
主从复制
所以主从复制就是指:主节点用来写数据,其他从节点负责读数据,同时同步主节点的新的数据。
如果说主节点宕机了,那么就不能写数据了,照旧可以继续读取数据的,如果从节点宕机了,另有其他从节点的话(一样平常都是一主多从的),照旧可以继续读数据的。
https://i-blog.csdnimg.cn/direct/d4f508f2de33404ea5f8f9c65c48fd40.png
哨兵
哨兵模式就是指,添加监视器,去监听各个节点是否宕机了,从节点宕机了没关系,只不外是其他从节点压力增大了(不会是读取功能失效)。主从同步存在一个致命的题目,当主节点奔溃之后,必要人工干预才华规复 Redis 的正常使用。 所以我们必要一个自动的工具——Redis Sentinel (哨兵模式) 来把手动的过程酿成自动的,让 Redis 拥有自动容灾规复 (failover) 的能力。
如果是主节点宕机了,那么就会被哨兵监听到,随后该监听的哨兵就会发起 “选主” 操作,其余哨兵就会举行投票,票数多的选为新的主节点。
一样平常来说都是单数的哨兵,如果非要设置双数的哨兵,也可以让发起选主的哨兵的权庞大一些,平票的题目也可以解决。
固然这个选主操作不是由起首发现的哨兵直接做出判断的(有大概做出一个误判),而是先辈入一个 “ 主观 ” 下线,比及其他哨兵都确认了确实有题目了,就会将该节点标记为客观下线
如下图所示:
https://i-blog.csdnimg.cn/direct/feea22f4b07d4387b28b368135983388.png
Cluster集群模式
单点存在的不足
[*]Redis 单节点摆设时面临的容量瓶颈、高可用性和水平扩展题目,一主多从的摆设写的能力照旧会到达上限。
[*]单节点 Redis 的数据存储受限于单机内存(通常几十 GB),无法处理海量数据(如 TB 级缓存或日记存储)。单线程模子在高并发下易到达 CPU 上限,无法使用多核服务器资源。
[*]单节点无法通过添加呆板分担负载,只能升级硬件(垂直扩展),成本高昂且有上限。
所以可以将多个 哨兵模式(不是多个哨兵)组合起来,该模式下存在多个主节点。
https://i-blog.csdnimg.cn/direct/0d9cc3d568984f4080668d7457982ed9.png
从上图可以看出 Redis 的主从同步只能有一个主节点,而 Redis Cluster 可以拥有无数个主从节点,因此 Redis Cluster 拥有更强盛的平行扩展能力,也就是说当 Redis Cluster 拥有两个主从节点时,从理论上来讲 Redis 的性能相比于主从来说性能提升了两倍,而且 Redis Cluster 也有自动容灾规复的机制。
Redis Cluster 是 Redis 官方提供的分布式解决方案,通太过片(Sharding)实现数据在多个节点之间的自动分片和负载均衡,解决了 Redis 单节点的容量和可用性瓶颈。
在Cluster 集群模式中引入了 哈希槽的概念:
[*]哈希槽(Hash Slot)
Redis Cluster 将整个数据库分为16384 个哈希槽(Hash Slot),每个键通过CRC16(key) % 16384盘算后映射到对应的槽。
[*]节点分配
每个节点负责一部门哈希槽(比方,3 节点集群中每个节点约负责 5461 个槽)。节点动态添加 / 删除时,槽会自动迁徙,无需重启集群。
Redis Cluster集群中,必要确保16384个槽对应的node都正常工作,如果某个node出现故障,它负责的slot也会失效,整个集群将不能工作。
Redis 关于脑裂题目
Redis 脑裂是指在分布式体系中,由于网络分区等缘故起因,导致 Redis 集群中的部门节点与其他节点失去接洽,从而形成多个独立的子集群,每个子集群都以为本身是主集群,进而引发数据不同等等题目。
比方图下所示:
https://i-blog.csdnimg.cn/direct/0eccaaf39081414caed95ad9c11b09b1.png
这张图就很好的说明白题目:
[*]因为网络题目,导致原来的主节点(旧)并未同步新的主节点,旧的还不知道已经重新选主了;
[*]此时,原来毗连了旧主节点的客户端还在往这里写数据,其他新毗连的客户端向新节点写数据;比及网络规复后,旧节点与新节点比力一下版本号,发现新的节点版本号比他大,它也就明白了已经举行了一次选主操作了;
[*]这个时间旧节点就降级为从节点,并向新的主节点举行请求同步数据,此时题目来了:那在网络故障的情况下,旧的客户端向 Redis 中写的数据怎么办呢?
[*]此时就发现数据丢失了。
在网络故障期间看似是有两个大脑,差别的客户端向差别的节点举行写数据。
脑裂的主要缘故起因着实就是哨兵集群以为主节点出现“假故障”了,于是开始主从切换,推举出了新的主节点,这就导致短暂的出现了两个主节点。
redis集群没有过半机制会有脑裂题目,网络分区导致脑裂后多个master对外提供写服务,一旦网络分区规复,会将此中一个master变为从节点,这时会有大量数据丢失。
redis集群应对脑裂的解决办法应该是取限定原主库吸取请求,Redis提供了两个配置项:
[*]min-slaves-to-write:主库能举行数据同步的最少从库数量。
[*]min-slaves-max-lag:主从举行数据复制时,从库给主库发送ACK消息的最大耽误秒数。
这两项必须同时满足,不然主节点会克制写入操作,这就解决了因脑裂导致数据丢失的题目。
举个例子,我们把min-slaves-to-write设置为1,把min-slaves-max-lag设置为10。
如果Master节点因为某些缘故起因挂了12s,导致集群判断主节点客观下线,开始主从切换。
同时,因为原Master宕机了12s,没有一个(min-slaves-to-write)从节点与主节点之间的数据复制在10s(min-slaves-max-lag)内,不满足配置要求,原Master就无法实行写操作了。
那么如许做就可以解决脑裂题目吗?
答案是不可以的,这两个配置项主要是针对脑裂时数据丢失题目举行防范,但并不能完全解决脑裂大概带来的全部题目,如脑裂发生后多个子集群之间的和谐、数据辩说的处理等。还必要联合其他措施,如使用 Redis Sentinel 或 Redis Cluster 的自动故障转移机制等,来全面应对 Redis 脑裂题目。
按照官方文档所言,redis 并不能包管强同等性
Redis + Sentinel 集群,是最终同等性产物
对于要求强同等性的应用,更应该倾向于 传统关系型数据库 如mysql ,大概使用强同等性的 和谐组件 Zookeeper。
缓存三兄弟
Redis 怎样处理缓存穿透?
缓存穿透是指查询一个不存在的数据,导致请求直接到达数据库。
缓存穿透一样平常都是这几种情况产生的:
[*]业务不公道的操持,比如大多数用户都没开保卫,但是你的每个请求都去缓存,查询某个userid查询有没有保卫。
[*]业务/运维/开辟失误的操作,比如缓存和数据库的数据都被误删除了。
[*]黑客非法请求攻击,比如黑客故意捏造大量非法请求,以读取不存在的业务数据。
解决方法包罗:
[*]布隆过滤器:预先将全部大概的键存储在布隆过滤器中,查询时先检查是否存在。
[*]缓存空值:对于查询不到的数据,缓存一个空值,并设置较短的逾期时间。
[*]针对恶意用户,可以对其举行限定,限定操作次数
布隆过滤器:
https://i-blog.csdnimg.cn/direct/4687b315f5a04e5fac7e811410a08874.png
布隆过滤器原理:它由初始值为0的位图数组和N个哈希函数构成。一个对一个key举行N个hash算法获取N个值,在比特数组中将这N个值散列后设定为1,然后查的时间如果特定的这几个位置都为1,那么布隆过滤器判断该key存在。
Redis 怎样处理缓存雪崩?
缓存雪崩是指大量缓存同时失效,导致请求直接到达数据库。
大概造成缓存雪崩的缘故起因:
[*]大量缓存键同时逾期:当缓存键设置了类似的逾期时间,大概由于某种缘故起因导致大量的键同时失效,会导致缓存雪崩。
[*]缓存服务器故障:当缓存服务器发生故障,无法提供服务时,请求将直接访问后端服务,导致压力会集在后端服务上。
解决方法包罗:
[*]设置差别的逾期时间:制止大量缓存同时失效。
[*]使用分布式锁:在缓存失效时,使用分布式锁控制数据库访问,防止数据库被压垮。
[*]设置熔断机制:在缓存失效的情况下,通过设置熔断机制,直接返回默认值或错误信息,制止请求直接访问后端服务,减轻后端服务的压力。
[*]实时监控和报警:监控缓存体系的状态和性能指标,实时发现非常情况,并通过报警机制关照运维职员举行处理,淘汰缓存雪崩的影响。
Redis 怎样处理缓存击穿?
缓存击穿是指某个热门数据逾期或失效时,同时有大量的请求访问该数据,导致请求直接访问数据库或后端服务,导致体系性能降落以致瓦解的征象。
缓存击穿大概发生的缘故起因包罗:
[*]热门数据失效:当某个热门数据逾期时,此时大量请求访问该数据,导致缓存失效,请求直接访问数据库。
[*]并发访问热门数据:在高并发情况下,大量的请求同时访问同一个热门数据,导致该热门数据在缓存失效期间被并发地访问,触发缓存击穿。
为相识决缓存击穿题目,可以采取以下策略:
[*]设置热门数据永不逾期或逾期时间较长:对于一些热门数据,可以将其设置为永不逾期,大概设置一个较长的逾期时间,确保热门数据在缓存中可用,淘汰因为逾期而触发的缓存击穿。
[*]加互斥锁或分布式锁:在访问热门数据时,可以引入互斥锁或分布式锁,包管只有一个线程去访问后端服务或数据库,其他线程等候效果。当第一个线程获取到数据后,其他线程可以直接从缓存获取,制止多个线程同时访问后端服务,减轻压力。
[*]限定并发访问:通过限定并发访问热门数据的请求量,可以控制请求的流量,制止过多请求同时访问热门数据
Redis 的分布式锁怎样实现?
SETNX + EXPIRE(有原子性题目)
在 Redis 中实现分布式锁可以使用 SETNX 和 EXPIRE 下令来实现,SETNX 是 "SET if Not eXists" 的缩写,是一个原子性操作,用于在指定的 key 不存在时设置 key 的值。如果 key 已经存在,SETNX 操作将不做任何事变,返回失败;如果 key 不存在,SETNX 操作会设置 key 的值,并返回成功。而 EXPIRE 是设置锁的逾期时间的,主要为了防止死锁的发生
SETNX 和 EXPIRE 一起使用可以实现分布式锁的功能,但存在锁误删的题目,比如线程 1 设置的逾期时间为 5s,而线程 1 实行了 7s,那么在第 5s 之后锁逾期了,那么其他线程就可以拥有这把锁了,之后线程 1 实行完业务,又实行了锁删除操作,那么此时锁就被误删了
怎样解决呢?
在删除之前,先判断一下持有锁的持有者是非为它本身。
给每个锁的 value 中添加拥有者的标识,删除之前先判断是否是本身的锁,如果是则删除,否则不删除。固然删除时任然不是个原子操作,所以照旧有题目,给它加个 lua 脚原来判断并删除锁,lua 脚本可以包管 redis 中多条语句实行的原子性,所以就可以解决此题目了。
还可以使用 Redission 框架来实现
Redisson 框架:封装了分布式锁、可重入锁、公平锁、红锁(RedLock)等功能,简化开辟。
Redis 逾期策略和内存淘汰策略
Redis 的逾期策略有哪些?
Redis 的逾期策略包罗:
[*]定期删除:每隔一段时间随机检查一批键,删除此中逾期的键。
[*]惰性删除:在访问键时检查其是否逾期,如果逾期则删除。
Redis中同时使用了惰性逾期和定期逾期两种逾期策略。
[*]假设 Redis当前存放非常多的key,而且都设置了逾期时间,如果每隔肯定时间去检查这些 全部的 key,那么CPU的负载就会特别高,以致挂掉
[*]因此,redis 接纳的是定期逾期,每隔一段时间就随机抽取肯定命量的 key 来举行检查和删除
[*]但是,末了大概会有许多已颠末期了的key 没被删除,这个时间接纳 惰性删除,当用户获取的时间,redis 举行检查一下,逾期了就给他删掉
Redis 的内存淘汰策略有哪些?
Redis 提供了多种内存淘汰策略,包罗:
[*]noeviction:不淘汰数据,返回错误。
[*]allkeys-lru:从全部键中淘汰迩来最少使用的键。
[*]volatile-lru:从设置了逾期时间的键中淘汰迩来最少使用的键。
[*]allkeys-random:从全部键中随机淘汰键。
[*]volatile-random:从设置了逾期时间的键中随机淘汰键。
[*]volatile-ttl:从设置了逾期时间的键中淘汰剩余时间最短的键。
在 Redis 4.0 版本中又新增了 2 种淘汰机制:
[*]volatile-lfu:淘汰全部设置了逾期时间的键值中,最少使用的键值;
[*]allkeys-lfu:淘汰整个键值中最少使用的键值。
Redis 的变乱机制怎样工作?
[*]开始变乱(MULTI):客户端发送 MULTI 下令,标记变乱的开始。
[*]下令入队:后续发送的下令不会立即实行,而是进入队列等候。
[*]实行变乱(EXEC):客户端发送 EXEC 下令,Redis 按次序实行队列中的全部下令。
[*]返回效果:EXEC 返回全部下令的实行效果,次序与入队时同等。
示例代码:
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET key1 "value1"
QUEUED
127.0.0.1:6379> SET key2 "value2"
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
2. 变乱的关键特性
原子性(Atomicity)
[*]单条下令原子性:Redis 包管单个下令的原子性(如 INCR 操作不会被打断)。
[*]变乱级原子性:Redis 变乱不支持回滚,若队列中某个下令失败(如范例错误),其他下令仍会继续实行。
MULTI
SET key1 "value1"
INCR key1# 错误:对字符串执行 INCR
SET key2 "value2"
EXEC# 结果:key1 被设置,key2 也被设置,INCR 失败
隔离性(Isolation)
[*]Redis 是单线程实行下令,变乱实行期间不会被其他客户端下令打断,包管了变乱的隔离性。
3. WATCH 机制(乐观锁)
Redis 提供 WATCH 下令实现乐观锁,用于实现 CAS(Compare-and-Swap)操作:
[*]原理:在 MULTI 前使用 WATCH 监视一个或多个键,若变乱实行前这些键被其他客户端修改,则整个变乱会被放弃(EXEC 返回 nil)。
[*]典范场景:实现分布式锁或计数器的原子递增。
示例:库存扣减(CAS 操作)
WATCH stock# 监视库存键
GET stock # 获取当前库存
# 判断库存是否足够,若足够则执行事务
MULTI
DECRBY stock 1
EXEC# 若期间 stock 被修改,EXEC 返回 nil,需重试
4. 变乱的范围性
[*]不支持回滚:Redis 以为 “错误通常由编程错误导致”,因此不支持变乱回滚,简化了内部实现。
[*]串行实行:变乱中的下令按次序实行,无法并发,大概影响性能。
[*]不支持嵌套:Redis 变乱不能嵌套,每个变乱必须以 MULTI 开始,EXEC 竣事。
5. 与其他数据库变乱的对比
特性Redis 变乱传统数据库(如 MySQL)原子性部门支持(不支持回滚)完全支持(ACID)隔离性基于单线程包管通过锁或 MVCC 实现长期性依赖长期化配置通常通过 WAL 包管嵌套变乱不支持支持复杂查询仅支持简单下令组合支持 SQL 复杂查询6. 最佳实践
[*]替换方案:对于复杂变乱需求,可思量使用 Lua 脚本(Redis 包管脚本实行的原子性)。
-- 原子性地实现库存扣减
if redis.call("GET", "stock") > 0 then
redis.call("DECR", "stock")
return 1
else
return 0
end
[*]错误处理:变乱实行后需检查返回值,若 EXEC 返回 nil,需重试整个操作。
[*]性能考量:制止在变乱中包罗大量下令,淘汰客户端等候时间。
Redis 的性能优化有哪些方法?
Redis 的性能优化方法包罗:
[*]使用合适的数据结构:根据场景选择最合适的数据结构。
[*]淘汰网络耽误:将 Redis 摆设在靠近应用服务器的地方。
[*]批量操作:使用 MGET、MSET 等下令淘汰网络请求次数。
[*]长期化优化:根据业务需求选择合适的长期化策略。
[*]根据业务需求设置公道的内存淘汰策略(maxmemory-policy),如 allkeys-lru(得当缓存场景)或 volatile-lru(得当带逾期时间的键)。
[*]限定最大内存(maxmemory),防止 Redis 因内存溢出瓦解。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]