Redis面试题
1.redis基本数据类型及常用客户端命令
string、list、set、zset、hash。相关指令见 redis常用客户端命令
2.redis过期key删除策略
Redis中过期key的删除策略,分为三种:定时删除、定期删除、惰性删除。其中,定时删除和定期删除是主动删除策略,惰性删除是被动删除策略。 1、定时删除 定时删除是在设置key的过期时间的同时,会创建一个定时器(timer)。定时器在key的过期时间来临时,立即执行对key的删除操作。缺点是消耗CPU,基本不使用 2、定期删除 定期删除是每隔一段时间,程序就会对Redis数据进行一次检查,删除里面的一定数量的过期key,通过定期删除策略,可以有效地减少因为过期key而带来的内存浪费。 3、惰性删除 惰性删除是是每次获取key时,都会检查取得的key是否过期,如果过期,则删除该key;若没有过期,就返回该key的值。缺点是对内存是最不友好的。如果一个key已经过期,而这个key又仍然保留在db中,那么只要这个过期key不被删除,它所占用的内存就不会释放。
3.redis数据淘汰策略
voltile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰 allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰 allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰 no-enviction(驱逐):禁止驱逐数据
4.redis持久化
1.RDB持久化 根据时间的间隔将redis中数据快照(dump)到dump.rdb文件。优势 :备份恢复简单。RDB通过子进程完成持久化工作,相对比AOF启动效率高;劣势 :服务器故障会丢失几分钟内的数据 2.AOF持久化 以日志的形式记录所有更新操作到AOF日志文件,在redis服务重新启动时会读取该日志文 件来重新构建数据库,以保证启动后数据完整性。劣势:日志文件相对RDB快照文件要大的多 AOF日志重写功能 :AOF日志文件过大,redis会自动重写AOF日志,append模式不断的将更新记录写入到老日志文件中,同时redis还会创建一个新的日志文件用于追加后续的记录。
5.redis事务
见 redis事务
6.redis单线程模型原理
Redis基于Reactor模式开发了自己的网络事件处理器,称之为文件事件处理器(File Event Hanlder)。文件事件处理器由Socket、IO多路复用程序、文件事件分派器(dispather),事件处理器(handler)四部分组成。 IO多路复用程序会同时监听多个socket,当被监听的socket准备好执行accept、read、write、close等操作时,与这些操作相对应的文件事件就会产生。 IO多路复用程序会把所有产生事件的socket压入一个队列中,然后有序地每次仅一个socket的方式传送给文件事件分派器,文件事件分派器接收到socket之后会根据socket产生的事件类型调用对应的事件处理器进行处理。 Redis采用非阻塞式IO,在读写 IO 时可以不必再阻塞了,读写可以瞬间完成 Redis的多路 I/O 复用模型是利用epoll可以同时监察多个流的 I/O 事件的能力,只轮询那些真正发出了事件的流,并利用mmap()文件映射内存加速与内核空间的消息传递,减少内存复制开销
7.redis集群
见 redis集群
1.主从复制 a.从服务器->主服务器,发送SYNC命令; b.主服务器: 生成RDB文件并使用缓冲区记录此后执行的所有写命令; c.主服务器->从服务器,发送快照文件,并在发送期间继续记录被执行的写命令; d.从服务器: 丢弃所有旧数据,载入收到的快照; e.主服务器->从服务器,发送缓冲区中的写命令; f.从服务器: 执行来自主服务器缓冲区的写命令; g.主服务器->从服务器,每执行一个写命令就会向从服务器发送相同的写命令 2.哨兵模式 a.监控主服务器和从服务器是否正常运行 b.主服务器出现故障时自动将从服务器转换为主服务器 3.Cluster模式 需要将每个数据库节点的cluster-enable配置打开即可。每个集群中至少需要三个主数据库才能正常运行。 a.所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。 b.客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
8.redis管道
Redis 管道技术可以在服务端未响应时,客户端可以持续向服务端发送请求(当 client 使用 pipelining 发送命令时,redis server 必须将部分请求放到队列中),并最终一次性读取所有服务端的响应。
9.假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
答:使用keys指令可以扫出指定模式的key列表。
问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
答:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。
这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。。
10.缓存雪崩和缓存穿透问题解决方案
缓存雪崩:缓存同一时间大面积的失效 缓存穿透:请求缓存中不存在的数据 解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
11.Redis相比memcached有哪些优势
1.memcached所有的值均是简单的字符串,Redis作为其替代者,支持更为丰富的数据类型 2.Redis的速度比memcached快很多 3.Redis可以持久化其数据 4.Redis支持数据的备份,即master-slave模式的数据备份。
12.redis分布式锁
1.setnx『SET if Not eXists』 命令在设置成功时返回 1 ,设置失败时返回 0 。对于判断加锁成功的线程, 再加expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS)过期时间,防止异常导致锁未释放 2.Redisson redis命令通过封装在lua脚本中发送给redis,保证业务逻辑执行的原子性。 只要客户端加锁成功,就会启动一个watch dog看门狗,他是一个后台线程,会每隔10秒检查一下,如果客户端还持有锁key,那么就会不断的延长锁key的生存时间。
最大缺陷:在redis master实例宕机的时候,可能导致多个客户端同时完成加锁。
13.数据结构原理
字符串(String) redis设计了一种简单动态字符串(SDS[Simple Dynamic String])作为底实现。此对象中包含三个属性: 1.len buf中已经占有的长度(表示此字符串的实际长度) 2.free buf中未使用的缓冲区长度 3.buf[] 实际保存字符串数据的地方 列表(List) 在3.2版本之前,列表是使用ziplist和linkedlist实现的,在这些老版本中,当列表对象同时满足以下两个条件时,列表对象使用ziplist编码: 1.列表对象保存的所有字符串元素的长度都小于64字节 2.列表对象保存的元素数量小于512个 当有任一条件 不满足时将会进行一次转码,使用linkedlist。 而在3.2版本之后,重新引入了一个quicklist的数据结构,列表的底层都是由quicklist实现的,它结合了ziplist和linkedlist的优点。 ziplist的结构:ziplist充分体现了Redis对于存储效率的追求。ziplist却是将表中每一项存放在前后连续的地址空间内,一个ziplist整体占用一大块内存。它是一个表(list),但其实不是一个链表(linked list)。 linkedlist的结构:意思为一个双向链表,和普通的链表定义相同,每个entry包含向前向后的指针,当插入或删除元素的时候,只需要对此元素前后指针操作即可。 quicklist的结构:双向链表结构,和普通的链表操作一样,插入删除效率很高,但查询的效率却是O(n)。每个quicklist节点就是一个ziplist,具备压缩列表的特性。 哈希(hash) hash底层的数据结构实现有两种: 一种是ziplist,上面已经提到过。当存储的数据超过配置的阀值时就是转用hashtable的结构。同时满足以下两个条件时才会使用这种结构: 1.当键的个数小于hash-max-ziplist-entries(默认512) 2.当所有值都小于hash-max-ziplist-value(默认64) 另一种就是hashtable。这种结构的时间复杂度为O(1),但是会消耗比较多的内存空间。 集合(Set) 列表可以存储多个相同的字符串,而集合则通过使用散列表(hashtable)来保证自已存储的每个字符串都是各不相同的(这些散列表只有键,但没有与键相关联的值) 有序集合(zset) 有序集合和散列一样,都用于存储键值对:有序集合的键被称为成员(member),每个成员都是各不相同的。有序集合的值则被称为分值(score),分值必须为浮点数。它的存储方式也有两种: 1.ziplist结构:与上面的hash中的ziplist类似,member和score顺序存放并按score的顺序排列 2.skiplist与dict的结合: skiplist是一种跳跃表结构,用于有序集合中快速查找,大多数情况下它的效率与平衡树差不多,但比平衡树实现简单。
14.redis分片算法(腾讯面试内容)
见 redis集群
redis cluster有固定的16384个hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot。 redis cluster中每个master都会持有部分slot,比如有3个master,那么可能每个master持有5000多个hash slot。 hash slot让node的增加和移除很简单,增加一个master,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去。移动hash slot的成本是非常低的