大数据观察
了解大数据,关注大数据观察吧!
每个想了解最新大数据资讯的人,都关注了我
文 / 数据君
一、缓存的几种更新策略
从下面的表格看,缓存的更新策略大致分为三种,本文将从一致性和维护成本两个方面对于三种缓存更新策略进行简要说明,因为这些东西比较理论和抽象,如哪里说得不对,欢迎拍砖。
注:
(1) 一致性:缓存和真实数据源(例如mysql, hbase, elasticsearch等等)是否存在一段时间数据的不一致。
(2) 维护成本: 开发人员的开发和维护成本。
策略 |
一致性 |
维护成本 |
LRU/LIRS/FIFO算法剔除 |
最差 |
低 |
超时剔除 |
较差 |
较低 |
主动更新 |
强 |
高 |
二、LRU/LFU/FIFO算法剔除
1. 使用场景:
通常用于缓存使用量超过了预设的最大值时候(缓存空间不够),如何对现有的数据进行清理。例如FIFO会把最新进入缓存的数据清理出去, LRU会把最近最少使用的数据清理掉。
例如:Memcache使用的是LRU,具体Memcache如何实现的,这里就不在赘述了,网上资料多的是。
例如:Redis使用maxmemory-policy这个配置作为内存最大值后对于数据的更新策略。
配置名 |
含义 |
默认值 |
maxmemory |
最大可用内存 |
不使用该配置,也就对内存使用无限制 |
maxmemory-policy |
内存不够时,淘汰策略 |
volatile-lru |
volatile-lru -> 用lru算法删除过期的键值
allkeys-lru -> 用lru算法删除所有键值
volatile-random -> 随机删除过期的键值
allkeys-random -> 随机删除任何键值
volatile-ttl -> 删除最近要到期的键值
noeviction -> 不删除键,只返回一个错误
2. 常用算法:
这里不再赘述,常用的算法有如下几种:
FIFO[first in first out]
LFU[Less Frequently Used]
LRU[Least Recently used]
3. 一致性
可以想象,要清理哪些数据,不是由开发者决定(只能决定大致方向:策略算法),数据的一致性是最差的。
4. 维护成本
这些算法不需要开发者自己来实现,通常只需要配置最大maxmemory和对应的策略即可。
开发者只需要有这个东西,知道是什么意思,选择自己需要的算法,算法的实现是由缓存服务器实现的。
三、超时剔除
1. 使用场景:
就是我们通常做的缓存数据过期时间设置,例如redis和memcache都提供了expire这样的API,来设置K-V的过期时间。
一般来说业务可以容忍一段时间内(例如一个小时),缓存数据和真实数据(例如:mysql, hbase等等)数据不一致(一般来说,缓存可以提高访问速度降低后端负载),那么我们可以对一个数据设置一定时间的过期时间,在数据过期后,再从真实数据源获取数据,重新放到缓存中,继续设置过期时间。
例如: 一个视频的描述信息,我们可以容忍一个小时内数据不一致,但是涉及到钱的方面,如果不一致可想而知。
2. 一致性:
一段时间内(取决于过期时间)存在数据一致性问题,即缓存数据和真实数据源数据不一致。
3. 维护成本
用户的维护成本不是很高,只需要设置expire过期时间即可(前提是你的业务允许这段时间可能发生的数据不一致)。
典型的缓存模式,一般有如下几种:
Cache Aside;
Read/Write Through;
Write Behind。
每种模式都有不同的特点,适用于不同的项目场景,下面来依次看看:
1、Cache Aside模式
这是大家经常用到的一种策略模式。这种模式主要流程如下:
应用在查询数据的时候,先从缓存Cache中读取数据,如果缓存中没有,则再从数据库中读取数据,得到数据库的数据之后,将这个数据也放到缓存Cache中;
如果应用要更新某个数据,也是先去更新数据库中的数据,更新完成之后,则通过指令让缓存Cache中的数据失效。
这里为什么不让更新操作在写完数据库之后,紧接着去把缓存Cache中的数据也修改了呢?
主要是因为这样做的话,就有2个写操作的事件了,担心在并发的情况下会导致脏数据,举个例子:
假如同时有2个请求(请求A和请求B)并发的执行。请求A是要去读数据,请求B是要去更新数据。初始状态缓存中是没有数据的,当请求A读到数据之后,准备往回写的时候,此刻,请求B正好要更新数据,更新完了数据库之后,又去把缓存更新了,那请求A再往缓存中写的就是旧数据了,属于脏数据。
那么Cache Aside模式就没有脏数据问题了吗?不是的,在极端情况下也可能会产生脏数据,比如:
假如同时有2个请求(请求A和请求B)并发的执行。请求A是要去读数据,请求B是要去写数据。
假如初始状态缓存中没有这个数据,那请求A发现缓存中没有数据,就会去数据库中读数据,读到了数据准备写回缓存中,就在这个时候,请求B是要去写数据的,请求B在写完数据库的数据之后,又去设置了缓存失效。
这个时候,请求A由于在数据库中读到了之前的旧数据,开始往缓存中写数据了,此时写进入的就也是旧数据。
那么最终就会导致,缓存中的数据与数据库的数据不一致,造成了脏数据。
不过这种概率比上面一种概率要小很多。所以整体而言Cache Aside模式还是一种比较简单实用的方式。
2、Read/Write Through模式
这个模式其实就是将缓存服务作为主要的存储,应用的所有读写请求都是直接与缓存服务打交道,而不管最后端的数据库了,数据库的数据由缓存服务来维护和更新。
不过缓存中数据变更的时候是同步去更新数据库的,在应用的眼中只有缓存服务。
流程就相当简单了:
应用要读数据和更新数据都直接访问缓存服务;
缓存服务同步的将数据更新到数据库。
这个模式出现脏数据的概率就比较低,但是就强依赖缓存了,对缓存服务的稳定性有较大要求。另外,增加新缓存节点时还会有初始状态空数据问题。
3、Write Behind模式
这个模式就是Read/Write Through模式的一个变种。区别就是Read/Write Through模式的缓存写数据库的时候是同步的,而Write Behind模式的缓存操作数据库是异步的。
流程如下:
应用要读数据和更新数据都直接访问缓存服务;
缓存服务异步的将数据更新到数据库(通过异步任务)。
这个模式的特点就是速度很快,效率会非常高,但是数据的一致性比较差,还可能会有数据丢失的情况,实现逻辑也较为复杂。
以上就是目前三种主流的缓存更新策略,另外还有Refrsh-Ahead模式等由于使用的不是很常见就不详细介绍了。
缓存是互联网项目中非常普遍的一个提高效率的方案,用法比较多,也比较关键,大家可以一起交流。
主题 |数据缓存
插图 | 网络来源
作 者 介 绍
数据君:)
了解大数据,关注大数据观察
部分图文来自网络,侵权则删
“嘿,长按二维码,跟我一起有趣”
我想给你一个理由 继续面对这操蛋的生活
版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《【大数据操作】缓存的更新策略具体有哪些?》的版权归原作者「大数据观察」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458
文章来源: 阅读原文