【问题标题】:Load balancing SQL reads while batch-processing?批处理时负载平衡 SQL 读取?
【发布时间】:2020-04-22 22:36:06
【问题描述】:

给定一个带有时间戳记录的 SQL 表。每隔一段时间,应用程序App0 就会执行类似foreach record in since(certainTimestamp) do process(record); commitOffset(record.timestamp) 的操作,即它会定期消耗一批“新鲜”数据,按顺序处理并在每条记录后提交成功,然后只是休眠一段合理的时间(以积累另一个批)。这适用于单个实例。但是如何对多个实例进行负载平衡?

在完全相同的环境中App0App1 同时竞争新鲜数据。这个想法是App0 执行的就绪查询不得App1 执行的相同读取查询重叠 - 这样它们就不会尝试处理相同的项目。换句话说,我需要基于 SQL 的保证,即并发读取查询返回不同的数据。这甚至可能吗?

附: Postgres 是首选。

【问题讨论】:

    标签: sql transactions load-balancing batch-processing


    【解决方案1】:

    App0 处理先前选择的记录时,App1 应该做什么的问题描述相当模糊。
    在这个答案中,我做了以下假设:

    • 所有应用程序都知道最后一个certainTimestamp是什么,并且所有应用程序在启动数据库查询时都是一样的。
    • App0 正在处理时,比如说它开始工作时发现的 10 条记录,新记录进来了。这意味着,关于certainTimestamp 的新记录堆增加了。
    • App1(或任何进一步的App)启动时,应该只处理那些尚未被其他处理的关于certainTimestamp的新记录>应用程序
    • 然而,如果 App 上发生故障/崩溃,则应在下次运行另一个 App 时选择未完成的记录。

    这可以通过锁定许多 SQL 数据库中的记录来实现。

    解决这个问题的一种方法是使用

     SELECT ... FOR UPDATE SKIP LOCKED
    

    该语句结合范围选择since(certainTimestamp) 选择并锁定所有符合条件且当前未锁定的记录。 每当一个新的 App 实例运行此查询时,它只会得到“剩下的”要做的事情并且可以处理它。

    这解决了“叠加”或处理相同数据的问题。

    剩下的就是certainTimestamp的定义和更新。 为了保持这个答案简短,我不会在这里讨论,只是将指针留给需要正确考虑的 OP,以避免出现例如由于某种原因无法处理的单个记录将certainTimestamp 保持在永久最小值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-10
      • 2021-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 2012-07-22
      • 2017-09-21
      相关资源
      最近更新 更多