2017-04-03 83 views
2

考慮Spring MVC的Java Web應用程序,它提供了一些REST API防止REST客戶

假設它有很多方法,其中之一是DELETE /api/foo/{id},它顯然從數據庫中刪除foo實體,給定的id

的問題是,由於DB大數據,這個操作不是即時的,因此,如果客戶端嘗試同時執行多重刪除同一實體操作,說

DELETE /api/foo/123 X N次(錯誤地在客戶端軟件當然),

,它引起了一些DB令人不快的副作用(你知道,如果你嘗試在幾個交易刪除同一實體,這不是一般的好看)。

我的問題是:什麼是Spring MVC的最佳實踐,以防止這樣的情況呢?

我當然可以在每個這樣的更新方法(PUT/DELETE)中引入Foo id的同步。我將需要爲所有實體和所有PUT/DELETE API方法做到這一點,但我真的不想這樣做。我想這應該是一些優雅而又不錯的解決方案,如何在攔截器/ servlet級別上執行這種類型的同步,即不在控制器級別的服務上。

我還可以創建特定的攔截器,並執行那裏等着重複請求(有相同的URL和參數請求)。但是,這聽起來並不是一個優雅的解決方案(直到我將確保無法以更美觀的方式在Spring MVC中進行配置)。

+1

原則上,交易機制是爲此目的而設計的。你有什麼進一步的要求,你認爲事務回滾爲DB **中令人不快的副作用? –

+0

是的,問題是不同的數據庫對於這種事件有不同的行爲。在我的情況下,由於複雜的複製結構,我得到了某種阻塞。我通常不想從數據庫中接收和接收任何類似的例外情況,我想阻止他們的出現。 – Andremoniy

+0

我對或錯。我不知道根據我的知識,我們可以做一件事情,只是檢查數據可用的數據庫或不像getFooById(ID);如果你得到的數據比你可以刪除相同的數據,否則你可以拋出異常,數據不存在 –

回答

1

這是一個併發問題,應通過使用適當的事務和鎖定級別來處理。不幸的是,在這裏沒有單一的規模,根據你的實際需求,你可能必須實現樂觀或悲觀的鎖定,以及可能的事務級別之一(從沒有事務到可串行化事務)。

一般情況下,在網絡層面處理這種問題是一個糟糕的主意,因爲你會喜歡什麼就做要求的提問要刪除一些數據,另一種是在同一時間顯示?在SpringMVC中,常用的方法是在服務層使用事務方法。另外,您應該在持久層中聲明一個樂觀或悲觀的鎖定系統。

樂觀層通常給出更高的吞吐量,在異常終止某些交易的成本。在這種情況下,目前的最佳做法是向用戶報告問題,要求他/她再次發送他/她的請求。

+0

這種方法並沒有涵蓋我目前的麻煩。在重負載的數據庫中,幾個多重請求的相同原始的DELETE會導致一種阻塞,所以所有這些多個請求都會失敗,併發生504超時錯誤。當然,所有刪除方法本身都是在事務級別執行的。但它不包括DB本身行爲不正確的情況。 – Andremoniy

+0

504刪除請求上的超時錯誤通常是無法獲得(悲觀)鎖定的症狀。但是,這是優化數據庫訪問的難點,它很大程度上取決於數據庫本身和主要用例。我很抱歉,但我恐怕不能多說了。也許你可以嘗試用樂觀的方式替換悲觀鎖,以便像*系統忙,無法完成請求,請重試504超時錯誤,請再試一次。* –

+0

這不合適。正如我在我的問題中所寫的,直接的方式是在特定實體的ID上引入同步。這將簡單地阻止DB被鎖定,所以它不會有任何超時異常的麻煩 - 順序執行的DELETE方法將很快返回OK,因爲刪除我的API中的缺席實體是合法操作。我的問題是:是否有可能使用Spring MVC框架的現有功能在更高層次上執行相同的技巧。 – Andremoniy