mapr-fs 架构
在上一篇文章中,我们讨论了使该分布式数据库特别有趣的MapR-DB的某些功能。 在这篇文章中,我们打算通过提出一个特定的用例来继续这项工作。
问题
要解决的问题可以描述如下。
一连串的消息正在通过流。 每个值都有一个id
和一个count
。 对于每个id
,我们必须使用流中出现的count
通过增加其值来更新数据库中的现有count
。
下图显示了该问题的示例。
有多种方法可以解决此问题。 一种可能是通过读取存储在数据库中的给定id
的当前状态,然后使用流中的值更新其count
,以最终将更新后的值保存回数据库。
让我们详细了解这个过程。
如上图所示,为了更新数据库中的状态,我们需要首先从数据库中加载每个数据,将值与传入流连接起来以计算新状态,最后保存新状态。状态返回到持久存储。 通常,无论我们选择使用哪种数据库技术,无论是MapR-DB还是任何其他持久性技术,我们都必须遵循相同的过程。
以下代码显示了如何使用与MapR-ES(MapR Streams技术)和MapR-DB集成的Apache Spark来实现这一想法。
重要的是要注意,在每个流幻灯片上,我们都是从MapR-DB(或其他任何Db)加载的,并将加载的数据帧与流合并。 然后,我们将最近计算出的当前新状态保存回数据库。
这个过程是完全有意义的,而且在大多数数据库中,都无法解决。 但是,每次我们在流上接收数据时,执行这些操作的成本很高。
MapR-DB突变
当其他人缺少短裤时,MapR-DB会发光。
MapR-DB能够以增量方式更新文档,而无需先加载它们。 更具体地说,可以仅更新文档的某些字段,而无需在文档级别上进行其他操作。
快速提出的一个合理问题是:考虑到MapR-DB的分布式性质,此更新是否原子应用? 答案是肯定的。
让我们首先编写一些代码来证明最后一条语句,然后使用该概念来解决有问题的问题。
我们可以从下面的代码片段开始。
正如我们所看到的, run
功能将递增count
对于给定的id
,具体而言, times
次。
基于此代码,我们可以通过创建多个线程并在每个线程上执行UpdateSameId.run
来创建另一个并行执行相同功能的函数。
我们可以通过以下方式运行上面的代码。
这将在MapR-DB上打印出每个文档的最终状态,并且可以肯定地说,更新是原子应用的。
整个代码是Reactor项目的一部分,您可以在这里找到 。
如我们所见,即使在多线程或多处理器环境中运行,MapR-DB仍可确保值始终(原子)更新。 为了增加并行度,我们可以使用Apache Spark编写类似的代码,但是结果将是相同的。 我们尝试了。
基于这些发现,我们可以改进原始应用程序以解决我们首先提出的问题。
让我们首先从MapR-DB中删除首先加载的部分,然后将其替换为更新。
让我们回顾一下我们原始应用程序中的一些重要更改。
首先,根本不需要从数据库加载当前状态。 相反,我们创建必要的突变并将其与MapR-DB并行应用。
其次,我们大大减少了Spark必须执行的任务数量,提高了整体性能,同时减少了数据库的负载。
第三,代码更简单,更优雅,更易于理解,增加了可维护的索引,同时使其他人的生活更轻松。
最后,我们将为每个分区创建一个连接,因此在增加并行度的同时避免了任何Spark序列化问题,因为每个分区操作都将同时运行(Spark magic在这里起作用)。
在流程运行之后,我们可以放心,我们将通过最新方法正确,有效地更新我们的数据。
结论
如前所述,MapR-DB是一个非SQL数据库,具有非常有趣的功能,值得探讨。 这些功能不仅使其成为高性能和分布式工作负载的首选,还使我们作为问题解决者的生活变得更加轻松。 即使MapR-DB具有固有的分布式特性,我们也可以从像这样的复杂系统中遇到的许多问题中抽象出来,并轻松地使用MapR-DB来解决市场上最复杂的业务问题。
请阅读与MapR-DB交互 有关如何使用MapR-DB及其周围工具的更全面的介绍。
翻译自: https://hackernoon.com/mapr-db-atomic-document-updates-d54f535b589
mapr-fs 架构