首页 > 编程知识 正文

redis常见的面试题,redis面试官常问

时间:2023-05-03 21:26:10 阅读:202495 作者:3539

Redis 有哪些数据类型 String字符串:可以是字符串,整数或者浮点数,整数和浮点数可执行自增操作:incr key,整数自增可以用来实现全局唯一id的生成。String是最常用的一种类型,以key-value形式存在于内存中。List列表:底层采用链表或者ziplist实现,里面的元素可重复。可以用来存储一些按时间顺序的消息显示.Set集合:底层采用hashtable或者intset实现。不能有重复元素。可用来执行交集,并集,差集等。可用来实现获得共同好友等功能Zset有序集合:底层采用ziplist或者skiplist来实现。集合内元素有序且无重复,由于集合内元素带有权重属性,可用来实现排行榜等功能。Hash散列:底层采用ziplist或者hashtable实现。可以用来存储复杂对象。

详见:redis设计与实现读书笔记——底层数据结构

Redis 持久化机制 RDB:RDB持久化既可以手动执行也可以根据服务器配置选项定期执行,手动执行有两种命令:BGSAVE:派生出一个子进程,然后由子进程负责创建RDB文件,父进程继续处理命令请求。SAVE:阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求

自动间隔性保存配置,若提供以下配置:

Save 900 1

Save 300 10

Save 60 1000

只要满足以下三个条件中的任意一个,BGSAVE命令就会被执行:

服务器在900秒之内,至少执行了一次修改;服务器在300秒之内至少执行了10次修改,服务器在60秒之内至少进行了1000次修改。

原理:服务器状态的数据结构中保存了dirty(距离上一次成功执行SAVE或者BGSAVE命令后,服务器对数据库状态进行了几次更改),lastsave(记录上次成功执行SAVE或BGSAVE命令的时间),每100ms统计一次currenttime-lastsave和dirty大小,如果同时满足条件之一,则执行BGSAVE命令。

AOF:通过保存Redis服务器所执行的写命令来记录数据库状态。

服务器每次结束一个事件循环之前都会调用flushAppendOnlyFile函数,考虑是否需要将aof_buf缓冲区中的内容写入和保存到AOF文件中,其行为取决于appendfsync:

Always:将aof_buf缓冲区中的所有内容写入并同步AOF文件No:将aof_buf缓冲区中的所有内容写入AOF文件,不进行同步操作,何时同步由操作系统来决定。Everysec:将aof_buf缓冲区中的所有内容写入AOF文件,如果上次同步AOF文件的时间距离现在超过1s,则对其进行同步Redis 为什么是单线程的

 Redis客户端对服务端的每次调用都经过了服务端接收客户端命令-执行命令-返回结果三个过程,redis的单线程指的是执行命令过程使用单个线程执行。多个客户端并发请求执行的命令会被放在队列里依次执行。因为CPU不是redis的瓶颈,由于redis命令基本都是纯内存操作,每个命令都执行的很快,单线程实现简单且避免了线程切换和竞态的消耗,所以选择了单线程实现。如果CPU成为redis瓶颈了,可以使用多开几个redis进程搭建集群。

使用缓存的合理性问题 缓存雪崩:redis服务器出现故障,所有请求到达数据库层,数据库崩溃。缓存穿透:伪造请求恶意攻击缓存,即发送大量请求查找不存在于缓存种的数据,缓存被穿透就会访问数据库,会对数据库造成很大压力甚至崩溃。解决方案:将不存在的数据也缓存起来或者使用布隆过滤器过滤恶意请求。缓存预热:redis服务器开机时,直接加载热点数据。缓存更新:数据库被更新时,缓存需要被同步更新缓存降级:为了防止redis服务器出现故障时,数据库跟着崩溃。如果无法通过redis获得请求数据,直接返回默认数据而不请求数据库。热点数据才有必要被缓存对每个键设置失效时间经常修改的数据不应该被放入缓存Redis常见的回收策略

Redis数据量达到设定的最大内存时,需要驱逐数据,有以下6种策略。

Noeviction:不删除策略,如果存达到使用上线,则报错Allkeys-lru:对所有的key,使用lru算法回收最近最少使用的键。Volatile-lru:对设置了过期时间的key,使用lru算法回收最近最少使用的键。Allkeys-random:对所有key,随机回收部分keyVolatile-lru:对设置了过期时间的key,随机回收部分keyVolatile-ttl:对设置了过期时间的key,回收剩余存活时间最短的key

对于volatile-*策略,如果数据库种没有设置过期时间的key,则基本与noevinction策略相同。

Redis过期策略是怎么实现的呢 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。对内存友好,对CPU不友好。通过无序链表维护时间事件,遍历链表寻找到期的时间事件,执行删除键操作惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;否则,返回该键。对cpu友好,对内存不友好。定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。设置每次检查的数据库数量n和每个数据库检查的键数量k,数据库通过遍历方式访问,访问到当前数据库时,每次随机抽取一个键,如果过期则删除,共抽取k次,然后访问下一个数据库。若过程中达到了时间上限,则停止删除,下次再从停止的数据库开始。Redis集群方案与实现

redis官方的redis-cluster:使用hash slot方式,将16348个hash slot 覆盖到所有节点上。对于存储的每个key值,使用CRC16(KEY)&16348=slot得到他对应的hash slot。在访问key时就去找他的hash slot在哪一个节点上,然后由当前访问节点从实际被分配了这个hash slot的节点去取数据。节点之间使用轻量协议通信,减少带宽占用,性能很高,自动实现负载均衡与高可用,自动实现failover  并且支持动态扩展。官方已经玩到可以1000个节点 实现的复杂度低。

由于redis选举机制,每个redis集群至少需要三个主节点;要保证集群的高可用,每个主节点都至少需要配备一个从节点。所以一共至少需要6个节点。

将一个节点加入集群:CLUSTER MEET <ip> <port>

将槽指派给节点负责:CLUSTER ADDSLOTS <slot> [slot…]

当客户端向节点发送与数据库键有关的命令时,接收命令的节点会计算出命令要处理的数据库属于哪个槽,并检查这个槽是否指派给了自己:如果键所在的槽刚好指派给当前节点,那么节点直接执行这个命令;否则,节点向客户端返回一个MOVED错误,指引客户端转向正确的节点,并再次发送之前想要执行的命令。

详见:redis设计与实现读书笔记——集群

Redis复制的过程

复制分为同步和命令传播两个操作:同步操作用于将从服务器的数据库状态更改至主服务器当前所处的数据库状态;命令传播操作则用于在主服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态。

同步:客户端向从服务器发送SALVEOF命令要求从服务器复制主服务器时,从服务器首先需要执行同步操作。从服务器向主服务器发送SYNC命令。收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有命令。当主服务的BGSAVE命令执行完毕时,主服务器会将BG命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库更新至主服务器当前的状态。命令传播:主服务器将收到的写命令传播给从服务器。

详见:redis设计与实现读书笔记——复制

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。