簡體   English   中英

Spring mongo線程安全

[英]Spring mongo thread safety

我正在學習 spring 啟動和並發。 據我了解,當 spring 啟動收到多個請求時,它將啟動多個線程來處理請求。 我這里有一個訪問 mongo 的方法。 此方法將保存一個新的 someResult(可能包含調用者設置的一些新值)。 我的問題是,如果我的 spring 啟動 controller 有 100 個並發調用,我得到一些結果 object,設置值和保存等,會不一致嗎?

  public void upsert(SomeResult someResult) {
        String collection = this.SomeResultConfig.getCollectionSomeResultCollection();
        String queryStr = "{testingID : '%s'}";
        queryStr = String.format(queryStr, someResult.getTestingID());
        Query query = new BasicQuery(queryStr);
        List<SomeResult> someResultList = this.mongoOps.find(query, SomeResult.class, collection);
        if (someResult.size() != 0) {
            this.mongoOps.findAllAndRemove(query, collection);
        }
        this.mongoOps.save(someResult, collection);
    }

MongoDB 文檔級操作是原子的。 因此,如果多個線程修改同一個文檔,則生成的文檔將是這些更新操作的一些交錯。 如果這些更新操作更新了公共值,則結果值將是上次更新時設置的值,這是不確定的。

但是,如果您的更新操作是多步驟操作(例如讀取文檔,在 memory 中對其進行修改,然后將其重寫),那么當您編寫文檔時,無法保證您不會覆蓋另一個線程所做的更改。 對於這些類型的更新,請考慮使用 mongo 事務,以便讀取更新操作確保您更新的內容就是您讀取的內容。

如果多個線程正在處理不同的文檔,您就不會遇到任何這些問題。

是的,有可能 2 個線程會先讀取結果,然后進行修改,然后每個線程將修改寫入數據庫。 數據庫 state 以其中一個值結束 - 后一個,較早的寫入丟失 - 這稱為丟失更新現象。

除了使用具有足夠隔離級別的事務之外,您還可以使用樂觀鎖定。

@Version 注釋在 MongoDB 的上下文中提供類似於 JPA 的語法,並確保更新僅應用於具有匹配版本的文檔。 因此,版本屬性的實際值被添加到更新查詢中,這樣如果另一個操作同時更改了文檔,則更新不會產生任何影響。 在這種情況下,將引發 OptimisticLockingFailureException。 以下示例顯示了這些功能:

https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo-template.optimistic-locking

在您的代碼中,您可以決定是否要在拋出異常時重試整個操作,或者是否向用戶報告錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM