互联网Java面试-Redis篇
1、为什么要使用Redis?
高性能、高并发
2、Redis 与其他 key - value 缓存产品有以下三个特点
Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等数据结构的存储。
Redis 支持数据的备份,即 master-slave 模式的数据备份。
3.什么是缓存穿透?什么是缓存雪崩?
缓存穿透
按照 key 去缓存查询,如果不存在对应的 value,就应该去数据库查找。一些恶意的请求会故意查询不存在的 key,就会压垮数据库。
如何避免?
1:对查询结果为空的情况也进行缓存,缓存时间设置短一点
2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。
缓存雪崩
当缓存服务器崩溃的时候,压垮数据库。
如何避免?
事前:redis高可用,避免全盘崩溃
事中:本地ehcache缓存+hystrix限流&降级
事后:redis持久化,快速恢复缓存数据
4、Redis 的数据类型?
答:Redis 支持五种数据类型:string(字符串),hash(哈希),list(列表),
set(集合)及 zset(sorted set:有序集合)。
5、使用 Redis 有哪些好处?
1、速度快,因为数据存在内存中,类似于 HashMap
2、支持丰富数据类型,支持 string,list,set,Zset,hash 等
3、支持事务,操作都是原子性
4、丰富的特性:可用于缓存,消息,按 key 设置过期时间,过期后将会自动删除
6、Redis 相比 Memcached 有哪些优势?
1、Memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类
2、Redis 的速度比 Memcached 快
3、Redis 可以持久化其数据
7、Redis 是单进程单线程的?
答:Redis 是单进程单线程的,redis 利用IO多路复用技术和队列技术将并发访问变为串行访问。
8、一个字符串类型的值能存储最大容量是多少?
答:512M
9、Redis 的持久化机制是什么?各自的优缺点?
Redis 提供两种持久化机制 RDB 和 AOF 机制:
1、RDB(Redis DataBase)持久化方式:记录 redis 数据库的所有键值对,
2、AOFAppend-only file)持久化方式: 记录所有的命令日志
10、RDB(Redis DataBase)持久化方式的优缺点
优点:
1、只有一个文件 dump.rdb,方便持久化。
2、容灾性好,一个文件可以保存到安全的磁盘。
3、性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO最大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis的高性能。
4.相对于数据集大时,比 AOF 的数据恢复效率更高。
缺点:
数据安全性低。RDB 是间隔一段时间(5min)进行持久化,如果在下一次持久化之前 redis 发生故障,会发生数据丢失。
11、AOF(Append-only file)持久化方式的优缺点
优点:
1、数据安全,aof 持久化可以配置每进行一次命令操作就记录到 aof 文件中一次。
2、通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof工具解决数据一致性问题。
缺点:
AOF 文件比 RDB 文件大,且恢复速度慢且可能出错
12、redis 过期键的删除策略?
1、惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。
2、定期删除:每隔一段时间程序就对数据库进行一次检查,删除里面的过期键。
3、定时删除:在设置键的过期时间的同时,创建一个定时器(timer). 让定时器在键的过期时间来临时,立即执行对键的删除操作。
13、Redis 的回收策略(淘汰策略)?
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
no-enviction(驱逐):不淘汰任何数据,不可写入任何数据集(一般不用)
注意这里的 6 种机制,volatile 和 allkeys 规定了是对已设置过期时间的数据集淘汰数据还是从全部数据集淘汰数据,后面的 lru、ttl 以及 random 是三种不同的淘汰策略,再加上一种 no-enviction 永不回收的策略。
使用策略规则:
1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低,则使用 allkeys-lru
2、如果数据呈现平等分布,也就是所有的数据访问频率都相同,则使用allkeys-random
14、最近最少使用LRU 算法知道吗?写一下 java 代码实现?
//第三个参数置为 true,代表 linkedlist 按访问顺序排序,可作为 LRU 缓存;设为 false 代表按插入顺序排序,可作为 FIFO 缓存
LRU:new LinkedHashMap<K, V>(capacity, DEFAULT_LOAD_FACTORY, true);
15、为什么 redis 需要把所有数据放到内存中?
答:Redis 为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以 redis 具有快速和数据持久化的特征。
16、Redis 的持久化机制?
答:Redis 可以使用主从同步。第一次同步时,master节点做一次 bgsave,并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到slave节点,slave节点接受完成后将 rdb 镜像加载到内存。加载完成后,再通知master节点将期间修改的操作记录同步到slave节点进行重放就完成了同步过程。
17、Pipeline 有什么好处,为什么要用 pipeline?
pipeline允许客户端可以一次发送多条命令,而不等待上一条命令执行的结果,pipeline管道批量执行指令,可以节省多次IO往返的时间,但是如果指令间有依赖建议分批发送
18、是否使用过 Redis 集群,集群的原理是什么?
1)、哨兵模式Redis Sentinal着眼于高可用,在 master 宕机时会自动将 slave 提升为master,继续提供服务。
2)、集群模式Redis Cluster包含Redis Sentinal ,着眼于扩展性,在单个 redis 内存不足时,使用Cluster 进行分片存储(hash slot算法)。
19、Redis 集群方案什么情况下会导致整个集群不可用?
答:有 A,B,C 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了,
那么整个集群就会以为缺少 5501-11000 这个范围的槽而不可用。
20、Redis 支持的 Java 客户端都有哪些?
答:Redisson、Jedis、lettuce 等等,官方推荐使用 Redisson。
21、说说 Redis 哈希槽的概念?
答:Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有16384 个哈希槽,每个 key 对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
22、如何保证缓存和数据库双写一致性?
Cache Aside Pattern
(1)读的时候,先读缓存,缓存没有的话,那么就读数据库,然后取出数据后放入缓存,同时返回响应
(2)更新的时候,先删除缓存,然后再更新数据库
23、如何解决异步复制和脑裂导致的数据丢失?
min-slaves-to-write 1//至少跟一个slave进行通信
min-slaves-max-lag 10//异步复制延时不能超过10秒
(1)减少异步复制的数据丢失
有了min-slaves-max-lag这个配置,就可以确保,一旦slave复制数据和ack延时太长,就认为可能master宕机了,就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低到可控范围内
(2)减少脑裂的数据丢失
如果master出现了脑裂,不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那就直接拒绝客户端的写请求
24、Redis 集群之间是如何复制的?
答:异步复制
25、redis的主观宕机和客观宕机
sdown是主观宕机,就一个哨兵如果自己觉得一个master宕机了,那么就是主观宕机
odown是客观宕机,如果quorum数量的哨兵都觉得一个master宕机了,那么就是客观宕机
sdown达成的条件很简单,如果一个哨兵ping一个master,超过了is-master-down-after-milliseconds指定的毫秒数之后,就主观认为master宕机。
sdown到odown转换的条件很简单,如果一个哨兵在指定时间内,收到了quorum指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机
26、redis的slave->master选举算法
如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave来
会考虑slave的一些信息
(1)跟master断开连接的时长:如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master
(2)slave优先级:按照slave优先级进行排序,slave priority越低,优先级就越高
(3)复制offset:如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,offset越靠后,优先级就越高
(4)run id如果上面两个条件都相同,那么选择一个run id比较小的那个slave
27、redis cluster的通信协议
gossip协议包含多种消息,包括ping,pong,meet,fail,等等
meet: 某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信
ping: 每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据
pong: 返回ping和meet,包含自己的状态和其他信息,也可以用于信息广播和更新
fail: 某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点,指定的节点宕机了
28、怎么理解 Redis 事务?
1)事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
2)事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
29、Redis 事务相关的命令有哪几个?
1.MULTI用来组装一个事务;
2.EXEC用来执行一个事务;
3.DISCARD用来取消一个事务;
4.WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。
30、Redis key 的过期时间和永久有效分别怎么设置?
EXPIRE mykey 10
PERSIST mykey
31、Redis 如何做内存优化?
答:尽可能使用数据类型(hash),hash使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个hash里面。比如你的 web 系统中有一个用户对象,不要为这个用户的名称,姓氏,邮箱,密码设置单独的 key,而是应该把这个用户的所有信息存储到一个hash里面.
32、为什么Redis是单线程还可以支持高并发?
(1)纯内存操作
(2)核心是基于非阻塞的IO多路复用
(3)单线程反而避免了多线程的频繁上下文切换
33、都有哪些办法可以降低 Redis 的内存使用情况呢?
可以好好利用 Hash,list,sorted set,set等集合类型数据,因为通常情况下很多小的 Key-Value 可以用更紧凑的方式存放到一起。
34、一个 Redis 实例最多能存放多少的 keys?List、Set、Sorted Set 他们最多能存放多少元素?
理论上 Redis 可以处理多达2的32次方的 keys,实际每个实例至少存放了 2.5 亿的 keys。
任何 list、set、 和 sorted set 都可以放2的32次方个元素。
35、如何保证 redis 中的数据都是热点数据?
Redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。
36、Redis 最适合的场景?
1、会话缓存(Session Cache)、热点数据缓存
2、排行榜(zset)/计数器(INCR key)
37、假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以某个固定的已知的前缀开头的,如果将它们全部找出来?
keys 指令可以扫出指定模式的 key 列表(keys key1111*),但会导致线程阻塞一段时间,线上服务会停顿。
scan 指令可以无阻塞的提取出指定模式的 key 列表(scan 0 match key1111* count 20)
38、如果有大量的 key 需要设置同一时间过期,一般需要注意什么?
如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。
39、如果对方追问 redis 如何实现延时队列?
使用 sortedset,拿时间戳作为score,消息内容作为 key 调用 zadd 来生产消息,消费者用 zrangebyscore 指令获取 N 秒之前的数据轮询进行处理。