2012-03-22 63 views
2

我正在研究收集有關某個帳戶的(last_x,counters)信息的項目。 用戶操作可能會導致生成多個業務事件。當Web上的單個用戶操作導致多個事件時,它將觸發USER HISTORY表的更新。是否有樂觀鎖定的替代方案

我們進行樂觀鎖定以確保所有事件都導致USER HISTORY表更新。

問題:

樂觀鎖定導致額外的讀取(檢測到衝突時,再次讀取和更新)和額外寫入(解決衝突之後)。

解決方案的嘗試:

  • 每一個事件的結果插入到用戶履歷表 - 更多的歷史信息,導致讀取性能較差。

有沒有其他的選擇?

+0

你能寫出記錄而不是更新嗎?因此沒有潛在的衝突。 – davidfrancis 2012-03-22 23:43:46

+0

寫入將導致網站中的用戶事件與用戶歷史記錄表中的記錄之間的一對一映射。由於它是一個有計數器變量和last_X變量的表。我們需要最新的紀錄。這意味着我們必須在加載之前對所有事件進行排序。這會導致讀取性能差。 – 2012-03-22 23:46:30

+0

立即更新它有多重要? – Ben 2012-03-22 23:52:13

回答

2

是否有重寫需要在此表上有讀取性能?

這聽起來像是某種'營業日結束'/每小時左右,客戶簡介/情報表。如果是這種情況,那麼你可以使用插入和思考數據服務技術,如Star Schema來照顧(last_x,counter)方面的事情。

如果它更關鍵和時間依賴,那麼你的模式可能不適合這項工作。您是否考慮過使用消息中間件(例如JMS)來通知並觸發其他業務事件?

由於您使用的是Oracle,你可以看看:Oracle AS

[編輯]根據討論,你的計數器信息的實時生產者/消費者。我不認爲數據庫是解決這個問題的基本方法。您可能需要守住計數器計算的目的,所以也許這樣的事情是你所需要的:

監製:初始化(重建從DB會話/ memcached的)
RECV用戶操作X - >會議/ Memcached的(ActionX)+插入到數據庫。

消費者:運行(檢查會話/ memcached的爲條件,行爲)

你甚至可以讓用戶歷史櫃檯的消費者是訂戶由生產者當計數器達到X和觸發的事件消除消費者對用戶歷史的依賴

+0

數據倉庫不是一種選擇,因爲我們需要實時數據。我們使用觸發寫入的JMS。如果有多個事件,那麼它們會觸發同時寫入相同的記錄。我們通過樂觀鎖定來解決衝突,但這會導致過度的讀取和寫入。我們想避免這種情況。 – 2012-03-23 00:13:24

+0

是否需要實時閱讀歷史記錄表?如果櫃檯達到一定水平,還有什麼需要啓動的?基本上,寫作歷史表並在歷史表上扮演兩件不同的事情?歷史需要在那裏進行覈算,但是如果計數器擊中X,需要立即發生一些事情? – 2012-03-23 00:15:21

+0

是的,我們確實採取了基於計數器和變量生命週期的操作。 – 2012-03-23 00:16:25

0

聽起來像這些多個事件遵循不同的路徑,並且每個事件導致歷史記錄。那是對的嗎?

應用程序不應該能夠控制事件並以某種方式指示其跟蹤不同路徑中的相同事件嗎?也許可能爲每個事件生成一個唯一的ID,並使該字段在數據庫中唯一,以便寫入失敗?由於獨特的約束,您可以輕鬆忽略失敗。

+0

是的。不同的事件遵循不同的路徑所以他們不知道另一個。是的,我們有一個重試邏輯,但會導致更多的讀取和寫入。我們正在努力避免這種情況。 – 2012-03-23 00:10:59

+0

在這種情況下,爲什麼不能爲每個事件生成一個UNIQUE標識符並將該標識符傳遞給該事件的每個克隆?在這種情況下,DB將通過忽略具有相同唯一ID的多個寫操作來簡單地處理唯一約束(假設您可以使您的模式對事件的ID執行唯一約束)。 – uaarkoti 2012-03-23 00:14:35

+0

如果事件ID是唯一鍵的一部分,那麼它將避免違反唯一約束。但是,如果事件A在事件B寫入之前從數據庫讀取,該怎麼辦?在這種情況下,事件A正在更新過時的信息,當它寫入時,我們失去事件B的信息,因爲唯一約束不會因事件ID而失敗。 – 2012-03-23 00:20:00