5

我正在重构一个分析系统,该系统将进行大量计算,并且我需要关于可能的体系结构设计的一些想法来解决我面临的数据一致性问题。分布式分析系统上数据一致性的体系结构设计

当前的架构

我有一个队列为基础的系统,在不同的请求应用程序创建最终由工人使用的消息。

每个“请求应用”分解大的计算成小块将由工人被发送到队列和处理。

当所有作品完成时,原始“请求应用程序”将合并结果。

此外,工人为了处理请求消耗从集中式数据库(SQL Server)的信息(重要:工人不改变数据库的任何数据,只有使用它)。

Current Architecture

问题

确定。到现在为止还挺好。当我们包含更新数据库信息的Web服务时,会出现问题。这可能随时发生,但每个来自同一个“请求应用程序”的“大型计算”在数据库中看到相同的数据是至关重要的。

例如:

  1. 应用生成消息A1和A2,将其发送到队列
  2. 工人W1用于处理拾取消息A1。
  3. Web服务器更新数据库,从状态S0更改为S1
  4. 工人W2拿起消息A2进行处理

我只是不容使用数据库的状态S1有工人W2。为了使整个计算一致,它应该使用先前的S0状态。

思考

  1. 一个锁模式防止Web服务器更改数据库,同时还有与它有工人消费的信息。

    • 缺点:锁可能在很长一段时间,由于在计算形式不同的 “请求的应用” 可能会重叠(A1,B1,A2,B2,C1,B3,等)。
  2. 创建数据库和工作人员(即控制由REQ数据库缓存应用程序服务器)之间新层

    • 利弊:添加另一层可能会强加显著开销(也许? ),而且这是很多工作,因为我将不得不重写工人的持久性(很多代码)。

我未决的第二个解决方案,但它不是很有信心。

任何精彩的想法?我设计错了,还是错过了一些东西?

OBS:

  • 这是一个巨大的2层遗留系统(在C#),我们试图 演变成与作为最小的努力更具扩展性的解决方案 可能。
  • 每个工作人员可能在不同的服务器上运行。
+1

听起来非常像地图/减少我。你为什么要自己写这样的东西?我只是使用Hadoop。 – duffymo

+0

我忘了提及这是一个巨大的2层遗留系统(使用C#),我们试图用尽可能少的努力发展成为一个更具扩展性的解决方案。我相信把一切都变成哈多普将是一项艰巨的任务。 –

+0

比编写,调试和维护Hadoop已经做的更多的工作?我承诺在提交之前。 – duffymo

回答

0

谢谢大家的帮助。

因为我认为这是问题在其他情况下可能会很平常,所以我想分享我们选择的解决方案。

更彻底地思考这个问题,我明白它的真正含义。

  • 我需要某种形式的会话控制的每个作业
  • 有进程的高速缓存充当会话控制每个作业

现在计算已经发展到分布,我只需要改进我的缓存以便分发。

为了做到这一点,我们选择使用内存数据库(哈希值),作为单独的服务器部署。 (在这种情况下为Redis)。

现在,每当我开始工作的时候,我创建了一个ID为工作,并把它传递给他们的信息

当每个工人希望从数据库中的一些信息,它会:

  1. 查找在Redis的数据(与作业ID)
  2. 如果数据是在Redis的,使用数据
  3. 如果不是,从SQL加载它,并将其保存在Redis的(与作业ID)。

在作业结束时,我清除与作业ID关联的所有哈希。

1

你可以用你的数据库版本吗?

可以说,请求应用程序用ct1标记了计算的开始。现在,这个计算生成的每条消息都会加上相同的时间戳。

而且每次数据库更新都会在更新时刻标记数据库状态。因此,状态S0在时间t0上,在t1上的状态S1上等。

现在当工作人员得到消息时,它需要获得DB状态,其中更新时间是最大的,小于或等于消息时间。在你的例子中,如果A1和A2用ct1和t1> ct1标记,那么两个工作人员将检索S0而不是S1。

这当然意味着你需要持有好几个版本在你的数据库中。如果您知道您的计算必须在一段时间之后完成,您可以在一定时间后清除这些版本。

+0

你有一个好点。我可以准备每个表以允许版本化,但我需要重写整个模式。您是否知道Sql Server中的任何功能会自动执行该功能,或者至少使其更容易? –

+0

不是。但是,将时间戳记行添加到数据库模式通常不会太困难。 –

1

我喜欢选项2,特别是如果全套计算所需的数据量不是不合理的大。我假设有一种方法可以关联(通过id)属于同一个整体工作的计算吗?

当一组计算的第一消息进来,那它捡起查询数据库和所有必要去做所有的计算数据,并创建一个临时数据存储的工人。此数据存储会是什么样子将取决于很多因素(规模,结构等)什么,但它可能是一个blob /文档,在关系模式(通过的correlationID隔离)的一组数据,在一个条目企业缓存等

你需要小心当工人1和工人2二者均在同一组计算工作的情况下,因为只有他们中的一个应该创建数据存储,都需要在继续之前等待商店完全填充。

+0

我可以将计算与相同的整体工作关联起来。我可以生成一个ID并将其设置为所有计算。但是发现工作所需的所有数据对我来说是一项非常复杂的任务。我正在考虑将新服务器添加到所有工作人员将访问的体系结构中,而不是数据库。此服务器将通过作业ID对来自数据库的结果进行缓存。你怎么看 ? –

+0

难道你不是回到原来的问题吗?或者序列中的每个计算只依赖于之前计算的结果? –

+0

每个计算都是相互独立的,它们只依赖于数据库中的数据。这个“服务器”将是唯一的,充当所有与数据库连接的外观,以便它可以管理每个人在内存中的缓存。虽然不是很有信心。 –