浅析缓存读写策略

简介: 随着我们业务量的增长,系统面对的压力也陡然上升,大量的读写请求到数据库往往会伴随着各式各样的问题,可能仅仅是一条慢SQL,就有可能拖垮整个系统服务。通常这个时候,我们除了做数据库的读写分离架构,还会对数据库进行分库分表。但是可能有些一成不变或者极少时间触发变更的数据,像类目、类目属性等,大量的针对类目维度的读数据库也会给数据库带来各种压力,通常会以NoSql数据库与关系型数据库互相搭配的方式,以用来更好的服务与我们的业务发展。

前言

image.png
随着我们业务量的增长,系统面对的压力也陡然上升,大量的读写请求到数据库往往会伴随着各式各样的问题,可能仅仅是一条慢SQL,就有可能拖垮整个系统服务。通常这个时候,我们除了做数据库的读写分离架构,还会对数据库进行分库分表。但是可能有些一成不变或者极少时间触发变更的数据,像类目、类目属性等,大量的针对类目维度的读数据库也会给数据库带来各种压力,通常会以NoSql数据库与关系型数据库互相搭配的方式,以用来更好的服务与我们的业务发展。

为什么要使用缓存

伴随着业务量的增长,数据量、并发量也会翻个很多倍,这个时候数据库的IO也逐渐成了系统的性能瓶颈,这个时候我们可以利用缓存中间件,来提升访问速度降低请求响应时间,以便提升整体系统性能。
说到缓存,大家可能都会想到memcached、redis、tair等,日常使用中可能大部分场景都是简单的读取缓存,有数据就返回,没有数据就查数据库,然后再写入缓存中。但是真正的缓存读写策略是比较复杂的,不仅要考虑各种场景,还需针对业务的各种因素权衡利弊的,比如“缓存与数据库”以谁为准、数据更新时是“淘汰缓存”还是“更新缓存”、缓存和数据库的操作时序如何保障等。

缓存的读写策略

缓存读写策略中有三种,分别是旁路缓存模式策略、读写穿透策略、异步缓存写入策略,日常开发中最常用的就是旁路缓存模式策略,它常常用于读请求比写请求多的场景下,具体的策略定义如下:

  • 旁路缓存策略(Cache Aside Pattern)

    • 读:先读取缓存,读取到就直接返回;没有读取到缓存,就读取数据库,然后拿出数据后放入缓存,同时返回响应。
    • 写:先更新数据库,然后再删除缓存
  • 读写穿透策略(Read/Write Through Pattern)

    • 先:先读取缓存,读取到就直接返回;没有读取到缓存,就读取数据库,然后拿出数据后放入缓存,同时返回响应。
    • 写:与旁路缓存策略相反,先看缓存中是否存在该数据,存在则先更新缓存,再更新数据库,也就是同时更新数据库跟缓存;不存在直接更新数据库。
  • 异步缓存写入策略(Write Behind Pattern):

    • 它跟读写穿透策略类似,但是它们的不同点就是:读写穿透是同步更新DB和cache,而异步缓存只更新缓存不直接更新数据库,而是通过异步批量的方式来更新数据库
关于这三种读写策略详细的解析,本文暂不展开,且听下回书讲解。

Cache Aside Pattern

上文说到旁路缓存策略是日常使用最多的一种策略,我们通过一个案例分析来看看是如何使用的。
假设现在数据库有个订单,字段order_id为订单号,字段price为订单价格。缓存中存储了以订单号为key的缓存(20221126:100),如下所示:
image.png

需求:由于可能订单算错了价格,需要将order_id为20221126的订单的价格改成300,我们该如何去做?

1、先更新数据库,在更新缓存

image.png
首先说明,这种读写策略下可能会存在数据不一致的情况的,假如A请求是将order_id=20221126的价格改为300,请求B是将order_id=20221126的价格改为100,那么最终情况应该是order_id=20221126的价格为100,且数据库与缓存中的数据一致,那么如果没有并发等控制,那么如下图所示:
image.png
因为更新数据库和更新缓存是两个非原子性的操作,而且没有并发控制等策略,所以请求A/B执行的顺序是不能保证的,如果你是因为系统并发量小而采取这种操作,那么是有问题的,这种情况发生的概率还是很高的,它不一定是并发导致,还有可能因为查询接口的耗时或者网络波动导致操作并发,最终导致数据的不一致。

2、先更新数据库,在删除缓存

其实解决上面那样的问题也很简单,我们不采取缓存更新的方案,而是删除缓存。而读取数据的时候,如果缓存没命中,就去查数据库,然后再回填到缓存中,如下所示:
image.png
这种解决方案就是上文的旁路缓存策略,它是以数据库的数据为基准的,而缓存是按需才加载,一般被分为读策略和写策略。此示例只是作为数据不一致的推导。
其实像Cache Aside这种缓存策略,也是有缺点的即也会出现数据不一致的情况,同时操作数据库以及缓存,任何一个操作失败都会造成数据不一致。假如设置了数据库,但是操作缓存失败了,没有清除掉,就会导致数据不一致。
而且这种方案也有可能出现脏数据可能,请求A读取缓存,此时缓存刚好失效,而更新操作执行速度比读操作执行快,读线程最后更新缓存,但是是个老数据,虽然更新操作最后会删除缓存,但是在这中间,脏数据就会产生。

Cache Aside策略有什么缺陷

最大的缺陷就是当我们写入操作很频繁的时候,缓存中的数据就会被频繁的删除掉,会直接导致缓存命中率下降,但是如果我们业务中又必须要很高的缓存命中率怎么办呢?

  1. 在更新数据库记录的时候也更新缓存,我们在代码写更新缓存前加上分布式锁,每次运行一个线程更新缓存,防止并发问题,这种做法就是会对写入性能带了一定影响,毕竟加了锁。
  2. 第二种方案,同样也是更新数据库的时候更新缓存,但是这次我们把缓存设置一个过期时间,一般很短,即使根据业务需求计算,即使出现了数据不一致的情况,也是会很快就过期了,这种情况是可以接受的。

还有就是首次的请求的数据一定不在缓存的问题,这种解决方式也简单,我们可以在系统加载的时候将热点数据提前写入缓存中。

目录
相关文章
|
5月前
|
缓存 负载均衡 网络协议
电商API接口性能优化技术揭秘:缓存策略与负载均衡详解
电商API接口性能优化是提升系统稳定性和用户体验的关键。本文聚焦缓存策略与负载均衡两大核心,详解其在电商业务中的实践。缓存策略涵盖本地、分布式及CDN缓存,通过全量或部分缓存设计和一致性维护,减少后端压力;负载均衡则利用反向代理、DNS轮询等技术,结合动态调整与冗余部署,提高吞吐量与可用性。文中引用大型及跨境电商平台案例,展示优化效果,强调持续监控与迭代的重要性,为电商企业提供了切实可行的性能优化路径。
|
6月前
|
缓存 搜索推荐 CDN
HTTP缓存策略的区别和解决的问题
总的来说,HTTP缓存策略是一种权衡,需要根据具体的应用场景和需求来选择合适的策略。理解和掌握这些策略,可以帮助我们更好地优化网页性能,提高用户的浏览体验。
199 11
|
缓存 算法 数据挖掘
深入理解缓存更新策略:从LRU到LFU
【10月更文挑战第7天】 在本文中,我们将探讨计算机系统中缓存机制的核心——缓存更新策略。缓存是提高数据检索速度的关键技术之一,无论是在硬件还是软件层面都扮演着重要角色。我们会详细介绍最常用的两种缓存算法:最近最少使用(LRU)和最少使用频率(LFU),并讨论它们的优缺点及适用场景。通过对比分析,旨在帮助读者更好地理解如何选择和实现适合自己需求的缓存策略,从而优化系统性能。
406 3
|
5月前
|
存储 缓存
.NET 6中Startup.cs文件注入本地缓存策略与服务生命周期管理实践:AddTransient, AddScoped, AddSingleton。
记住,选择正确的服务生命周期并妥善管理它们是至关重要的,因为它们直接影响你的应用程序的性能和行为。就像一个成功的建筑工地,工具箱如果整理得当,工具选择和使用得当,工地的整体效率将会大大提高。
226 0
|
8月前
|
数据采集 缓存 JavaScript
数据抓取的缓存策略:减少重复请求与资源消耗
本教程聚焦于提升爬虫效率与稳定性,通过结合缓存策略、代理IP技术(如爬虫代理)、Cookie和User-Agent设置,优化数据采集流程。以知乎为例,详细讲解如何抓取指定关键词的文章标题和内容。内容涵盖环境准备、代码实现、常见问题及解决方案,并提供延伸练习,帮助读者掌握高效爬虫技巧。适合具备Python基础的初学者,助你规避网站机制,顺利获取目标数据。
231 2
数据抓取的缓存策略:减少重复请求与资源消耗
|
缓存 JavaScript 中间件
优化Express.js应用程序性能:缓存策略、请求压缩和路由匹配
在开发Express.js应用时,采用合理的缓存策略、请求压缩及优化路由匹配可大幅提升性能。本文介绍如何利用`express.static`实现缓存、`compression`中间件压缩响应数据,并通过精确匹配、模块化路由及参数化路由提高路由处理效率,从而打造高效应用。
518 96
|
Web App开发 缓存 UED
如何设置浏览器的缓存策略?
【10月更文挑战第23天】通过合理地设置浏览器的缓存策略,可以在提高网页性能、减少网络流量的同时,确保用户能够获取到最新的内容,从而提升用户体验和网站的性能优化效果。
1034 60
|
11月前
|
缓存 API C#
C# 一分钟浅谈:GraphQL 中的缓存策略
本文介绍了在现代 Web 应用中,随着数据复杂度的增加,GraphQL 作为一种更灵活的数据查询语言的重要性,以及如何通过缓存策略优化其性能。文章详细探讨了客户端缓存、网络层缓存和服务器端缓存的实现方法,并提供了 C# 示例代码,帮助开发者理解和应用这些技术。同时,文中还讨论了缓存设计中的常见问题及解决方案,如缓存键设计、缓存失效策略等,旨在提升应用的响应速度和稳定性。
175 13
|
存储 缓存 安全
在 Service Worker 中配置缓存策略
Service Worker 是一种可编程的网络代理,允许开发者控制网页如何加载资源。通过在 Service Worker 中配置缓存策略,可以优化应用性能,减少加载时间,提升用户体验。此策略涉及缓存的存储、更新和检索机制。
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
196 10
下一篇
oss云网关配置