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