文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

引入缓存后给业务带来的问题,你看懂了吗?

2024-11-29 19:13

关注

业务系统引入缓存之后,架构由原来的两层架构变成了三层架构:

图片

由此,带来了三个问题需要解决,分别是缓存读取、缓存更新和缓存淘汰。

缓存读取

缓存读取比较简单,查询数据时首先查询缓存,如果缓存命中,则从缓存中读取数据。如果缓存不命中,则查询数据库,并且更新缓存。

2.缓存更新

缓存更新时,在更新存储和更新缓存的先后关系上,有以下几种策略:

1)先更新数据库再更新缓存

首先,这种方案会有线程安全的问题:

例如,同时有线程A和线程B对数据进行更新操作,可能会出现下面的执行顺序。

①线程A更新了数据库

②线程B更新了数据库

③线程B更新了缓存

④线程A更新了缓存

此时就会出现数据库中的数据与缓存的数据不一致的情况,这是因为线程A先更新了数据库,可能因为网络等异常情况,线程B更新完数据库进而更新了缓存,当线程B更新完缓存后,线程A才更新缓存,这就导致了数据库数据与缓存数据的不一致。

其次,这种方案也有其不适用的业务场景:

首先一个业务场景就是数据库写多读少的场景,这种场景下采用先更新数据库再更新缓存的策略,就会导致缓存并未被读取就会被频繁的更新,极大的浪费了服务器的性能。

再一个业务场景就是数据库中的数据不是直接写入缓存的,而是需要大量的复杂运算,将运算结果写入缓存。如果这种场景下使用先更新数据库再更新缓存的策略,也会造成服务器资源的浪费。

2)先删除缓存,再更新数据库

先删除缓存再更新数据库的方案也存在着线程安全的问题,例如,线程A更新缓存,同时,线程B读取缓存的数据。可能会出现下面的执行顺序:

①线程A删除缓存

②线程B查询缓存,发现缓存中没有想要的数据

③线程B查询数据库中的旧数据

④线程B将查询到的旧数据写入缓存

⑤线程A将新数据写入数据库

此时,就出现了数据库中的数据和缓存中的数据不一致的情况。如果删除缓存失败,也会出现数据库数据和缓存数据不一致的现象。

3)先更新数据库,再删除缓存

首先,这种方式也有极小的概率发生数据库数据和缓存数据不一致的情况,例如,线程A做查询操作,线程B执行更新操作,其执行的顺序如下所示:

①缓存刚好失效

②请求A查询数据库,获取到数据库中的旧值

③请求B将新值写入数据库

④请求B删除缓存

⑤请求A将查到的旧值写入缓存

如果上述顺序一旦发生,就会造成数据库中的数据和缓存中的数据不一致的情况发生。但是,先更新数据库再删除缓存的策略发生数据库和缓存数据不一致的概率很低,原因就是:③的写数据库操作比步骤②的读数据库操作耗时更短,才有可能使得步骤④先于步骤⑤执行。

但是,往往数据库的读操作的速度远快于写操作,因此步骤③耗时比步骤②更短这一场景很难出现。因此,先更新数据库,再删除缓存是一种值得推荐的做法。

4)异常情况

上面的讨论与对比都是在删除缓存和更新数据库这两步操作都成功的情况下叙述的。当然系统正常运行时的操作基本上都是成功的,那么如果两步操作有其中一步操作失败了呢?以先更新数据库再删除缓存举例:

图片

①更新数据库数据;

②删除缓存数据失败;

③将需要删除的key发送至消息队列;

④自己消费消息,获得需要删除的key;

⑤继续重试删除操作,直到成功。

3.缓存淘汰

主要有两种策略,分别是主动淘汰和被动淘汰:

二、缓存的三座大山

1.一致性

一致性主要解决以下几个问题:

1)并行更新如何解决隔离性问题

2)原子性更新时如何解决部分更新的问题

3)如何解决读一致的问题

2.缓存击穿

缓存击穿指的是访问数据时直接绕过缓存,访问数据库。可能会有两种原因造成这种现象:

图片

一种是大量的空查询,比如黑客攻击;另外一种是缓存污染,比如大量的网络爬虫造成的。

1)为了解决空查询带来的缓存击穿,主要有两种方案:

第一种是在缓存层前面再加一层布隆过滤器,布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。布隆过滤器是一个 bit 向量或者说 bit 数组,长这样:

图片

如果我们要映射一个值到布隆过滤器中,我们需要使用多个不同的哈希函数生成多个哈希值,并对每个生成的哈希值指向的 bit 位置 1,例如针对值 “baidu” 和三个不同的哈希函数分别生成了哈希值 1、4、7,则上图转变为:

图片

我们现在再存一个值 “tencent”,如果哈希函数返回 3、4、8 的话,图继续变为:

图片

值得注意的是,4 这个 bit 位由于两个值的哈希函数都返回了这个 bit 位,因此它被覆盖了。现在我们如果想查询 “dianping” 这个值是否存在,哈希函数返回了 1、5、8三个值,结果我们发现 5 这个 bit 位上的值为 0,说明没有任何一个值映射到这个 bit 位上,因此我们可以很确定地说 “dianping” 这个值不存在。

而当我们需要查询 “baidu” 这个值是否存在的话,那么哈希函数必然会返回 1、4、7,然后我们检查发现这三个 bit 位上的值均为 1,那么我们可以说 “baidu” 存在了么?答案是不可以,只能是 “baidu” 这个值可能存在。

这是为什么呢?答案很简单,因为随着增加的值越来越多,被置为 1 的 bit 位也会越来越多,这样某个值 “taobao” 即使没有被存储过,但是万一哈希函数返回的三个 bit 位都被其他值置位了 1 ,那么程序还是会判断 “taobao” 这个值存在。

很显然,过小的布隆过滤器很快所有的 bit 位均为 1,那么查询任何值都会返回“可能存在”,起不到过滤的目的了。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。另外,哈希函数的个数也需要权衡,个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。

第二种是把所有的key和热数据value加入缓存,在缓存层拦截空数据查询。

图片

2)为了解决爬虫带来的缓存击穿问题,可以设置缓存策略:

3.缓存雪崩

缓存雪崩指的是热数据集中淘汰,大量请求瞬间透传到存储层,导致存储层过载。

图片

造成缓存雪崩的原因主要是TTL机制过于简单造成的,解决方案主要有以下:

来源:一安未来内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯