【问题标题】:Guaranteed cache hits when retrieving data检索数据时保证缓存命中
【发布时间】:2009-06-03 11:43:30
【问题描述】:

问题设置

  1. 实体到达进行处理,并通过一系列步骤对这些实体以及可能对其他相关实体进行操作并生成一些结果;
  2. 某些实体需要实时处理,无需任何数据库访问;
  3. 目前的实现只是在数据库中查找实体,没有任何缓存。

优化时间:-)

可能的方法

简单缓存

一个简单的内存缓存有两个缺陷:

  1. 它可能会溢出,因为我们谈论的是大量实体;
  2. 它不保证在缓存中找到所需的实体,并且无法查询可用性或被要求“预加载”自身。

所以这是不行的。

实体分析+预加载

我正在考虑构建某种分析器,以找出需要为给定实体检索哪些数据,即使是大型形式,并请求缓存以带外加载所需的数据。

步骤如下:

  1. 实体到达。如果需要在内存中处理,发送缓存加载请求;
  2. 实体被放置在缓存等待队列中,直到收到缓存加载响应。如果数据可用,这可能是即时的;
  3. 发送实体进行处理并使用加载的数据;
  4. 缓存被清除。这确实有可能清除政策,但我目前并不担心这些。

问题

您对这种方法有何看法?我是否遗漏了一些可以在这种情况下应用的众所周知的数据访问模式?


更新 1:忘了说整个处理是单线程的,这确实极大地限制了选项。

【问题讨论】:

  • 能否请您澄清有关缓存的问题。我还不完全明白为什么它不是一个选项?这会比目前只有 db 命中的情况要好得多,不是吗?为什么不能预加载缓存?如果大小是个问题,分布式缓存(例如 memcached)可能会有所帮助。

标签: java sql caching jdbc


【解决方案1】:

你说:

一个简单的内存缓存有两个缺陷:

  1. 它可能会溢出,因为我们正在谈论大量的实体
  2. 它不保证在缓存中找到所需的实体,并且无法查询可用性或被要求“预加载”自身。

也许我完全误解了您的问题和需求,但这在很多层面上听起来都不正确:

  1. 许多缓存解决方案允许您定义可以存储在缓存中的元素的最大数量。达到最大尺寸后,可以根据先进先出策略或根据最近最少使用来移除项目。
  2. 缓存不应“保证在缓存中找到所需的实体”;这不是缓存的目的。
  3. 大多数缓存解决方案的 API 允许您检查缓存中是否存在密钥(事实上,如果您使用 Map 构建自己的解决方案,您仍然可以这样做...)。
  4. Ehcache 有self-populating caches,可用于允许您在需要开始检索项目之前预填充缓存(another link here)。

【讨论】:

  • 感谢您的回答。 1和2是我问题的根本原因。由于没有更好的名字,我称它为“缓存”。它是一个内存数据层,出于内存目的,它被卸载到基于磁盘的存储中。问题是我需要保证,否则股票缓存会做得很好。 4) 看起来不错,谢谢。
  • 啊,我明白了。我认为使用“缓存”这个词来表示多个事物肯定会造成混淆
【解决方案2】:

基本上,您是在尝试缓存数据库查询。当您开始使用缓存时,数据库状态可能已经改变。这是导致数据不一致的秘诀。

作为替代方法,检查您是否可以优化数据库。数据库很可能在 10 毫秒内回答查询。您甚至可以拥有索引视图等,并定期访问它,以便将其缓存在内存中。

作为另一种选择,请考虑以下情况:预取数据不会减少总工作量。实体必须等待预取,无论它是否排队。既然工作无论如何都要做,不如在队列工作进程中做呢?考虑增加工作进程的数量,这样您就可以同时处理更多队列。

编辑:正如您的评论所说,您绑定到单个工作线程:

  • 是否可以将处理分为两步?第一个进程检索数据库数据,并将丰富的实体存储在新队列中。第二个进程从新队列中读取数据,并执行涉及其他内存数据源的工作
  • 使用全局互斥锁保护其他内存中的实体。这意味着许多工作线程可以与数据库通信,而只有一个可以访问其他内存中的实体。

【讨论】:

  • 感谢您的回答。我忘了提到所有的处理都是在一个线程上完成的,因为我们正在访问其他内存数据源。
  • 编辑后:这主要是我的想法,将数据加载到不同的线程上,同时保持主处理分开。谢谢。
猜你喜欢
  • 1970-01-01
  • 2013-10-28
  • 2021-12-31
  • 2014-01-28
  • 2021-06-12
  • 2020-06-08
  • 2018-05-28
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多