java八股之redis面试题

您所在的位置:网站首页 redis面试题大全 java八股之redis面试题

java八股之redis面试题

#java八股之redis面试题| 来源: 网络整理| 查看: 265

目录

1、redis是单线程还是多线程

2、Redis为什么那么快

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

4、Redis Key过期了为什么内存没释放(附删除策略)

5、Redis没设置key的过期时间,为什么被Redis主动删除了

(淘汰策略)

6、Redis主从、哨兵、集群架构优缺点比较

7、Redis集群数据分片

8、Redis主从切换导致缓存雪崩

9、Redis持久化 RDB、AOF和混合持久化

AOF

4.0以后的混合模式持久化

10、Redis主从复制原理

全量拷贝:

增量拷贝:

1、redis是单线程还是多线程

答:分版本

在redis6.0之前是单线程,这里的单线程指的是网络I/O和键值对读写是由一个线程完成的。

在redis6.0之后,引入了多线程这个概念,这个多线程是网络I/O的多线程,而键值对读写还是单线程完成的,所以redis依然是并发安全的。

补充一下:这里的单线程是指网络请求和数据操作,而其他的持久化和集群数据同步等,其实是由额外的线程执行的

2、Redis为什么那么快

答:我们都知道Redis是基于内存的。

一条命令在内存里操作的时间是几十纳秒

命令执行是单线程操作,没有线程切换开销

基于IO多路复用机制提升了Redis的I/O利用率

高效的数据存储结构:全局hash表以及多种高效数据结构,比如:跳表,压缩列表,链表等等。

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

答:我们都知道Redis有一个有序集合zset里面是用元素:分值 ,它的底层可以用压缩列表O(N)和跳表O(logN)来存储,今天我们就讲讲跳表。

我们这样理解 一开始我们会把这个集合放到一个链表里面来,链表会按照我们每个元素的分值进行从小到大排序。我们也知道一个链表特性就是插入删除快,查询慢。但是这个有序集合在底层给我们做了优化。就是进行横向扩张什么意思呢?

a:3

e:7

i:11a:3c:5e:7g:9i:11a:3b:4c:5d:6e:7f:8g:9h:10i:11

如图上最下面一行是我们的链表,在这个基础上,当前元素指向下两个元素。并且那个元素指向自己的下方元素。找元素假设找f:8这个元素 那么会从最上层找,找到e:7后找i:11发现小于i:11这时候e:7就往下一层继续从e:7出发查找,发现小于g:9这时候e:7继续往下一层,再next的时候就找到了f:8这个元素了。

跳表:将有序链表改造为支持近似“折半查找”算法,可以进行快速的插入、删除、查找操作。

4、Redis Key过期了为什么内存没释放(附删除策略)

在我们使用set命令的时候除了可以设置key-value以外 还可以设置key的过期时间,就像这样

set minus 123 ex 60

这时候我们如果执行这个操作

set minus 456

那么这个key的过期时间就会被擦除掉,这时候我们ttl minus 返回的就是-1(永不过期)

如果我们设置了过期时间但是Redis内存持续增长,后面发现过期时间丢失,那么很有可能就是问题造成的了。

当然还有可能就是惰性删除、定期删除和定时删除

1、惰性删除:读/写到一个已经过期的key,就会触发惰性删除,如果过期了就会删除这个key

优点:节约cpu性能,到了必须删除的时候才执行删除。

缺点:内存压力较大,会出现长期占用内存的数据(冷数据)。

空间换时间

2、定时删除:惰性删除无法保证冷数据被及时删除,所以我们可以设置Redis定时器,当key设置有过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作。

优点:节省内存,到时间就删除,快速释放不必要的内存占用。

缺点:CPU压力较大,无论CPU此时负载情况如何,均占用CPU来执行删除,会影响Redis服务器的响应时间和指令吞吐量。

时间换空间

3、定期删除:

Redis服务器初始化 读写配置中的server.hz,默认为10 代表每10秒执行一次sereverCron()操作在serverCron()中会调用databasesCron()来轮询每一个db(即循环expire[*])。在databasesCron()中会调用activeExpireCycle()方法,对每一个expire[*]进行检测,每次执行的时长为250ms/server.hz。对某个expire[*]检测时,随机挑选W个key进行检测。如果key超时,即删除。如果第四步中,删除的key的数量大于W*25%,则继续在此expire[*]上检测执行。如果第四步中删除的key的数量小于等于W*25%,则检测下一个expire[*]。(从0-15循环,Redis默认为16个DB)

其中W值,可以在配置文件中配置,对应的属性为ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 默认20;

​ 在第四步中的activeExpireCycle()方法执行检测的时候,因为时间长度时固定的,下一次activeExpireCycle()方法执行为了接着上一次中断的位置执行,用参数current_db来记录当前检测的expire。

特点:对cpu的使用有峰值,也有一定的自定义空间。删除过程中,内存的压力也不是很大。

Reids采用的是 惰性删除+定期删除

 文章参考:(90条消息) Redis删除策略_shui2104的博客-CSDN博客_redis删除策略

5、Redis没设置key的过期时间,为什么被Redis主动删除了 (淘汰策略)

当redis的内存超过了maxmemory( 不设置为0)限定时,触发主动清理策略

主动清理策略在redis4.0之前一共实现了6种内存淘汰策略,在4.0之后,又增加了2种策略 一共8种:

1)针对过期key的处理:

volatile-ttl: 过期时间的键值对 先后删除,越早过期越先被删。

volatile-random:过期时间的键值对随机删除。

volatile-lru:过期时间的键值对 淘汰最长时间未被使用的。

(新)volatile-lfu:过期时间的键值对 淘汰一定时期内被访问次数最少。

2)针对所有key的处理

allkeys-random: 所有键值对 随机删除。

allkeys-lru: 所有键值对 淘汰最长时间未被使用的。

(新)allkeys-lfu: 所有键值对 淘汰一定时期内被访问次数最少。

3)不处理

noeviction: 不会剔除任何数据,拒绝写入并且返回OOM异常(默认)

6、Redis主从、哨兵、集群架构优缺点比较

主从架构:

单个主 master节点进行操作,多个从 slave进行备份

如果主节点挂了,就需要运维人员到从节点选一台机器当作主节点。

哨兵架构:

有主从的基础上,再增加上一些哨兵sentinel节点(同主 从一样都是redis的一个实例),

每一个哨兵都会对redis主从节点进行监听。客户端是通过哨兵集群来知道主节点信息的。

这时候如果主节点挂掉了,哨兵会到从节点里面挑选一台机器当主节点(这里不赘述选举过程)

并且告诉给客户端新的主节点。

集群架构:

在集群架构,比如我们有100G的数据,我们有三个集群,那么它的存储不是每个节点都100G数据的,而是 30G、30G、40G分别存储,也就是说水平拆分数据。那怎么分片的呢?

7、Redis集群数据分片

我们要知道,Redis Cluster启动的时候,会分配16384个哈希solt(槽位),每个节点负责其中一部分的solt,solt的信息存储于每个节点。

那怎么确定存在哪个solt呢?

HASH_SOLT=CRC16(key) mod 16384

8、Redis主从切换导致缓存雪崩

假设slave机器时钟走的比master快很多。

此时,Redis master里设置了过期时间的key,从slave角度来看,可能会有很多在master里没过期的数据,其实在slave里面已经过期了。

如果这时候主从切换,把slave切换为新的master

它在成为master后,就会开始大量清理过期key(slave不会清理过期的key),这时候就会导致:

1、master大量清理key,导致主线程阻塞,无法及时处理客户端请求。

2、Redis中大量数据过期,引发缓存雪崩。

所有我们一定要保证主从的机器时钟一致性,避免这种问题发生。

9、Redis持久化 RDB、AOF和混合持久化

默认情况下是RDB快照的

Redis在RDB情况下,会把内存数据库快照保存在dump.rdb的二进制文件。

我们可以对Redis进行设置,让它在X秒内数据集至少有Y个改动 满足时,自动保存一次数据集。

比如:Redis在60秒内有1000个key改动,自动保存一次数据集。

# save 60 1000 #关闭RDB只需要将所有的save保存策略注释掉即可

优点:恢复速度快、体积小  缺点:可能丢失数据

还可以手动执行命令生成RDB快照,Redis客户端通过 save 或 bgsave 可以生成 dump.rdb 文件

save:同步IO 会阻塞客户端

bgsave:异步IO 不会阻塞客户端 后台进行写时复制(fork子线程)

AOF

        appendonly yes 开启AOF 写入到.aof文件

AOF可以配置几种策略:

appendfsync always 写一条马上持久化一条

appendfsync everysec 可以设置多久执行一次,

appendfsync no 操作系统来处理

优点:丢失极少数据  缺点:恢复速度慢 体积大

AOF重写优化:可能出现set a 1,set a 2 ,set a 3这样的操作,但是最后我们只需要set a 3

我们可以来控制AOF自动重写频率

#auto-aof-rewrite-min-size 64mb  //aof文件至少到64mb才会自动重写

#auto-aof-rewrite-percentage 100  //aof自上一次重写后 增长了100% 再次重写

bgrewriteaof 重写aof命令

恢复数据默认用aof恢复

4.0以后的混合模式持久化

#aof-use-rdb-preamble yes                #开启混合持久化(必须先开启AOF才能使用)

我们在aof重写时,会把重写这一刻之前的命令变成rdb快照处理(二进制),并且把重写过程中的命令以aof的内容和rdb的内容存一起变为新文件,在重写写入期间新文件名称不叫 appendonly.aof 直到写入完毕就会覆盖掉原来的aof文件,于是Redis重启的时候,可以先加载RDB的内容,然后再aof重写。

10、Redis主从复制原理

通过slaveof命令或者设置slaveof选项,让一个服务器去复制另一个服务器的数据。

全量拷贝:

1、主节点通过bgsave来fork出一个子进程来进行RDB持久化,这个过程是非常消耗CPU、 内存(页表复制)、硬盘IO的

2、主节点通过网络将RDB文件发送给从节点,对主从节点的带宽都会带来很大的消耗

3、从节点清空老数据,载入新RDB文件的过程是阻塞的,无法响应客户端的命令,如果从节点执行bgrewriteaof,还会带来额外的消耗

增量拷贝:

1、复制偏移量:执行复制的双方、主从节点、分别会维护一个偏移量offset

2、复制积压缓冲区:主节点内部维护一个固定长度的、先进先出的队列作为复制积压缓冲区,当主从节点offset的差距过大,超过缓冲区长度时,将无法增量拷贝,只能全量拷贝。

3、服务器运行ID(runid):每个Redis节点在运行的时候都会生成一个runid,主节点会把自己的runid发送给其他从节点,从节点会将主节点的runid存起来,从节点重连时,会根据runid判断同步进度

        如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会继续尝试使用增量拷贝(看offset差距是否超过了缓冲区长度)

        如果从节点保存的runid与主节点现在的runid不同(主节点被换成了其他节点),只能进行全量拷贝。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3