Redis的过期策略以及内存淘汰机制
一、Redis的过期策略
1.过期策略
redis采用的是定期删除和惰性删除的策略
为什么不用定时删除策略?
定时删除:用一个定时器来负责监视key,过期则自动删除,虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略。
定期删除+惰性删除时如何工作的?
定期删除:redis默认每隔100ms检查,是否有过期的key,有过期的key则删除,需要注意的是,redis不是每隔100ms将所有key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行删除,redis卡死),因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
惰性删除:每次当客户端get任何数据都会调用expirelfNeeded()这个函数。这个函数可以判断数据是否过期。如果过期删除expires以及value的空间。
数据达到过期时间,不做处理,等下次访问该数据时,如果未过期,返回数据,如果已经过期,返回不存在。
内存占用很大,出现长期占用内存的数据。
通过上述两种手段结合起来,保证过期的key一定会被干掉。
但实际上还是有问题,如果定期删除漏掉了很多过期key,然后也没及时去查找,也就没有走惰性删除,此时就会走内存淘汰机制。
二、内存淘汰机制
如果内存占用过多的时候,此时会进行内存淘汰,有如下策略
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。
volatile-tll:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
allkeys-lru:从数据集(server.dt[i].dict)中挑选最近最少使用的数据淘汰。
no-envition:静止驱逐数据,新写入操作会报错。
三、Redis为什么是单线程的?
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。那为啥还有用多线程???多线程会带来很多麻烦。
1.绝大部分请求是存粹的内存操作。
2.采用单线程,避免不必要的上下文切换。
四、单线程的redis为什么这么快
1.纯内存操作。
2.单线程操作,避免了频繁的上下文切换。
3.采用I/O多路复用机制。
五、为什么Redis的操作是原子性的,怎么保证原子性的?
对于Redis而言,命令的原子性是指:一个操作的不可再分,操作要么执行,要么不执行。
redis的操作之所以是原子性的,是因为Redis是单线程的。Redis本身提供的所有API都是原子操作,reids中的事务其实是要保证批量操作的原子性。
1.redis事务
redis事务功能是通过MULTI、EXEC、DISCARD和WATCH四个原语实现的。
Redis会将一个事务中的所有命令序列化,然后按顺序执行。
Redis内部不支持回滚“Redis在事务失败时,不进行回滚,而是继续执行余下的命令”。所以Redis内部可以保持简单且快速。
定义事务的过程中,命令输入错误会造成所有的命令都不执行。
如果一个书屋在运行中,出现了运行错误,那么正确的命令会被执行。