【问题标题】:Handling embargoed content scenario in MarkLogic在 MarkLogic 中处理禁运内容场景
【发布时间】:2014-10-28 18:12:40
【问题描述】:

我有一个 MarkLogic 7 数据库,其中插入了几个文档,每个文档都有自己的 created-onreleased-on。例如,如果一个文档在 1400 小时插入到数据库中,并且其 released-on 值为 1700 小时,那么我需要将此文档发布到外部 REST 服务1700 小时。

我尝试了以下选项:

  1. 配置一个 CPF 管道,这样每当插入一个文档时,它的 released-on 值就会被读取,并创建一个 计划任务 以根据从 released-on 读取的时间戳值触发。

    以下是对这种方法的查询/观察:

    1. 由于管理配置操作 API 不是受事务保护的操作,我需要强制锁定某些 URI,以便从并行运行的 CPF 操作模块中创建计划任务。 详情read here

    2. 当我插入 1000 个文档时,CPF 操作模块需要大约 20 分钟来触发和创建 1000 个基于计划的任务在从插入的文档中读取的released-on 值上。

    3. 如何根据从文档中读取的released-on 值将触发 CPF 操作模块的文档的 URI 传递给从 CPF 操作模块中创建的计划任务?

  2. 配置一个 CPF 管道,这样每当插入一个文档时,它的 released-on 值就会被读取,并且 xdmp:sleep() 在当前日期时间和 released-on 的值之间剩余的毫秒数内被调用文件。

    以下是对这种方法的查询/观察:

    1. 触发 CPF 操作模块的任务服务器线程保持占用状态,并且在从其中调用 xdmp:sleep() 时不会释放,因此在任何时候都会为最多 16 个文档和其他文件触发 CPF 操作模块留在队列中。

    2. 有什么方法可以将睡眠线程配置为非活动状态,并让其他排队的操作模块被触发,当睡眠持续时间过去后,它会再次变为活动状态?

  3. 按照here 的描述配置一个多步 CPF 管道,在该管道中,文档一直在两个状态之间来回切换,直到 released-on 时间戳到达。

    以下是对这种方法的查询/观察:

    1. 即使插入 30 个文档,观察到的 CPU 利用率仍为 100%

在所有尝试中,即使对于 1000 个文档,也会使用大量系统资源(CPU 和 RAM)。我需要找到一种可以满足 100K 文档的方法。

如果上述方法可以进行任何改进,或者 MarkLogic 提供了一些其他方法来有效处理此类情况,请告诉我。

【问题讨论】:

  • 我认为选项 2 和 3 只会给您带来问题。一个更好的问题是为什么创建 1000 个计划任务需要 20 分钟?您是否为所有插入的文档使用相同的 URI 锁定?将日志级别设置为调试,并检查错误日志中的 DEADLOCK 消息。这应该让您了解您的性能问题是否与锁定有关。
  • @wst:是的,我使用相同的 URI 锁定:使用 xdmp:lock-for-update("/sample.xml") 完整的 CPF 操作模块已发布 here
  • 插入 1000 个全部锁定在同一个 URI 上的文档听起来像是您的问题。使用插入文档的唯一 URI;然后所有其他任务可以并行运行。或者,查看多语句事务,它可以在单独的事务中串行执行表达式。
  • @wst 我尝试锁定使用xdmp:lock-for-update($cpf:document-uri) 触发CPF 操作模块的文档uri,但在这种情况下,当我并行插入多个文档时,所有文档都会触发CPF 操作模块但只有一个计划任务被创建。更多read here
  • 啊,我明白了。我仍然怀疑问题可能是太多进程争夺该锁。您可以返回到您的单 URI 锁,让 CPF 作业 xdmp:spawn 实际执行任务。那么您最多会有 N(N = 任务服务器线程)任务竞争锁,而不是全部 1000。将 N 减少到 2 或 1,您可能会得到改进。值得一试。

标签: scheduled-tasks marklogic


【解决方案1】:

您可以设置一个计划作业,例如每 10 分钟运行一次并查找准备发布的文档,而不是 CPF。该作业将查找 released-on 值介于 fn:current-dateTime() 和作业上次运行时间之间的文档,我会将其保存在数据库中。

对于这些文档中的每一个,您都会生成一个任务来发布文档,这样一个错误就不会给其他文档带来问题。循环完成后,将当前时间保存在数据库中,以备下次使用。

这 10 分钟的窗口可以根据您的喜好大小,这取决于您对延迟的容忍度。

【讨论】:

  • 一定要防止重叠的计划任务。我会用信号量来做到这一点:在任务中,在/tasks/my-task-name 之类的任意URI 上调用xdmp:lock-for-update。该 URI 不需要存在,但锁定它会阻止多个任务尝试处理相同的文档。
  • @mblakele 现在我创建了一个 Minutely Scheduled Task,它在 entities 集合中查找 released-on 值已传递的文档并将它们发布到外部服务和将它们移动到 dispatched 集合。但是我在这种方法中面临的问题是,如果我通过 [task host] (docs.marklogic.com/…) 创建一个分钟计划任务并且该主机已关闭,那么计划任务根本不会被执行。如果我将任务主机留空 (),则计划任务将在 ALL 主机上执行。
  • 有什么方法可以确保在集群环境中的 任何一个 主机(不是任何特定主机)上执行 Minutely Schedule Task 以退出失败情况?
  • 您可以在所有主机上以交错的时间间隔设置任务。在一个有十台主机的集群中,每台主机每十分钟启动一次任务,它们的开始时间会有所不同。加入 mblakele 的信号量以确保一次只有一个信号量。那么如果一台主机宕机,就意味着你有两分钟的长间隔。
  • @DaveCassel 澄清一下,让我借助一个示例来解释我的理解:我有一个 3 节点集群,因此我将为每个节点创建一个计划任务每 3 分钟运行一次。节点 1 于 10:00 开始,节点 2 于 10:01 开始,节点 3 于 10:02 开始。现在,如果节点 1 上的计划任务在 10:03 和 10:04 运行,节点 2 已关闭(计划任务未执行),那么节点 3 上的计划任务将在 10:05 执行并处理 @987654326 的文档@ 位于 10:03 到 10:05 之间。因此,每个失败的节点都会增加 1 分钟的文档发布延迟。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-08
  • 1970-01-01
  • 2014-05-07
  • 2020-10-31
  • 1970-01-01
相关资源
最近更新 更多