关于复述,缓存失效机制的介绍

  

今天小编给大家分享的是关于复述,缓存失效机制的介绍,很多人都不太了解,今天小编为了让大家更加了解复述,缓存失效机制,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。

复述,缓存失效的故事要从到期这个命令说起,到期允许用户为某个关键指定超时时间,当超过这个时间之后主要对应的值会被清除,这篇文章主要在分析复述,源码的基础上站在复述,设计者的角度去思考复述,缓存失效的相关问题。

关于复述,缓存失效机制的介绍

<强>复述,缓存失效机制

复述,缓存失效机制是为应对缓存应用的一种很常见的场景而设计的,讲个场景:

我们为了减轻后端数据库的压力,很开心的借助复述,服务把变化频率不是很高的数据从数据库加载出来放入了缓存,因此之后的一段时间内我们都可以直接从缓存上拿数据,然而我们又希望一段时间之后,我们再重新的从数据库加载出当前的数据放入缓存,这个事情怎么做呢?

问题提出来了,这个问题怎么解决呢?好吧,我们对于手头的语言工具很熟悉,坚信可以很快的写出这么一段逻辑:我们记录上次从数据库加载数据的时间,然后每次响应服务的时候都去判断时间是不是过期了,要不要从DB重新负载了……。当然这种方法也是可以的,然而当我们查阅复述,命令文件的时候,发现我们做了本来不需要做的事情,复述本身提供这种机制,我们只要借助到期命令就可以轻松的搞定这件事情:

键30到期

上面的命令即为关键设置30秒的过期时间,超过这个时间,我们应该就访问不到这个值了,到此为止我们大概明白了什么是缓存失效机制以及缓存失效机制的一些应用场景,接下来我们继续深入探究这个问题,复述,缓存失效机制是如何实现的呢?

<强>延迟失效机制

延迟失效机制即当客户端请求操作某个关键的时候,复述,会对客户端请求操作的关键进行有效期检查,如果关键过期才进行相应的处理,延迟失效机制也叫消极失效机制。我们看看t_string组件下面对得到请求处理的服务端端执行堆栈:

getCommand   →getGenericCommand   →lookupKeyReadOrReply   →lookupKeyRead   →expireIfNeeded

关键的地方是expireIfNeed,复述,对关键的得到操作之前会判断键关联的值是否失效,这里先插入一个小插曲,我们看看复述中实际存储值的地方是什么样子的:

typedef struct redisDb {   dict * dict类型;这个数据库*//*密钥空间   dict *到期;/*超时超时设置的键*/dict * blocking_keys;/*键与客户等待数据(BLPOP) */dict * ready_keys;/*屏蔽键推*/dict * watched_keys;/*看着键多/EXEC CAS */int id;长长的avg_ttl;/*平均TTL,只是为了统计*/}redisDb;

上面是复述中定义的一个结构体,dict是一个复述,实现的一个字典,也就是每个DB会包括上面的五个字段,我们这里只关心两个字典,一个是dict类型,一个是到期:

dict是用来存储正常数据的,比如我们执行了设置关键“hahaha",这个数据就存储在dict中。

到期使用来存储关联了过期时间的关键的,比如我们在上面的基础之上有执行的关键1到期,这个时候就会在到期中添加一条记录。

回过头来看看expireIfNeeded的流程,大致如下:

从到期中查找关键的过期时间,如果不存在说明对应关键没有设置过期时间,直接返回。

如果是奴隶机器,则直接返回,因为复述,为了保证数据一致性且实现简单,将缓存失效的主动权交给主控机器,奴隶机器没有权限将关键失效。

如果当前是主机器,且关键过期,则主人会做两件重要的事情:1)将删除命令写入AOF文件。2)通知奴隶当前关键失效,可以删除了。

大师从本地的字典中将主要对于的值删除。

<强>主动失效机制

主动失效机制也叫积极失效机制,即服务端定时的去检查失效的缓存,如果失效则进行相应的操作。

我们都知道复述是单线程的,基于事件驱动的,复述,中有个EventLoop, EventLoop负责对两类事件进行处理:

一类是IO事件,这类事件是从底层的多路复用器分离出来的。

一类是定时事件,这类事件主要用来事件对某个任务的定时执行。

看起来复述的EventLoop和网状的以及JavaScript的EventLoop功能设计的大概类似,一方面对网络I/O事件处理,一方面还可以做一些小任务。

关于复述,缓存失效机制的介绍