数据更新场景

在引进缓存后,数据会一起存放在缓存和数据库两个当地。因而,当需求更新数据时,需求保证这两个当地都可以得到更新,而且不同的更新时序可能会发生不同的成果。在业界,现已形成了多种处理数据更新问题的形式,例如Cache Aside Pattern和Read/Write Through等。

Cache Aside Pattern

Cache-Aside Pattern(缓存旁路形式) 是一种常用的缓存更新战略,可以进步体系的功能和可靠性。以下是Cache-Aside Pattern的主要流程:

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)

  1. 读取数据:当运用程序需求获取数据时,首要会查看缓存中是否现已存在所需数据。假如数据存在于缓存中,则运用程序直接从缓存中读取数据,无需拜访底层数据存储体系。

  2. 缓存未射中:假如数据不存在于缓存中,即缓存未射中,运用程序会查询底层数据存储体系来获取数据,并将数据存储到缓存中以备后续读取。

  3. 更新数据:当运用程序需求更新数据时,它首要会更新底层数据存储体系中的数据。然后,运用程序会使缓存失效,即从缓存中删去相应的数据。

  4. 下次读取:在下次读取该数据时,运用程序会从头执行过程1和过程2,将更新后的数据加载到缓存中。

战略思想

Cache-Aside Pattern的关键思想是将读操作和写操作分开处理,这种战略在数据读取频频、数据更新相对较少的场景中非常适用

  • 读操作优先从缓存中获取数据,削减对底层数据存储体系的拜访,然后进步体系的功能。
  • 写操作会更新底层数据存储体系,并使缓存失效,以坚持数据的一致性。

具体操作剖析

失效(Invalidation)

  • 当运用程序需求获取数据时,首要会尝试从缓存中查找数据。
  • 假如缓存中不存在该数据(即缓存失效),运用程序会从数据库中读取数据。
  • 读取成功后,运用程序会将数据放入缓存,以便后续拜访。

射中(Cache Hit)

  • 当运用程序需求获取数据时,首要会尝试从缓存中查找数据。
  • 假如缓存中存在该数据(即缓存射中),运用程序会直接从缓存中回来数据,防止了对数据库的拜访。

更新(Update)

  • 当数据需求更新时,首要将更新操作运用到数据库中。
  • 假如更新成功,再将缓存中对应的数据失效(即从缓存中删去),以便下次拜访时可以从头从数据库中读取最新的数据。

经过运用缓存旁路形式,可以有效地进步体系的功能和呼应速度。缓存可以削减对数据库的拜访次数,然后减轻数据库的负载,而且在缓存射中时可以快速回来数据,削减网络推迟。一起,经过合理办理缓存的失效和更新,可以保证缓存中的数据与数据库中的数据坚持一致性。

留意,在运用Cache-Aside Pattern时,运用程序需求考虑缓存和底层数据存储体系之间的一致性问题,以及缓存失效带来的功能丢掉。可以运用一些技能手段来处理这些问题,例如依据时刻的缓存失效战略、运用缓存确定来处理多个恳求一起更新缓存等

两个待剖析的问题

  • Cache Aside Pattern为什么不是更新缓存,而是失效(删去)缓存?
  • Cache Aside Pattern在数据更新的时分是选用先更新数据库,再失效缓存。

Cache Aside Pattern为什么不是更新缓存,而是失效(删去)缓存?

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)
如上图所示,假设A、B两个线程,A先更新数据库后 B再更新数据库,然后别离进行更新缓存,可是B先更新缓存成功,A后更新缓存成功,这样就导致数据库是最新的数据可是缓存中是旧的脏数据。而假如失效缓存数据的话,可以保证下一次读恳求回源到数据库将最新的数据载入到缓存中,防止脏数据的问题。因而,针对数据更新缓存选用失效的方法进行处理

失效数据计划

依据上述状况,可以采纳以下过程来处理数据更新缓存的问题:

  1. 在A线程更新数据库后,当即便B线程的缓存数据失效。可以经过设置一个标志位或许发送一个通知来完成。

  2. 在B线程更新数据库之前,查看缓存数据是否现已失效。假如缓存数据现已失效,则直接更新数据库并更新缓存。

  3. 假如缓存数据未失效,B线程需求等候一段时刻,等候A线程的缓存更新完结。可以运用一些同步机制,如锁或信号量来完成。

  4. 在等候一段时刻后,B线程再次查看缓存数据是否现已失效。假如缓存数据现已失效,则直接更新数据库并更新缓存。

经过以上过程,可以保证在数据更新时,先使缓存数据失效,然后再更新数据库和缓存,然后防止脏数据的问题。这样下一次读恳求将会从数据库中获取最新的数据,并将其载入到缓存中。

Cache Aside Pattern在数据更新的时分是选用先更新数据库,再失效缓存

双写不同数据源很容易导致数据纷歧致的问题。

当A线程先更新数据库,然后B线程再更新数据库,接着别离更新缓存时,假如B线程先更新缓存成功,而A线程后更新缓存成功,那么数据库中的数据便是最新的,但缓存中却是旧的脏数据。为了防止这种状况发生,可以选用失效缓存的方法处理。

经过失效缓存数据,可以保证下一次读恳求从数据库中获取最新的数据并将其加载到缓存中,以防止呈现脏数据的问题。这种方法可以进步数据一致性,但在并发状况下,一起写数据库和更新缓存依然存在双写不成功的可能性,这将在后续章节中进一步讨论。

总之,为了保证数据的一致性,主张在数据更新时运用失效缓存的方法进行处理,保证下一次读恳求可以获取到最新的数据。

先更新缓存再更新数据库

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)
先更新缓存再更新数据库也存在一些坏处。下面是其间一些可能的问题:

  1. 数据丢掉危险:假如在更新缓存成功后,但在更新数据库之前发生错误或中止,那么数据更新将会失利,导致数据库中的数据与缓存中的数据纷歧致。这可能导致数据丢掉的危险。

  2. 体系可用性下降:因为先要更新缓存,然后再更新数据库,整个过程需求两次数据库操作。假如其间一次操作失利或推迟,整个数据更新过程将会更加杂乱和耗时。这可能导致体系的可用性下降。

  3. 竞态条件:假如多个并发操作一起尝试更新缓存和数据库,可能会导致竞态条件。例如,假如两个操作一起读取了旧数据到缓存中,然后一起进行写入,终究可能会发生数据纷歧致的状况。

  4. 错误处理杂乱性:先更新缓存再更新数据库会添加错误处理的杂乱性。假如在更新缓存时发生错误,需求有一种机制来回滚或吊销这次更新。这添加了体系的杂乱性和维护成本。

因而,在规划数据更新计划时,需求归纳考虑数据一致性、可用性和体系杂乱性等方面的要素。一种常用的做法是在更新数据库后当即更新缓存,以保证数据的一致性。

优化数据懒加载

优化数据懒加载,防止不必要的核算开支:假如某些缓存值需求进行杂乱核算才干得出,每次更新数据时都更新缓存可能会导致很多核算功能的糟蹋,特别是在一段时刻内没有读取该缓存数据的状况下。为了更契合数据懒加载的概念并下降核算开支,在读恳求到来时再进行核算可能是更好的挑选。

以下是改进的主张

  • 推迟缓存更新:在数据更新时,不当即更新相关缓存值,而是推迟到读恳求抵达时进行核算和更新。这样可以最大极限地防止不必要的核算开支。

  • 设置缓存过期时刻:为每个缓存设置恰当的过期时刻。假如在过期时刻内没有读取该缓存数据,就不进行更新。只有当有读恳求到来时,再依据需求进行核算和更新缓存。

  • 运用缓存射中率监控:监控缓存的射中率,即缓存被读取的频率。假如某个缓存的射中率较低,阐明该缓存可能是不必要的,可以考虑取消或推迟更新该缓存。

  • 考虑依据事情的更新:将缓存更新与特定事情关联,只有在事情触发时才进行核算和更新相关缓存。这样可以保证在需求更新缓存时才进行核算,防止不必要的核算开支。

经过采纳上述措施,可以更好地遵循数据懒加载的准则,削减不必要的核算开支,进步体系功能和资源利用率。

失效缓存和更新数据库的次序问题

在处理数据更新后缓存失效的状况下,针对数据库和缓存更新的时序可以概括为以下几种状况:

先失效缓存再更新数据库

当缓存数据更新机制中先失效缓存再更新数据库时,可能会导致以下问题:

  1. 数据读取推迟:因为缓存失效后,下一次读取数据需求从数据库中获取,可能会添加读取的推迟,特别是在高并发的状况下。这会影响体系的呼应时刻和用户体会。

  2. 数据纷歧致性:假如在缓存失效之后,但在更新数据库之前,有其他恳求读取了旧的缓存数据,那么就会导致数据纷歧致的问题。因为这些恳求读取到的是失效的缓存数据,而不是最新的数据库数据。

  3. 频频的数据库操作:因为缓存失效后当即更新数据库,可能会导致频频的数据库操作。这会添加数据库的负载和资源消耗,可能影响体系的功能和稳定性。

    【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)
    假如恳求1的线程在失效缓存后,恳求2的线程读恳求发现缓存数据为空时,从数据库中读取旧值放入缓存,会导致脏数据的问题确实存在。这是因为在缓存失效期间,B线程读恳求发生,缓存没有更新,所以读取到的是旧值。

处理计划

为了处理这些问题,可以考虑运用更智能的缓存战略,例如:

  • 更新数据库后再失效缓存:先更新数据库,保证数据的一致性,然后再失效相关缓存,以便下一次读取时能获取最新的数据。

  • 运用缓存更新队列:将需求更新数据库的操作放入队列中,然后按次序处理。这样可以保证数据库的操作次序和数据一致性,并削减频频的数据库操作。

  • 引进缓存同步机制:在更新数据库之前,先将缓存标记为过期状况,在更新完结后再从头加载缓存。这样可以防止读取到过期的缓存数据。

  • 更新缓存时加锁:在线程A失效缓存并更新数据库时,可以经过加锁的方法保证其他线程不能读取脏数据。只有当更新完结后,其他线程才干持续读取缓存数据。

  • 推迟失效战略:在线程A失效缓存后,在更新数据库之前,可以设置一个较短的推迟时刻,让线程B等候一段时刻再进行读取操作。这样可以添加线程A完结更新的机会,削减读取脏数据的概率。

  • 引进版本号或时刻戳:在缓存数据中引进一个版本号或时刻戳,当读恳求发生时,比较恳求的时刻戳和缓存数据的时刻戳,假如时刻较新,则不再读取数据库,防止读取脏数据。

需求依据具体的事务场景和需求挑选适宜的缓存更新战略,以进步体系的功能和数据一致性。

选用延时双删

针对这种状况,可以选用延时双删的战略来有效防止。伪代码如下:

cache.delKey(key);
db.update(data);
Thread.sleep(xxx);
cache.delKey(key);

这种战略主要在写恳求完结数据库更新后,休眠一段时刻,然后再次删去可能由读恳求引进的脏数据,然后最大极限地削减脏数据的存在。

但是,需求留意的是这种延时双删方法需求线程休眠,会下降体系的吞吐量,并不是一种优雅的处理方法。另外,假如数据库选用主从架构,读取的数据也有可能是主从未同步完结时导致的脏数据。

异步删去处理机制

针对这个问题,还可以考虑选用异步删去的方法。即,在写恳求完结数据库更新后,不当即进行删去操作,而是异步地进行删去处理。这样可以防止线程休眠,进步体系的吞吐量,而且在一定程度上处理了主从未同步的问题。

另外,设置缓存的过期时刻也是一种处理计划。经过设定恰当的过期时刻,当缓存过期后,体系会主动载入最新的数据,而且需求体系可以忍受一段时刻的数据纷歧致性。

Write/Read Through 缓存透写/透读

在Cache Aside形式中,关于数据库和缓存的更新逻辑由调用方自行操控,这显然是一个相当杂乱的过程。而在写透写/读透读形式中,关于调用方而言,缓存是整个数据存储的接口,而不需求关怀缓存背后的数据库更新,数据库的更新由缓存统一办理,关于调用方来说,只需求与缓存进行交互,整个过程是透明的。

在写透写/读透读形式下

当调用方要更新数据时,首要会将数据写入缓存。缓存在收到写恳求之后,会负责将数据更新到数据库,并保证数据的一致性。读取数据时,调用方也直接经过缓存进行读取,假如缓存中不存在所需数据,缓存会主动从数据库中获取。这样,调用方就可以将缓存作为数据存储的唯一接口,而不需求直接与数据库进行交互。

读写形式的有点机制

运用写透写/读透读形式可以简化调用方的代码逻辑,削减数据拜访的杂乱性。一起,因为缓存统一办理数据库的更新,可以进步体系的功能和吞吐量。但是,需求留意的是,缓存和数据库之间的数据一致性需求得到保证,可能需求选用一些额外的机制来处理缓存与数据库之间的同步问题。

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)
总结起来,写透写/读透读形式将缓存作为整个数据存储的接口,统一办理数据库的更新,可以简化调用方的代码逻辑,并进步体系的功能。在实际运用中,需求依据具体的需求和场景,归纳考虑数据一致性、功能需求以及体系杂乱性等要素,挑选适宜的缓存战略。

Write Behind Cache Pattern 后写缓存形式

后写缓存形式是在数据更新时直接更新缓存数据,并树立异步任务去更新数据库。这种异步方法使得恳求呼应速度快,体系的吞吐量也会明显进步。但是,因为是异步更新数据库,数据一致性的保证会相对较弱。假如更新数据库失利,就会永远导致体系发生脏数据。因而,需求精心规划体系的重试战略。此外,假如异步服务呈现故障,还需求考虑如何耐久化更新的数据,以便在服务重启后可以快速恢复。

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)
在更新数据库时,因为存在并发多任务,还需求考虑并发写是否会导致脏数据问题,因而需求追溯每次更新数据的时序。运用这种形式需求考虑的细节很多,规划出一套杰出的计划并不容易。

留意要点

虽然后写缓存形式可以进步体系功能,但需求留意以下几点。

首要,因为数据一致性的危险,需求谨慎权衡是否可以忍受脏数据的呈现。其次,需求考虑并发写引发的脏数据问题,可能需求采纳恰当的并发操控措施。最终,需求规划合理的重试战略和数据耐久化计划,以应对异步更新和服务故障导致的问题。

后写缓存形式可以进步体系功能,但在数据一致性、并发写操控、重试战略和数据耐久化等方面需求投入较大的规划和完成工作。在实际运用中,需求依据具体状况权衡利弊,并归纳考虑体系需求、资源状况和可靠性要求等要素,挑选适宜的缓存形式。

总结剖析

最新的数据应该放置在数据库中。

缓存的目的是为了进步体系功能,经过利用内存的高速读取来进步体系吞吐量,并减轻数据库的压力。缓存的存在可以使得部分读恳求无需抵达数据库层,然后进步呼应速度。但是,这也带来了一个问题,即数据存在于缓存和数据库这两个方位,所以在数据更新时需求考虑将“正确的数据放置在哪个最可信的存储介质上”,这需求结合事务性质在两个数据存储介质中进行挑选。

在缓存除形式中,可以挑选先更新数据库,然后使缓存失效(Cache Aside Pattern),这样可以保证最新和最准确的数据一定会存储在数据库中。这种方法可以保证数据库中的中心事务数据是可信的,但会导致更新逻辑更杂乱,体系处理更新的耗时更长。关于非中心数据的更新,可以挑选后写缓存形式(Write Behind Cache Pattern),只需更新缓存即可,以完成快速呼应。但是,这种方法容易导致数据纷歧致,即数据库中的数据纷歧定是最可信的数据。

因而,不同的更新战略实际上是权衡最新数据放置的方位和体系功能的一种平衡。需求依据事务场景做出折衷挑选。在中心事务数据的更新中,优先挑选将最新数据放置在数据库中,以保证数据的可信性。而关于非中心数据的更新,可以考虑运用缓存来进步体系功能,但需求留意数据一致性的问题。

彩蛋事例

在这里,我向咱们引荐一本关于JVM优化和调优的实战系列书籍,《浅显易懂Java虚拟机 — JVM原理与实战》。这本书是最新出书的,内容涵盖了与咱们当前工作和开发实例密切相关的技能和实战事例。经过学习这本书,咱们可以深化了解Java虚拟机的原理,并经过实践掌握优化和调优的技巧。我诚挚地引荐这本书给咱们,信任它将为咱们的工作和技能发展带来巨大的收益。期望咱们可以抽出时刻多多学习一下这本名贵的资料

【分布式技术专题】「缓存解决方案」一文带领你好好认识一下企业级别的缓存技术解决方案的运作原理和开发实战(数据更新场景策略和方案分析)
【当当-点击链接】【京东-点击链接】