Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 是否可以锁定MongoDB中的某些条目,并执行不考虑锁定记录的查询?_Spring_Mongodb - Fatal编程技术网

Spring 是否可以锁定MongoDB中的某些条目,并执行不考虑锁定记录的查询?

Spring 是否可以锁定MongoDB中的某些条目,并执行不考虑锁定记录的查询?,spring,mongodb,Spring,Mongodb,我有一个mongoDB,它包含一个“任务”列表和两个执行者列表。这两个执行者必须从数据库中读取一个任务,将其保存在“in_EXECUTION”状态并执行该任务。当然,我不希望我的两个执行者执行相同的任务,这是我的问题 我使用事务查询。这样,当执行者试图更改任务的状态时,它会得到“写入异常”,必须重新启动并读取新任务。这种方法的问题是,有时执行器在能够正确保存任务状态的更改并执行新任务之前会出现大量错误。所以我好像只有一个执行者 注: -我不想在读/写时阻塞整个数据库,因为这样会减慢整个过程。 -

我有一个mongoDB,它包含一个“任务”列表和两个执行者列表。这两个执行者必须从数据库中读取一个任务,将其保存在“in_EXECUTION”状态并执行该任务。当然,我不希望我的两个执行者执行相同的任务,这是我的问题

我使用事务查询。这样,当执行者试图更改任务的状态时,它会得到“写入异常”,必须重新启动并读取新任务。这种方法的问题是,有时执行器在能够正确保存任务状态的更改并执行新任务之前会出现大量错误。所以我好像只有一个执行者

注: -我不想在读/写时阻塞整个数据库,因为这样会减慢整个过程。 -我认为有必要保存任务的状态,因为这可能是一项很长的任务

我问是否可以只锁定某些记录,并对“未锁定”记录执行查询,但解决我问题的每一条建议都会得到非常感谢

提前谢谢

编辑1: 对不起,我简化了上面问题中的概念。实际上,我提取了n条我必须发送的消息。我必须在100个消息块中发送这些消息,所以我的执行者将在100个消息块中分割提取的消息,并基本上将它们传递给其他执行者。 每个执行器提取消息,然后用新状态更新它们。我希望这一点现在更清楚

@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
public List<PushMessageDB> assignPendingMessages(int limitQuery, boolean sortByClientPriority,
        LocalDateTime now, String senderId) {
    final List<PushMessageDB> messages = repositoryMessage.findByNotSendendAndSpecificError(limitQuery, sortByClientPriority, now);
    long count = repositoryMessage.updateStateAndSenderId(messages, senderId, MessageState.IN_EXECUTION);
    return messages;
}
@Transactional(readOnly=false,propagation=propagation.REQUIRED)
公共列表assignPendingMessages(int-limitQuery、boolean-sortByClientPriority、,
LocalDateTime now,字符串senderId){
最终列表消息=repositoryMessage.findByNotSendendAndSpecificError(limitQuery,sortByClientPriority,现在);
long count=repositoryMessage.updateStateAndSenderId(messages,senderId,MessageState.IN_执行);
返回消息;
}
数据库更新:

public long updateStateAndSenderId(List<String> ids, String senderId, MessageState messageState) {
    Query query = new Query(Criteria.where(INTERNAL_ID).in(ids));
    Update update = new Update().set(MESSAGE_STATE, messageState).set(SENDER_ID, senderId);
    return mongoTemplate.updateMulti(query, update, PushMessageDB.class).getModifiedCount();
}
public long updateStateAndSenderId(列表ID、字符串senderId、消息状态MessageState){
Query Query=新查询(Criteria.where(INTERNAL_ID).in(ID));
Update Update=new Update().set(MESSAGE\u STATE,messageState).set(SENDER\u ID,senderId);
返回mongoTemplate.updateMulti(查询、更新、PushMessageDB.class).getModifiedCount();
}

您必须逐个执行锁定

如果试图一次锁定100条记录,同时使用第二个进程也锁定100条记录(两者之间没有任何协调),几乎肯定会导致重叠集,除非您有大量可用记录可供选择


根据您的应用程序,只要单个工作线程没有过载,所有工作都由一个线程完成(另一个线程只是“热备用”)也是可以接受的。

您不能仅使用原子更新将
$set
状态设置为“IN_EXECUTION”,而仅当它尚未处于“IN_EXECUTION”状态时?谢谢你的回答,但我不认为我解决了这个问题“…这种方法的问题是,有时执行者在能够正确保存任务状态的更改并执行新任务之前会出现很多错误。因此,就好像我只有一个执行者。”对吗?为什么会出现很多错误?什么错误?原子更新不会产生错误,它要么更新了文档,要么没有(如果另一台服务器碰巧同时更新了文档,但这应该是非常罕见的,因为选择和更新下一个任务之间的间隔只有几毫秒)。当我遇到这个错误时,这意味着另一台服务器正在执行任务,所以我必须从数据库中读取其他任务,而不是执行我刚才读取的任务。这种情况经常发生吗?另一台服务器处理该任务需要多长时间?在此之前,您无法获取另一个任务(通过重试任务选择事务)?队列中只有一个任务吗?