程序员社区

缓存策略

缓存是提高系统性能的最简单方法之一。数据库可能很慢(甚至是NoSQL数据库)。

如果操作得当,缓存可以减少响应时间、减少数据库负载并节省成本。有好几种缓存策略,正确地选择缓存策略可以带来很大的不同。缓存策略取决于数据和数据访问模式。换句话说,就是数据是如何写入和读取的。例如:

  • 系统是否写操作多,读操作少?(例如日志)
  • 数据写入一次,读取多次?(例如用户配置文件)
  • 返回的数据总是唯一的吗?(如搜索查询)

手机游戏排行榜前10名的缓存策略与收集并返回用户资料的服务截然不同。选择正确的缓存策略是提高性能的关键。让我们快速看一下各种缓存策略。

Cache-Aside

这可能是最常用的缓存方法,至少在我所从事的项目中是这样。缓存位于一侧,应用程序直接与缓存和数据库交互。

缓存策略插图
cache-aside

工作原理:
1、应用程序首先检查缓存。
2、如果数据在缓存中找到,那么缓存命中。数据被读取并返回给客户端。
3、如果数据在缓存中找不到,缓存没命中。应用程序需要做一些额外的工作。通过查询数据库读取数据,将数据返回给客户端并将数据存储在缓存中,因此后续对相同数据的读取将在缓存进行。

使用场景和优缺点

Cache-aside缓存策略非常通用,最适合读操作量大的工作负载。Memcached和Redis被广泛使用在这种情况。使用cache-aside的系统对缓存故障具有弹性。如果缓存集群宕机,系统仍然可以通过直接访问数据库进行操作。(尽管如此,如果缓存在峰值负载期间故障,它也没有多大帮助。数据读取响应时间可能变得很糟糕,在最坏的情况下,导致数据库可能停止工作。)

另一个好处是,缓存中的数据模型可以不同于数据库中的数据模型。例如,多个查询产生的响应可以根据某个请求id存储在缓存。

当使用cache-aside时,最常见的写策略是直接将数据写入数据库。当这种情况发生时,缓存可能与数据库不一致。为了解决这个问题,开发人员通常使用生存时间(time To live, TTL),并继续提供过期数据,直到TTL到期。如果必须保证数据最新,开发人员要么使缓存项失效,要么使用适当的写策略,我们将在后面讨论。

Read-Through Cache

Read-through策略中缓存与数据库保持一致。当缓存没命中,它从数据库加载数据,填充缓存并将其返回给应用程序。

缓存策略插图1
Read-Through

cache-aside策略和read-through策略都是惰性加载数据,也就是说,只有在第一次读取数据时才加载数据到缓存。

使用场景和优缺点

Read-through和cache-aside非常相似,但至少有两个关键的区别:
1、在cache-aside中应用程序负责从数据库获取数据并写入缓存。在read-through中,这个逻辑通常由第三方库或缓存独立来完成。
2、不像cache-aside,read-through中的数据模型不能与数据库中的数据模型不同。
Read-through在读负载很高,即相同的数据被多次请求的情况下效果很好。缺点是,当数据第一次被请求时,它总是会导致缓存丢失,必须通过数据库加载数据。需要开发人员通过人工发起查询,“预热””缓存来解决这个问题。与cache-aside一样,缓存和数据库之间也可能出现数据不一致的情况,解决方案就在写策略中,我们将在下面的内容中看到。

Write-Through 缓存策略

在这种写策略中,数据首先写入缓存,然后写入数据库。缓存与数据库保持一致,写操作总是通过缓存到主数据库。

缓存策略插图2
write-through

使用场景和优缺点

就其本身而言,write-through存似乎做不了什么,实际上,它引入了额外的写延迟,因为数据首先写入缓存,然后写入数据库。但是,当与read-through策略配合使用,可以利用read-through的所有好处,还能实现数据一致性的保证,将我们从使用缓存失效技术中解脱出来。
DynamoDB Accelerator (DAX)是read-through/write-through策略的一个很好的例子。DAX与DynamoDB和你的应用程序内联。读写DynamoDB可以通过DAX完成。(注:如果你计划使用DAX,请确保你自己熟悉它的数据一致性模型,以及它如何与DynamoDB相互作用。)

Write-Around

在这里,数据直接写入数据库,只有被读取的数据才会进入缓存。

使用场景和优缺点

Write-Around可以与read-through结合使用,在数据只写一次而不经常读或从不读的情况下提供良好的性能。例如,实时日志或聊天室信息。同样地,这种模式也可以与cache-aside模式结合使用。

Write-Back

在这种策略中,应用程序将数据写入缓存,并立即返回客户端,经过一段延迟后,它将数据写回数据库。

缓存策略插图3
write-back

有时也称为write-behind。

使用场景和优缺点

write back缓存策略提高写性能,适合写量大的工作负载。当和read-through结合使用时,它适用于混合工作负载,其中最近更新和访问的数据总是在缓存中可用。
它对数据库故障具有弹性,可以容忍一些数据库停机。如果支持批处理或合并,它可以减少对数据库的整体写操作,从而降低系统负载和成本。例如DynamoDB,数据库提供者是按请求数收费的。请记住,DAX是使用write-through策略,所以如果应用程序写量大,不会看到任何成本降低。

一些开发者使用Redis实现cache-aside和write-back,以更好地在请求峰值时起作用。主要的缺点是,如果缓存失败,数据可能会永久丢失。

大多数关系数据库存储引擎(如InnoDB)在其内部默认启用write-back缓存策略。查询首先写入内存,最终刷新到磁盘。

总结

在这篇文章中,我们探索了不同的缓存策略及其优缺点。在实践中,仔细评估你的目标,理解数据访问(读/写)模式,并选择最佳策略或组合。

如果缓存策略选择错了,不符合你的目标或数据访问模式会发生什么?您可能会引入额外的延迟,或者至少缓存不能更好地发挥作用。例如,如果你选择write-through/read-through,而实际上你应该使用write-around/read-through(写入的数据被较少访问),那么你的缓存中就会有无用的垃圾。可以这样说,如果缓存空间足够大,它可能没问题。但在许多高吞吐量系统中,当内存永远不够大且服务器成本是一个问题时,正确的策略就很重要。

赞(0) 打赏
未经允许不得转载:IDEA激活码 » 缓存策略

一个分享Java & Python知识的社区