redis面试题

目录

Redis集群

Redis集群模式下Leader选举?

Redis的集群是怎么实现的?

Redis主从的同步策略?

Redis实现分布式锁?

Redis集群 一致性hash的原理?

Redis的hash算法用是啥?

Redis集群,高可用,原理?

Redis缓存分片?

Redis有几种部署方式?哨兵机制和集群的区别是啥?

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

Redis中哨兵的作用?

Redis实现消息队列?

Redis基础

Redis⾼性能的原因大概可以讲一些?

如何使用redis实现记录用户登入了多少天,连续登入了多少天?

如何对Redis进行性能调优?

Redis为什么引入了多线程?

Redis线上操作最佳实践有那些?

Redis单线程为什么还这么快?

Redis实现语言以及Redis是什么?

系统有海量的活跃数据,怎么统计日活?

Redis为什么这么快?redis采用多线程会有哪些问题?

Redis中的Lua有没有使用过?可以用来做什么?

Redis的线程模型,是怎么工作的?

单线程的Redis如何能够高并发?

Redis的key

Reids热key问题怎么解决?

Redis中Key过期了一定会立即删除吗?

Redis的key和value的设计原则有那些?

Redis如何高效安全的遍历所有Key?

Redis的key过期了为什么内存没释放?

Redis淘汰key的算法LRU与LFU区别?

删除key的命令会阻塞Redis吗?

Redis中的key和value的类型分别是什么?

Redis中大key(bigkey)解决办法?

Redis的存储

Redis底层数据是如何用跳表来存储的?

Redis默认的DB(数据库)有多少个?

Redis的key在底层是怎么存储的?

Redis如何实现持久化?

Redis是如何处理过期数据的?

了解Redis事务的CAS操作吗?

当内存不够用时redis是如何处理的?

Redis的LRU过期策略的具体实现?

Redis宕机之后如何恢复数据?

Redis持久化的几种方式,优缺点是什么,怎么实现的?

Redis的缓存失效策略?

redis的数据淘汰(过期)策略?

redis数据类型存储的场景?

什么是缓存穿透?

什么是缓存击穿?

什么是缓存雪崩?

Redis缓存怎么和数据库保持一致性?

Redis数据结构

String类型的底层数据结构及实现原理?

List类型在redis中的实现?

Hash类型在redis中的实现?

Redis怎么解决哈希冲突?

Set和hset的区别?

Set类型在redis中的实现?

Zset类型在redis中的实现?

Redis支持的数据类型到跳跃表?

Redis跳跃表?

 Redis的命令

Redis中mset(批量)和set(单次)操作的区别是什么?

redis中的常用的命令有哪些?

Redis中mset(批量)和set(单次)操作的区别是什么?

热KEY重建有什么风险,如何优化?

Redis中大key(bigkey)解决办法?


Redis集群

Redis集群模式下Leader选举?

答:每个节点都会定期向其他节点发送PING消息来检查节点是否可达。如果一个节点在node - timeout时间(默认 15 秒)内没有收到另一个节点的PONG响应,就会将对方标记为疑似下线,如果超过半数节点都认为该节点下线时,该节点会被标注为已下线。这时将开启选举,1)slave发现自己的master变为FAIL;2)将自己记录的集群选举轮次标记加1,并广播信息给集群中其他节点;3)其他节点收到该信息,只有master响应,判断请求者的合法性,并发送结果;4)尝试选举的slave收集master返回的结果,收到超过半数master的统一后变成新Master;5)广播Pong消息通知其他集群节点。

Redis的集群是怎么实现的?

答:1)集群至少需要6个节点才能组成高可用集群,且每个节点要开启集群模式;2)各节点之间通过 Gossip 协议进行通信;3)Reids有一套被称作环的哈希算法,就是用节点IP+编号对16384个槽进行求模取余,对数据和节点进行哈希;4)一个主可以有多个从,主要用于数据备份和故障恢复,当主节点故障时,从节点会进行投票选举,超过半数票,将自己升级为主节点,实现故障迁移。

Redis主从的同步策略?

   答:分为全量同步和增量同步,全量同步分为三个阶段:1)同步快照阶段:msster创建并发送快照给slave,slave载入并解析快照,master此时将产生的新命令存储到缓冲区;2)同步写缓冲阶段:master向slave同步存储在缓冲区的写命令;3)同步增量阶段:master向slave同步写命令;增量同步:slave完成初始化,master每执行一个写命令就向slave发送发送相同的命令,slave接收并执行;

Redis分布式锁的特性?

答:1)互斥性:保证同一时间只有一个客户端可以拿到锁;2)安全性:只有加锁的服务才有解锁权限; 3)避免死锁:出现死锁就会导致后续的任何服务都拿不到锁,不能再对共享资源进行任何操作了;4)保证加锁与解锁操作是原子性操作, 加锁分为a.设置key set(key,value)b.给key设置过期时间;使用分布式锁:1)使用redis命令 set key value NX EX max-lock-time 实现加锁;2)使用redis命令 EVAL 实现解锁。

Redis集群 一致性hash的原理?

答:1)集群根据数据和节点对16384个slots(槽位)进行求模取余;2)集群默认会对key值使用crc16算法得到一个整数值;3)通过整数值找到具体槽位;4)在根据槽位值和Redis节点的对应关系找到具体的节点进行存储;缺点是:容易发生数据倾斜,解决办法是添加虚拟节点;

Redis集群,高可用,原理?

答:1)主观下线: 集群中每个节点都会定期向其他节点发送ping消息,接收节点回复pong消息作为响应。如果在cluster-node-timeout时间内通信一直失败,则发送节点会认为接收节点存在故障,把接受节点标记为主观下线(pfail)状态; 2)客观下线:a)当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播;b)假设节点a标记节点b为主观下线,一段时间后节点a通过消息把节点b的状态发送到其他节点,当其他节点收到消息并解析出消息体中含有b的pfail状态,把节点b加入下线报告链表;c)当某一节点c收到节点b的pfail状态时,此时有超过一半的槽主节点都标记了节点b为pfail状态时,则标记故障节点b为客观下线;d)向集群广播一条pfail消息,通知集群内的所有节点标记故节点b为客观下线状态并立刻生效,同时通知故障节点b的从节点触发故障转移流程;3)故障恢复:a)资格检查:若从节点与主节点断线时间超过一定时间,则不具备资格;b)准备选举时间:当从节点符合故障转移资格后,要等待一段选举时间后才开始选举在故障节点的所有从节点中,复制偏移量最大的那个从节点最先开始(与主节点的数据最一致)进行选举,然后是次大的节点开始选举.....剩下其余的从节点等待到它们的选举时间到达后再进行选举;c)发起选举;d)选举投票:只有持有槽的主节点才具有一张唯一的选票,从从节点收集到N/2 + 1个持有槽的主节点投票时,从节点可以执行替换主节点操作;e)替换主节点。

Redis缓存分片?

答:集群分片最少要有6个才能组成高可用集群,其中三个主节点,三个从节点,三个主节点会分配槽处理客户端的请求,通过范围分片,哈希分片,一致性哈希算法,哈希槽等方法对数据分片;

Redis有几种部署方式?哨兵机制和集群的区别是啥?

答:单机模式:优点:架构简单,部署方便,高性能,性价比高;缺点:不保证数据的可靠性,缓存失效后数据丢失;性能受限;哨兵(Sentinel)模式:优点:部署简单;能够解决主从的高可用切换问题;能通过哨兵监控各个节点; 缺点:部署主从比较繁琐;资源浪费备节点不提供服务;不能读写分离;集群模式;优点:无中心架构;可数据共享,动态分布数据;可扩展性高;高可用,运维成本较低;缺点:客户端实现复杂;数据通过异步,不能保证数据强一致性;批量操作KEY受限制;

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

     答:主要是发生在并发写;解决办法:1)利用redis自带的incr(1.为key储存的数字值加上一,2.如果key储存的值不能被解释为数字,那么INCR 命令将返回一个错误。)命令;2)使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高);3)使用watch命令:WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行。监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,所以在MULTI命令后可以修改WATCH监控的键值);4)这个是针对客户端来的,在代码里要对redis操作的时候,针对同一key的资源,就先进行加锁(java里的synchronized或lock);5)利用redis的setnx实现内置的锁,当且仅当key不存在,将key的值设置为value,并且返回1;若是给定的key已经存在,则setnx不做任何动作,返回0。

Redis中哨兵的作用?

          答:哨兵(sentinel) 系统用于管理多个 Redis 服务器,其实也是运行在特殊模式下的 Redis 服务器,主要有:1)监控(Monitoring): 哨兵会不断地检查你的Master和Slave是否运作正常;2) 提醒(Notification):当 Redis出现问题时,  通过 API 向管理员或者其他应用程序发送通知;3)自动故障迁移:当Master故障时,其中的Slave升级为新的Master,并让其它Slave改为新的master;

Redis实现消息队列?

答:Redis的消息队列有两种模式,一种是发布者和订阅者模式,另外一种是生产者和消费者模式, 发布者和订阅者模式:发布者发送消息到队列,每个订阅者都能收到一样的消息。 生产者和消费者模式:生产者将消息放入队列,多个消费者共同监听,谁先抢到资源,谁就从队列中取走消息。注意,每个消息只能被一个消费者接收。

Redis基础

Redis⾼性能的原因大概可以讲一些?

 答:1)存储速度快: Redis读写数据完全基于内存。2)数据类型存储丰富: Redis支持多种不同类型的数据结构, 包括集合、有序集合、哈希等。3)单线程单进程模型: Redis内部主要是使用单线程的IO复用模型,并支持使用select、poll、epoll的等方式的事件处理器, 单线程模型可以充分利用CPU资源,将速度优势发挥到最大。4)分布式集群:Redis除了支持单机模式,主从模式以外还自带了Redis集群。

如何使用redis实现记录用户登入了多少天,连续登入了多少天?

答:用Bitmap实现,计算天数: 前提(Id是唯一的数字,比如id为5),那么你第一天 用户5 登录了,你可以存储为一...第二天...二...以此类推,到最后一天,以当天为起点,然后往前面推算,凡是碰到1的,就把他给统计,碰到0,就不再给用户继续统计,即可!

如何对Redis进行性能调优?

答:1.性能优化:a.避免使用复杂度过高的命令;b.操作bigkey;c.内存碎片整理;d.fork操作优化;e.内存大页配置;2.数据管理:a.AOF配置的优化;b.集中过期处理;e.数据淘汰策略;3.网络磁盘:a.连接管理;b.数据传输优化;c.Swap的使用;

Redis为什么引入了多线程?

答:主要是在网络I/O处理上增加了多线程,增加的原因和优势:1)网络I/O瓶颈;2)提升宽度利用率;3)减低延迟;4)充分利用多核CPU;

Redis线上操作最佳实践有那些?

答:1)优化数据结构;2)设置合理的过期时间;3)使用持久化策略;4)监控和报警;5)规模化和高可用性;6)设计良好的命名空间;7)减少网络延迟;8)参数调优;9)客户端重试策略;10)访问控制和安全;

Redis单线程为什么还这么快?

答:1)命令执行基于内存操作;2)命令执行时候单线程操作,没有线程切换开销;3)基于IO多路复用机制提升Redis的I/O利用率;4)高效的数据存储结构,比如:跳表、压缩列表等;

Redis实现语言以及Redis是什么?

           答:C语言;redis是非关系型的键值对数据库,可以根据键以o(1)的时间复杂度查询或插入关联值,是以内存方式存储的,并内置了复制,磁盘持久化、事务、SSL客户端代理等功能,通过哨兵和自动化分区提高可用性;

系统有海量的活跃数据,怎么统计日活?

         答:用bitmap(位图),比如:setbit插入数据;用getbit获取数据;用bitcount统计数据;bitmap(位图)的存储原理是: 在setbit插入数据时,在key后面有个offset偏移量,通过偏移量设置bit的值,bit的底层其实是String类型,最多能存512M,通过bitcount key 0 -1其中key是需要统计的用户,0和-1是偏移量,这样就实现了天的统计;夸天统计是将key按位于(and),而周和月的统计是将多天的key按位或(or)合并存到一个key中在通过bitcount统计即可;

Redis为什么这么快?redis采用多线程会有哪些问题?

 答:redis快:1)数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);2)数据结构简单,对数据操作也简单;3)采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗CPU;4)使用多路I/O复用模型,非阻塞IO;5)使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制;redis线程:Redis在多线程高并发下出现数据错乱,也就是A的数据给了B,B的数据给到了C。

Redis中的Lua有没有使用过?可以用来做什么?

 答: 1、减少网络开销:可以将多个请求通过脚本的形式一次发送,减少网络时延和请求次数。2、原子性的操作:Redis会将整个脚本作为一个整体执行,中间不会被其他命令插入。因此在编写脚本的过程中无需担心会出现竞态条件,无需使用事务。 3、代码复用:客户端发送的脚步会永久存在redis中,这样,其他客户端可以复用这一脚本来完成相同的逻辑。4、速度快:见 与其它语言的性能比较, 还有一个 JIT编译器可以显著地提高多数任务的性能; 对于那些仍然对性能不满意的人, 可以把关键部分使用C实现, 然后与其集成, 这样还可以享受其它方面的好处。5、可以移植:只要是有ANSI C 编译器的平台都可以编译,你可以看到它可以在几乎所有的平台上运行:从 Windows 到Linux, 同样Mac平台也没问题, 再到移动平台、游戏主机,甚至浏览器也可以完美使用 (翻译成JavaScript);6、源码小巧:20000行C代码,可以编译进182K的可执行文件,加载快,运行快。 

Redis的线程模型,是怎么工作的?

  答:redis在6.0版本以前针对客户端是单线程的,当有unlink和慢IO时会创建子进程处理,在6.0版本以后提供了多线程默认是关闭的,而且只是对read和write是多线程,其command(处理客户端命令)是单线程的,另外客户端是通过TCP连接服务的,单个TCP连接内是有序的,多个TCP连接时不能保证有序;

单线程的Redis如何能够高并发?

答:Redis通过主从架构,实现读写分离,主节点负责写,并将数据同步给其他从节点,从节点负责读,从而实现高并发;

Redis的key

Reids热key问题怎么解决?

答:1)本地缓存,适合提前已知的情况;2)请求分摊:将热key拆分成多个子key,将读请求分摊到多个key上;3)限流:防止过多的请求进入;4)监控和报警:适合未知的热key场景;

Redis中Key过期了一定会立即删除吗?

答:不一定立即删除,有两种删除策略:1)惰性删除:过期后不会立即删除,而是等着下次访问时才会删除; 2)定期删除:reids后台会有一个定时任务,大约每隔100毫秒扫描一次删除;

Redis的key和value的设计原则有那些?

答:key:1)短小精炼;2)使用命名空间;3)避免热key;4)选择唯一和通用的标识;

value:1)选择合适的数据结构;2)限制单个value的大小;3)利用压缩;4)TTL设置;

Redis如何高效安全的遍历所有Key?

答:1)使用scan命令,就是增量式的,可以指定每次遍历一小部分的key;

Redis的key过期了为什么内存没释放?

答:修改过期的key时没有携带过期时间,那么这个key就变成永不过期了;redis的删除策略使用:惰性和定时删除,当一个key过期了,并不会立马删除;

Redis淘汰key的算法LRU与LFU区别?

答:LRU(最近最少使用):淘汰很久没被访问过的数据,以最近一次访问的时间作为参考;LFU(最不经常使用):淘汰最近一段时间被访问次数最少得数据;

删除key的命令会阻塞Redis吗?

答:删除单个字符串的key,事件复杂度是o(1),删除单个列表、集合、有序集合、哈希的key,事件复杂度是o(M);

Redis中的key和value的类型分别是什么?

      答:key都是String类型,value有String、Set、List、Hash、Zset;

Redis中大key(bigkey)解决办法?

           答:存在的问题:1)读写bigkey会导致超时严重,甚至阻塞服务;2)大key相关的删除或者自动过期时,会出现qps突降或者突升的情况,极端情况下,会造成主从复制异常,Redis服务阻塞无法响应请求;3)占用资源;解决办法:1)将大key分拆成多个key,value用multiGet获取值,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;2)将分拆的key,value用hash存储,用hget,hmget来获取部分的value,使用hset,hmset来更新部分属性;3)按照存储元素进行规则分类,分散存储到多个redis实例中;4)可以利用pipeline管道,一次发送多个命令,无需等待服务端返回;

Redis的存储

Redis底层数据是如何用跳表来存储的?

答:zset结构,对跳表做了优化,就是将有序链表改造为支持近乎“折半查找”算法,可以快速的插入、删除、查询等;

Redis默认的DB(数据库)有多少个?

              答:一共16个, 都是redisDb存储的,  redisDb的数据结构共有9个 :1)dict(字典):主要用于Key的索引; 2)expires:存储过期时间; 3)blocking_keys(阻塞):存储被阻塞的key; 4)ready_keys:存储的是可以解除阻塞的键, key通过该方式与客户端建立关系;5)watched_keys:存储的是正在被 watch 命令监控的键;6)id:记录的是当前数据库的一个编号;7)avg_ttl:收集了所有键剩余存活时间的一个平均值;8)expires_cursor;9)defrag_later;其中RedisDB数据结构整体流向:

                        

Redis的key在底层是怎么存储的?

      答:主要用redisObject对象,该对象中有type(数据类型:string、list、hash、set)、encoding(数据编码,内存的利用率极高)、iru:LRU_BITS(内存淘汰策略)、refcount(内存计数器)、 *ptr(len、free、buf[])指向数据编码对象也就是真实的数据;int类型存储逻辑:首先判断数据的长度是否在20以内,其次尝试转成int,如果是int的话ptr将不在创建内存地址,直接存储在redisObject对象上;embstr类型存储逻辑: 是SDS(Simple Dynamic String 简单动态字符串),其中cpu获取数据的缓存行是64byte, 如果业务数据少于44个字节,只需分配一次内存空间即可,而不在通过指针引用; raw类类型存储逻辑:存储大于 44 个字节的字符串,需要分配两次内存空间;

Redis如何实现持久化?

           答:有三种:1)RDB(redis DataBase):保存某一个时间点之前的快照数据,通知配置方式或者手动执行save命令,优点是a)服务启动数据恢复比较快;、b)持久化使用子进程处理主进程可以继续处理客户端请求 ;缺点是:a)持久化有时间间隔;b)写入进程多的话会有大量的分页错误,造成性能耗费;2)AOF(Append-Only File):所有的命令行记录以redis命令请求协议的格式完全持久化存储保存为aof文件,优点是:数据安全,配置appendfsync属性,每执行一次命令就记录到aof文件中;缺点是:数据大的时候,比rdb启动效率低;3)混合持久化(4.0版本以后):进行aof重写时子进程将当前时间点的数据快照保存为rdb文件格式,而后将父进程命令保存为aof格式,优点是:兼顾了rdb的恢复速度和aof的安全性;

Redis是如何处理过期数据的?

            答:有两种:1)惰性删除:当访问时才判断是否过期,是就删除返回null,否就返回数据;2)定期删除:通过serverCron(定时任务)每一秒执行10次;

了解Redis事务的CAS操作吗?

  答:cas(check-and-set 乐观锁):Redis的事务:redis事务用的命令:MULTI、SET、HSET、EXEC。Redis会将所有EXEC命令之前的命令放入一个QUEUE中,当遇到EXEC时批量执行QUEUE中的命令,但是 Redis的事务是不支持回滚的,它只是顺序的执行命令,并批量返回结果,但是对于极端情况下,事务在没有完全执行完时宕机,导致事务日志只写入部分,这样在重启时会产生错误,用aof的修复工具修复后可以进行启动;Watch命令可以监控Redis中的一个key,当Key发生变化时终止事务的提交;如果watch一个不稳定(有生命周期)的key并且此key自然过期,exec仍然会执行事务队列的指令;

当内存不够用时redis是如何处理的?

  答:当内存不足时影响最大的是写请求会返回错误,通过两个算法:1)LRU(The Least Recently Used)最近少使用:当数据在最近一段时间没有被访问,将被认定为访问的可能性很小,当内存满时将被淘汰,通过链表实现;2)LFU(Least Frequently Used)最不请经常使用:当数据在最近一段时间很少被访问,将被认定为访问的可能性很小,当内存满时将被淘汰也是用redisObject中的lru在存储lfu数据,将该lru分为两部分1)高16位记录访问时间(分钟);2)低八位记录频率,简称counter;

Redis的LRU过期策略的具体实现?

答:Redis中的键与值都是redisObject对象,unsigned的低24 bits的lru记录了redisObj的LRU time, LRU_CLOCK_RESOLUTION代表了LRU算法的精度,即一个LRU的单位是多长。server.hz代表服务器刷新的频率, 如果服务器的时间更新精度值比LRU的精度值要小,LRU_CLOCK()直接使用服务器的时间,减小开销。

Redis宕机之后如何恢复数据?

答:有三种:1)RDB(redis DataBase):保存某一个时间点之前的快照数据,通知配置方式或者手动执行save命令,优点是1)服务启动数据恢复比较快;2)持久化使用子进程处理主进程可以继续处理客户端请求 ;缺点是:1)持久化有时间间隔;2)写入进程多的话会有大量的分页错误,造成性能耗费;2)AOF(Append-Only File):所有的命令行记录以redis命令请求协议的格式完全持久化存储保存为aof文件,优点是:数据安全,配置appendfsync属性,每执行一次命令就记录到aof文件中;缺点是:数据大的时候,比rdb启动效率低; 3)混合持久化(4.0版本以后):进行aof重写时子进程将当前时间点的数据快照保存为rdb文件格式,而后将父进程命令保存为aof格式,优点是:兼顾了rdb的恢复速度和aof的安全性;

Redis持久化的几种方式,优缺点是什么,怎么实现的?

答:1)RDB:是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化;优点:a)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中 redis 的数据,这种多个数据文件的方式,非常适合做冷备。b)可以让 redis 保持高性能,因为 redis主进程只需要 fork 一个子进程,让子进程执行磁盘 IO 操作来进行RDB 持久化即可。c)对于灾难恢复,可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。d)如果数据集很大,RDB的启动效率会更高。缺点:a)RDB 数据快照文件,都是每隔 5 分钟,或者更长时间生成一次,这个时候就得接受一旦 redis 进程宕机,那么会丢失最近 5 分钟的数据。b)RDB是通过fork子进程来协助完成数据持久化工作的,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。实现方式:a)通过配置自动进行的持久化: save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。b)通过SAVE与BGSAVE命令进行持久化。c)通过执行FLUSHALL命令,会清空内存中的数据。d)执行复制的时候; 2)AOF:将Reids的操作日志以追加的方式写入文件;优点:a)每隔 1 秒,通过一个后台线程执行一次fsync操作,最多丢失 1 秒钟的数据。b)日志文件以 append-only 模式写入,没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损。c)如果日志过大,Redis可以自动启用rewrite机制。
      d)日志文件的命令通过非常可读的方式进行记录,格式清晰、易于理解。 缺点:a)相同数量的数据集而言,AOF文件通常要大于RDB文件。c)根据同步策略的不同,AOF在运行效率上往往会慢于RDB。

Redis的缓存失效策略?

  答:1)FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。  2)LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。 3)LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

redis的数据淘汰(过期)策略?

答:1)定时删除: 在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。  2)惰性删除:放任过期键不管,每次从键空间读写操作时,都检查键是否过期,如果过期,删除该键,如果没有过期,返回该键。 3)定期删除:每隔一段时间执行一次定时删除,并通过限制删除操作执行的总时长和总频率来限制删除操作对CPU占用时间的影响。 通过定期删除过期键,有效减少了因为过期键而带来的内存浪费。4)主动清理:当前已用内存超过maxmemory限定时,触发主动清理策略。清理时会根据用户配置的maxmemory-policy来做适当的清理。

redis数据类型存储的场景?

 答:1)string :一个 key 对应一个 value。value其实不仅是String,也可以是数字。string 类型是二进制安全的,使用场景:常规key-value缓存应用。常规计数: 微博数, 粉丝数。2)hash: 是一个键值(key => value)对集合,hash 是一个 string 类型的 field 和 value 的映射表,使用场景:存储部分变更数据,如用户信息等。Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口;3)list: 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),使用场景:比如微博ID等;4)set是string类型的无序集合。集合是通过hashtable实现的,概念和数学中个的集合基本类似,可以交集,并集,差集等等;使用场景:存储全班同学成绩;

什么是缓存穿透?

   答:每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源;解决办法:1)采用布隆算法过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉;2)设置缓存的过期时间(短);

什么是缓存击穿?

 答:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期就会从DB获取数据并回设到缓存;解决办法:1)使用互斥锁(mutex key)  ,就是在缓存失效的时候,不是立即去load db,而是先用Redis的SETNX去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法;2)用二级缓存也就是在一层redis;

什么是缓存雪崩?

     答:在流量洪峰达到时,大量的请求导致缓存服务宕机,所有请求访问db造成不可用称为雪崩;解决办法:1)采用集群架构实现;2)对服务接口降级;3)对缓存监控,达到阈值时通过自动故障转移和不重要的接口;4)将比较常用的key缓存在本地,减少redis访问;

Redis缓存怎么和数据库保持一致性?

答:我们一般保证数据的最终一致性,可以通过Canal框架监听mysql的binlog日志,把删除数据的动作放到客户端去做,如果删除失败就重试。

Redis数据结构

String类型的底层数据结构及实现原理?

          答:redis自定义了一个数据类型sds(simple dynamic string)简单的动态字符串,通过动态扩容机制减少内存浪费,也就是用存储的业务数据长度判断用什么方法存储;Stirng是由多个sdshdr5、sdshdr8、sdshdr16、sdshdr32等方法组成,每个方法中有len(长度)、char[]、flags组成,其中flags是由type(数据范围)和len(数据长度 )组成,flags是在真实数据往前偏移1个byte的位置;

List类型在redis中的实现?

        答:list是有序的数据结构,按照插入顺序排序,通过quicklist(双向链表)和ziplist实现的;ziplist是紧凑的结构有:zibytes(当前list的占用空间)、zitail(定位结尾数据的偏移量)、zllen(当前list中存储的个数)、zlend(当前list的结尾)、entry(prerawlen表示前面第一个元素,为0、len表示前面数据长度、data)主要存储数据;

                           

      其中quicklist(双向链表)是ziplist和linkedList的优化,通过head指向头部,通过tail指向尾部,每个quicklist(双向链表)中用quicklistNode包含一个ziplist,多个ziplist用双向指针串联起来;

                  
                  

        通过内存优化提供存取效率,在redis.conf文件中:1)list-max-ziplist-size  -2:设置ziplist最大容量;     2)list-compress-depth 0:压缩范围;

Hash类型在redis中的实现?

        答:hash的数据结构其实是dict(字典)是无序的,用key和value存储,当数据小时用ziplist存储,数据的大小和元素阈值可通过参数设置;

Redis怎么解决哈希冲突?

          答:首先hash会根据数组的长度求模,这时key会拿到数组的索引位置,hash有两个特点:1)相同的输入一定能得到相同的输出;2)不同的输入有可能得到相同的输出,也就是哈希冲突;redis通过链表法解决冲突,通过next指针指向原有的key,如果没有就是null;

Set和hset的区别?

         答:首先set和String中的命令,hset是hash中的命令,set可以通过expire设置过期时间而hset在单个filed不行,set每执行一次就会多一个key,造成内存消耗过高,而hset以hash散列表的形式存储比较节省内存;

Set类型在redis中的实现?

          答:set是无序的自动去重的集合类型,底层数据结构value是为null的dict(字典),当数据是整形时用intset存储(有序),否则用hashtable存储(无序);

Zset类型在redis中的实现?

           答:zset是有序的,优先根据score排序,score相同用元素字典排序,会自动去重,底层数据结构是用dict(字典)+skiplist(跳表)其中跳表的底层使用链表存的,数据少时用ziplist结构存储;

Redis支持的数据类型到跳跃表?

            答:zskiplist就是一个跳表,其中header 和 tail 指针分别指向表头和表尾节点,length 记录了节点数量,level 记录了所有节点中层级最高的节点的层级,表头节点的层高不计算在内,zskiplistNode是跳表的一个节点,每个节点的层级都是根据幂次定律(power law,越大的树出现的概率越小)随机生成的,它是1~32之间的一个数,作为level数组的大小;

Redis跳跃表?

 答:跳跃表(skiplist)是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点。Redis只在两个地方用到了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构;

 Redis的命令

Redis中mset(批量)和set(单次)操作的区别是什么?

          答:第一是命令有却别,单次用set插入,用get获取数据,批量用mset插入,mget批量获取;第二是IO,每次操作会产生rasp协议,转成tcp,最后转成IP,如果是单次的话会重复以上操作,造成IO浪费,而批量只会损失一次即可;

redis中的常用的命令有哪些?

 答:redisCommand数据结构存储着redis命令,其中负数代表至少有多少个参数,整数代表只能有两个;特殊:flushdb:清空数据库;String类型的命令有:1)type key:查看key的类型都是String;2)object encoding key:查看key在redis底层的实际存储类型;3)Incr key:对key进行递增或递减;4)strlen key:获取val的长度;5)help @string:查看String操作命令; 6)mset:批量插入数据;7)mget:批量查询数据;8)append key:字符串追加值;9)strlen key:查看长度; list类型的命令有:1)help @list:查看操作命令;2)lpush key:从左插入(入队列);3)lrange key 0 -1:从左获取所有数据;4)lpop key:从左查数据(出队列);5)rpush key:从右插入(入队列);6)rpop key:从右查数据(出队列);7)ltrim key 0 3:删除不是0到3的数据; 8)blpop key 秒:阻塞队列;  hash类型的命令有: 1)help @hash:查看操作命令;2)hset:插入数据;set类型命令有: 1)help @set:查看操作命令;2)sadd key:插入数据;3)smembers key:查询数据; zset类型命令有:1)help @sorted_set:查看操作命令;

Redis中mset(批量)和set(单次)操作的区别是什么?

 答:第一是命令有却别,单次用set插入,用get获取数据,批量用mset插入,mget批量获取;第二是IO,每次操作会产生rasp协议,转成tcp,最后转成IP,如果是单次的话会重复以上 操作,造成IO浪费,而批量只会损失一次即可;

热KEY重建有什么风险,如何优化?

答:设置的缓存过期了,有大量的请求访问同一个key,缓存失效的话可能会有大量的线程重建,造成数据库压力比较大;解决办法:1)通过集群方式分发缓解;2)服务端先将请求本地缓存;3)通过多级请求,层层过滤key缓解;

Redis中大key(bigkey)解决办法?

答:存在的问题:1)读写bigkey会导致超时严重,甚至阻塞服务;2)大key相关的删除或者自动过期时,会出现qps突降或者突升的情况,极端情况下,会造成主从复制异常,Redis服务阻塞无法响应请求;3)占用资源;解决办法:1)将大key分拆成多个key,value用multiGet获取值,将操作压力平摊到多个redis实例中,降低对单个redis的IO影响;2)将分拆的key,value用hash存储,用hget,hmget来获取部分的value,使用hset,hmset来更新部分属性;3)按照存储元素进行规则分类,分散存储到多个redis实例中;4)可以利用pipeline管道,一次发送多个命令,无需等待服务端返回;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值