问题、项目用Redis的原因是什么?
传统的关系型数据库已经不能适用所有的场景。
问题、请您描述下Redis和Memcached的区别。
(1)Redis的数据结构比Memcached多。
(2)Redis的执行速度比Memcached快。
(3)Redis支持数据持久化。
问题、请您说下Redis执行速度快的原因。
(1)基于内存。
(2)数据结构简单,数据操作也简单。
(3)采用单线程,不存在上下文切换对CPU的消耗,也不用考虑锁的问题。
(4)使用多路复用IO。
问题、Redis是单线程的,现在服务器是多核的,该怎么样资源利用最大化?
单机开多个Redis实例。
问题、请你说下Redis有哪些数据结构及其使用场景。
String(共享用户session)、Hash(存储用户信息)、List(异步消息队列)、Set(存储标签)、SortedSet(排行榜)、bitmap(用户签到)、HyperLogLog(UV统计)、Geo(附近的人)、Pub/Sub(消息多播)、BloomFilter(布隆过滤器)
问题、请简单描述什么是缓存雪崩,什么是缓存穿透,什么是缓存击穿,碰到问题该怎么解决?
缓存雪崩是指缓存的数据集体失效,导致原本应该访问缓存的请求都去查询数据库而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。
缓存雪崩的解决方案有三个:
(1)考虑用加锁或者队列,防止大量线程对数据库进行读写。
(2)分析用户行为,尽量让缓存失效的时间均匀分布,最次也得随机分布。
(3)使用二级缓存,当原始缓存失效时,可以访问备份缓存。
缓存穿透是指查找一个一定不存在的数据,因为不存在,所以没有缓存,导致每次都到数据库去查询,给数据库造成压力。
缓存穿透的解决方案有两个:
(1)使用布隆过滤器。
(2)将空对象记录在缓存中。
缓存击穿是指查找的数据在缓存中失效了,只能到数据库去查询,造成数据库压力倍增。
缓存击穿的解决方案有两个:
(1)考虑用加锁或者队列,防止大量线程对数据库进行读写。
(2)过期时间无限调长。
问题、您使用过Redis分布式锁么,它是怎么一回事。
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
问题、setnx指令和expire指令之间进程意外crash,该怎么解决?
Redis 2.8版本对set指令做了参数扩充,可解决该问题。
问题、假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如何将它们全部找出来?
使用keys指令。
问题、如果这个Redis正在给线上的业务提供服务,那使用keys指令会有什么问题,该怎么解决?
Redis是单进程单线程的,keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可了,但是整体所花费的时间会比直接用keys指令长。
问题、使用过Redis做异步队列么,你是怎么用的?
List结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会重试。
问题、那除了使用sleep之外,你还有别的办法么?
List还有个指令叫blpop,在没有消息的时候,它会阻塞直到消息到来。
问题、上面说的是一对一的场景,那一对多你又该如何解决呢?
使用pub/sub主题订阅者模式,可以实现一对多的消息队列。
问题、pub/sub有什么缺点?
在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如RabbitMQ等。
问题、Redis怎么实现延时队列?
使用sortedset,拿时间戳作为score,消息内容作为value,调用zadd来生产消息。消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。
问题、Redis是怎么做持久化的?
RDB做镜像全量持久化,AOF做增量持久化。因为RDB会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要AOF来配合使用。在Redis实例重启时,会使用RDB持久化文件重新构建内存,在使用AOF重放近期的操作指令来实现完整恢复重启之前的状态。
问题、如果机器突然掉电会出现什么问题?
取决于AOF日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下硬盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。
问题、请说下RDB的原理是什么?
Fork和Cow。Fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
问题、RDB和AOF的区别是什么?
RDB持久化:在指定的时间间隔内将内存中的数据集快照写入磁盘。
AOF持久化:以日志的形式记录服务器所处理的每一个增删改操作。
问题、RDB和AOF各自的优缺点是什么?
RDB优点
(1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备。
(2)RDB对redis对外提供读写服务的时候,影响非常小,因为redis 主进程只需要fork一个子进程出来,让子进程对磁盘io来进行rdb持久化。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
RDB缺点
(1)如果redis要故障时要尽可能少的丢失数据,RDB没有AOF好,例如1:00进行的快照,在1:10又要进行快照的时候宕机了,这个时候就会丢失10分钟的数据。
(2)RDB每次fork出子进程来执行RDB快照生成文件时,如果文件特别大,可能会导致客户端提供服务暂停数毫秒或者几秒。
AOF的优点
(1)AOF可以更好的保护数据不丢失,一般AOF会以每隔1秒,通过后台的一个线程去执行一次fsync操作,如果redis进程挂掉,最多丢失1秒的数据。
(2)AOF以appen-only的模式写入,所以没有任何磁盘寻址的开销,写入性能非常高。
(3)AOF日志文件的命令通过非常可读的方式进行记录,这个非常适合做灾难性的误删除紧急恢复,如果某人不小心用flushall命令清空了所有数据,只要这个时候还没有执行rewrite,那么就可以将日志文件中的flushall删除,进行恢复。
AOF的缺点
(1)对于同一份文件AOF文件比RDB数据快照要大。
(2)AOF开启后支持写的QPS会比RDB支持的写的QPS低,因为AOF一般会配置成每秒fsync操作,每秒的fsync操作还是很高的。
(3)数据恢复比较慢,不适合做冷备。
问题、pipeline有什么好处,为什么要用pipeline?
可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。
问题、Redis的同步机制了解么?
Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将RDB文件全量同步到复制节点,复制节点接受完成后将RDB镜像加载到内存。加载完成后,在通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。后续的增量数据通过AOF日志同步即可,有点类似数据库的binlog。
问题、请说下redis的过期删除策略。
redis 对过期的缓存数据采用定期删除+惰性删除的策略。
所谓定期删除,指的是 redis 每隔一段时间(默认100ms)就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。
所谓惰性删除,指的是在获取某个 key 的时候,redis 会检查其是否设置了过期时间,是否过期,如果设置了过期时间且已过期,redis 就会删除且不会返回任何数据。
问题、MySQL里有2000w数据,Redis中只存20w的数据,如何保证Redis中的数据都是热点数据?
redis 的内存占用过多时会进行内存淘汰,有六大淘汰机制:
(1)noeviction:当内存不足以容纳新写入数据时,新写入操作会报错;
(2)allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(推荐);
(3)allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key;
(4)volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key;
(5)volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key;
(6)volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,谁的过期时间早谁就优先移除;
问题、说说Redis哈希槽的概念?
Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽。