【问题标题】:Strategy to keep local cache see the same "version" of data in a distributed system保持本地缓存在分布式系统中看到相同“版本”数据的策略
【发布时间】:2016-07-29 19:15:13
【问题描述】:

我正在尝试构建一个分布式系统来运行一些性能密集型计算。一个计算可以在多个工作节点上并行完成。问题是,随着数据源不断实时变化,我们希望每个工作节点(在单个计算期间)对数据的相同“版本”进行操作,即数据库的时间点快照。这是为了避免结果不一致。

另一个问题是,每次计算的整个输入数据集可能非常大,所以目前我们在每个工作节点上保留一个本地缓存,它通过向数据源询问“差异”来定期刷新内容,因为当前本地缓存版本并将差异应用到本地缓存。

有哪些设计策略可以实现每个工作节点看到相同“版本”数据的要求(同时仍然有相当新的数据)?我想过下面的解决方案,但想看看这是否是已解决的常见模式:

  • 构建“版本控制”服务,定期查询数据源的差异并将每个差异存储为数据“版本”。工作节点的缓存与版本控制服务同步,并将其缓存数据保存在多个版本中。对于一种计算,我们确保工作节点使用相同版本的输入数据以实现一致性。此版本控制服务还应保留整个数据集的最新副本,以便工作程序节点最初加载其缓存,并在工作程序节点出现故障并重新启动时恢复本地缓存内容。

系统的一些估计参数:

  • 工人数量:10

  • 平均工作持续时间:显然我们希望它尽可能快,但假设它应该少于 2 分钟

  • 作业的输入数据(所有工作人员的总体数据):~100GB

  • 数据库大小:~1TB

【问题讨论】:

  • 请提供一些数字,例如:工人人数,平均。工作时间,平均计算持续时间,数据库大小。另外,什么是大输入数据?粗略估计就足够了,因为它们可能有助于确定一个好的解决方案。
  • 当然,我用一些估计数字更新了问题
  • 如前所述,这太笼统了,无法正确回答。基本上你想建立一个multiversion concurrency control 系统。有很多关于该主题的文献可以帮助您入门。
  • 我认为这里的需求没有 MVCC 复杂。它不必处理写入(假设写入仍然发生在其他地方),但作业引擎只需要在读取数据源时看到一致的时间点视图。
  • 您暗示如果没有(某些代理的)写入能力,这将是一个更简单的解决方案。但是,您仍然需要在可能发生写入时提取 100 GB。为此,您要么需要在提取过程中停止这些写入(锁定、提取、解锁),要么需要各种 MVCC。为简单起见,您的主存储可能已经在后台使用 MVCC(例如,以支持“快照隔离”的形式)。

标签: database architecture distributed distributed-computing distributed-system


【解决方案1】:

如果您没有绑定 MySQL 并且可以使用 Oracle,那么有一个简单的解决方案适合您:

Oracle Flashback

(我还没有找到 MySQL 闪回,如果你知道一些马达,请发表评论。)你不必创建手动快照等。你可以将它与单个数据库服务器一起使用,你的所有进程都可以读取数据,因为它在所需的时间表示。这个解决方案非常干净和强大,但需要许可证。

如果我是你,我会尝试退后一步,尝试进一步简化问题。如果不同的工作人员可以并行运行,则应适用以下内容:

  • 没有一个工人使用其他工人的输出
  • 他们都没有改变原始数据

如果这两个要求都有效,您可以使用单个数据库来存储计算等。您唯一需要关心的是交易应该仔细计划。

另一方面,在一个类似的项目中,我们使用了一个小技巧来实现这一点(作为闪回解决方案):数据库中也存储了插入时间。 (并且更新实际上是插入了新的时间戳。)所有的计算等都是通过在查询中添加

在 x 时间戳之前给我这种行的最后一个版本

使用此解决方案,我们避免了许可成本和快照维护。唯一的问题是,如果您不需要整个历史记录,它会很快吃掉您的数据库空间。为了解决这个问题,我们做了一个 cron 作业,根据时间戳清除未使用的记录。

如果你想获得更多,有一种叫做影子表的东西。关于这个主题有一篇不错的 MySQL 博客文章: http://arnab.org/blog/shadow-tables-using-mysql-triggers

【讨论】:

  • “您可以使用单个数据库来存储计算”是指将输入存储到计算中吗?
  • 实际上是输入和输出。如果你有更具体的问题,我明天会回答。 :)
  • 谢谢。我不确定为什么我们需要存储输出。存储输入似乎类似于我在问题中建议的使用数据快照服务(或我称之为“版本控制”服务)的方法。
  • 我只是假设,它需要以某种方式持久化。 :) 是的,该解决方案正在模仿 Oracle 闪回功能的行为。就我个人而言,我喜欢盒装的 Oracle,但我有点难过 Postgres 有相同的想法但未能实现它 (postgresql.org/message-id/9059865.post@talk.nabble.com)。另一种解决方案(使用触发器)也是一种不错的方法,但在内存和/或 CPU 方面可能会消耗更多资源。
【解决方案2】:

我认为你过于复杂了。对于您的任务,您只需要存储和区分当前和最新版本的数据。所以,你的脚本应该:

  1. 将最新数据标记为当前使用的数据集
  2. 删除所有旧数据
  3. 告诉工作人员使用标记的数据集
  4. 一直以来,您都在向表中添加新数据(不是更新而是添加)
  5. 转到步骤 1

【讨论】:

  • 这种方法需要更改整个数据库架构(我们不会更新现有行,而是不断添加具有新版本号的新行)。这对我们来说是不可行的,因为我们的数据库架构很大。
  • @Pinch 您的数据库架构可能很大,但您只需向每个表添加两个字段 - 时间戳和数据集 ID。当然,前提是你没有复杂的关系。无论哪种方式,您都可以通过架构重新设计或企业数据库的昂贵功能来实现所需的行为。哦,您也可以制作生产数据库的快照并允许工作人员处理快照。通过这个也将是相当昂贵的。
猜你喜欢
  • 2017-02-08
  • 2015-07-27
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 2016-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多