实现并行批量处理队列当我使用Informix SQL工作有可能使用简单的更新的事务隔离来创建一个处理队列是这样的:在Neo4j的Cypher支架
UPDATE Queue
SET processed_by = ?
WHERE processed_by IS NULL
ORDER BY inserted_at
LIMIT 3
这标志着一批处理器在第一个参数(?
,例如服务器名称和线程号)中最多处理3个项目(队列可能为空)。在此之后UPDATE
完成每个并行处理器上(分离的线程或机器),该队列是分片:
+-----+------------------+---------------+
| _id | inserted_at | processed_by |
+-----+------------------+---------------+
| 1 | 2017-03-07 01:15 | host2:thread3 |
| 2 | 2017-03-07 01:16 | host2:thread3 |
| 3 | 2017-03-07 01:17 | host2:thread3 |
| 4 | 2017-03-07 01:18 | host1:thread1 |
| 5 | 2017-03-07 01:19 | host1:thread1 |
| 6 | 2017-03-07 01:20 | host1:thread1 |
| 7 | 2017-03-07 01:21 | NULL |
+-----+------------------+---------------+
和每个处理器都可以在隔离自身工作对一批:
SELECT * from Queue WHERE processed_by = ?
,而他们可以肯定没有人接触他们的物品来处理。作为一个副作用,如果一个处理器死了,他们很容易从他们离开的地方拿起。
我试图实现与Cypher支架同样的事情,但我遇到了问题时,并行读取遵守相同的状态,因此更新相同的项目:
MATCH (n:Queue)
WHERE NOT exists(n.processed_by)
SET n.processed_by = $processor
RETURN n
LIMIT 3
建立在此我能够lock items并做处理与此:
MATCH (n:Queue)
SET n._LOCK_ = true
WITH n
WHERE NOT exists(n.processed_by)
SET n.processed_by = $processor
REMOVE n._LOCK_
RETURN n
LIMIT 3
的问题是,在_LOCK_
适用于所有队列的节点,而不是仅仅3如果它们中有很多,可能会导致性能下降。如果有时一个处理器会锁定所有可用项目,那么它将不会成为问题,因为其他处理器将锁定所有可用项目。
用Cypher表达这个问题的正确方法是什么?
如果可能,我想还包括订购(请参阅SQL中的inserted_at
)。
我也很乐意让它在没有限制的情况下工作,所以只需标记单个项目而不会发生冲突。
注意:我希望这可以不使用任何服务器端扩展。
您可能希望使用WITH WITH DISTINCT 1 AS忽略,因为前一次匹配的基数将保持不变。最好把它弄到一排。 – InverseFalcon
谢谢,稍后当我到达我的电脑后再尝试。我到目前为止唯一的问题(仅基于阅读本文)是为什么我们需要创建队列节点?排队的项目来自外部来源,由其他内容插入,包含要处理的数据/关系。处理器不应该创建它们,因此SQL示例中的'UPDATE'语句并没有看到'INSERT INTO'。注意:为了强调,如果没有两个查询同时运行,我的第一个Cypher示例(使用'SET')似乎可以在很大的来源上工作,但我无法保证。 (通知:@InverseFalcon) – TWiStErRob
我完全改变了我的答案,因为我最初并不理解你的问题。我还没有测试过新的答案,但对我来说似乎是合理的:-)。 – cybersam