设为首页 加入收藏

TOP

Redis面试题(一)
2023-09-23 15:44:12 】 浏览:210
Tags:Redis

Redis到底是多线程还是单线程

Redis 6.0版本之前的单线程指的是其网络I/O和键值对的读写是由一个线程完成的。
多线程在Redis 6.0中的引入是为了改善一些特定场景下的性能问题,特别是在大型多核系统上。Redis 6.0引入了多个I/O线程这些线程负责处理网络事件的监听和接收。主线程仍然是单线程的,负责命令的执行和响应的返回
举个例子,假设有多个客户端同时向Redis发送请求,这些请求在网络上到达Redis服务器。主线程会监听这些网络事件,并将请求分发给空闲的I/O线程进行处理。每个I/O线程负责接收请求、解析命令,并将命令发送给主线程执行。主线程执行完命令后,将响应发送给对应的I/O线程,然后I/O线程将响应返回给客户端。而键值对读写命令仍然是单线程处理,所以Redis依然是并发安全的。
只有网络请求模块和数据操作模块式是单线程的,而其他的持久化、集群数据同步等,其实是由额外的线程执行的。
image.png

服务端的读写命令是单线程的。

Redis单线程为什么还能那么快

  1. 命令执行基于内存操作,一条命令在内存里操作的时间是几十纳秒
  2. 命令执行时单线程操作,没有线程切换的开销
  3. 基于IO多路复用机制提升Redis的IO利用率
  4. 高效的数据存储结构:全局hash表以及多种高效数据结构,比如跳表,压缩列表,链表等等。

Redis底层数据如何用跳表存储的

有序集合放到链表中,跳表就是根据链表查找较慢这点而去做优化
在Redis中,跳表(Skip List)是用于实现有序集合(Sorted Set)的数据结构。跳表通过引入多层索引加速有序集合的查找操作。
跳表的底层原理是由多层链表组成,其中最底层是原始链表,包含所有的元素节点。上层的索引节点通过指针连接了下层的节点,形成了一种跳跃的结构。
跳表的层数是根据元素数量和概率计算得出的,通常由一个随机算法决定。每一层的索引节点数量是根据元素数量和层数计算得出的。
image.png
O(logN)
把有序链表改造为支持近似“折半查找”算法,可以进行更快速的插入、输出、查找操作

Redis删除过期key的策略

Redis对于过期key的删除策略主要有三种:

  1. 定时删除:在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时,对key进行删除。这种方式可以保证内存被尽快释放,但如果过期key很多,删除这些key会占用很多的CPU时间¹。
  2. 惰性删除:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。这种方式对CPU时间的占用是比较少的,但如果大量的key在超出超时时间后,很久一段时间内,都没有被获取过,那么可能发生内存泄露。
  3. 定期删除:每隔一段时间执行一次删除过期key操作。通过限制删除操作的时长和频率,来减少删除操作对CPU时间的占用¹。

定时删除和定期删除为主动删除:Redis会定期主动淘汰一批已过去的key。惰性删除为被动删除:用到的时候才会去检验key是不是已过期,过期就删除¹。

惰性删除为redis服务器内置策略。定期删除可以通过配置redis.conf 的hz选项,默认为10 (即1秒执行10次,100ms一次),以及配置redis.conf的maxmemory最大值,当已用内存超过maxmemory限定时,就会触发主动清理策略¹。

Redis默认的删除策略是惰性删除+定期删除

Redis Key过期了为什么内存没释放

你在使用Redis时,肯定经常使用SET命令
SET除了可以设置key-value 之外,还可以设置key的过期时间,就像下面这样:

127.0.0.1:6379> SET tuling zhuge EX 120
oK
127.0.0.1:6379> TTL tuling4 (integer)117

此时如果你想修改key的值,但只是单纯地使用SET命令,而没有加上过期时间的参数,那这个key的过期时间将会被擦除

127.0.0.1:6379> SET tuling zhuge6662oK
127.0.0.1:6379> TTL tuling // key永远不过期了!4 (integer) -1

导致这个问题的原因在于:SET命令如果不设置过期时间,那么Redis 会自动擦除这个key的过期时间
如果你发现Redis的内存持续增长,而且很多key原来设置了过期时间,后来发现过期时间丢失了,很有可能是因为这个原因导致的。
这时你的Redis中就会存在大量不过期的 key,消耗过多的内存资源
所以,你在使用SET命令时,如果刚开始就设置了过期时间,那么之后修改这个key,也务必要加上过期时间的参数,避免过期时间丢失问题。

Redis对于过期key的处理一般有惰性删除和定时删除两种策略
1、惰性删除:当读/写一个已经过期的key时,会触发惰性删除策略,判断key是否过期,如果过期了直接删除掉这个key。
2、定时删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期(默认每100ms)主动淘汰一批已过期的key ,这里的一批只是部分过期key,所以可能会出现部分key已经过期但还没有被清理掉的情况,导致内存并没有被释放。

Redis Key没设置过期时间为什么被Redis主动删除了

当redis已用内存超过maxmemory限定时,触发主动清理策略
主动清理策略在Redis 4.0之前一共实现了6种内存淘汰策略,在4.0之后,又增加2种策略,总共8种:
a)淘汰策略只对设置了TTL的key生效:

  1. volatile-ttl:是基于生存时间(Time-To-Live,TTL)的策略。这种策略会从已设置过期时间的数据集中挑选将要过期的数据进行淘汰。淘汰的策略不是LRU,而是基于key的剩余寿命TTL的值,TTL越小的key越优先被淘汰。
  2. volatile-random:就像它的名称一样,在设置了过期时间的键值对中,进行随机删除。
  3. volatile-lru:会使用LRU 算法筛选设置了过期时间的键值对删除。
  4. volatile-lfu:会使用LFU 算法筛选设置了过期时间的键值对删除。

b)淘汰策略对所有key生效:

  1. allkeys-random:从所有键值对中随机选择并删除数据。
  2. allkeys-lru:使用LRU (Least Recently Used)算法在所有数据中进行筛选删除。
  3. allkeys-lfu:使用LFU(Least Frequently Used)算法在所有数据中进行筛选删除。

c) 不处理:

  1. noeviction:不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息"(error) OOM command not allowed whenused memory",此时Redis只响应读操作。(默认的内存淘汰策略

LRU (Least Recently Used)算法:在淘汰时应该优先选择最近最少使用的数据项。LRU算法维护一个使用顺序队列,最近访问的数据项被移动到队列的末尾(redis默认)。
LFU(Least Frequently Used)算法:在淘汰时应该优先选择最不经常使用的数据项。LFU算法维护一个使用频率计数器,记录每个数据项被访问的次数。当存在大量的热点缓存

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Spring 多线程的事务处理 下一篇主动写入流对@ResponseBody注解的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目