2012-05-07 54 views
0


MySQL的:分割在不同的節點

我有一個兩難之間的特定表格的處理,也許你能幫助我。

我有一個表,其功能是作爲一個工作隊列。記錄被插入並需要處理。記錄處理完成後,將從隊列中刪除。 有幾個限制:

  • 只有一個實體可以處理在任何給定時間的記錄(以及由「實體」,我的意思是:一個線程,或連接到同一個數據庫在單獨的計算機)
  • 實體有些動態。它們可能會發生變化(實體數量或特徵)
  • 實體處理1個事務中的記錄
  • 處理必須並行發生(如果entity1選擇batch1,entity2必須能夠並行處理batch2,而不必等待使用實體來完成處理)
  • 一旦實體回升記錄處理,記錄整個「批」這一屬於,不得被其他實體來採摘。當我說 「批量」,我的意思是表(邏輯)安排如下:
    • ROW1(BATCH1)
    • 2行(BATCH1)
    • ROW3(batch2)
    • ROW4(batch2)
    • ROW5(batch2)
    • ....等。

因此,可以說使用實體和ENTITY2既要挑從表中處理芯片。 如果使用實體挑選ROW1,然後ENTITY2可以挑選任何其他除外BATCH1(任何其他除外ROW1和2行)。

讓抽象的處理部分,因爲它並不重要的實際處理是什麼。我很想知道如何才能阻止實體之間的衝突,只使用一個mysql數據庫,但也保持處理的並行性質。

從我的角度來看,我看到了兩個很一般方向:

  1. 使用某種狀態字段,這表明一個特定實體已經選擇了一個批次,而這一次必須從未來的排除選秀權。這個想法的缺點是,如果挑選批次的實體崩潰,那麼恢復其他實體的處理有點困難。
  2. 下使用mysql的鎖,其具有的缺點是很難保證的並行處理,而不是連續的。例如我可以做一個select ... for update,用於entity1。但是entity2不能執行相同的select ... for update,因爲這會等待第一個實體在獲取所需批次之前完成處理。

我想知道:

  • 將導致最小的編碼工作的方向
  • 是否有任何其他的方向,我在這裏失蹤(記住,實體不能保持溝通除非通過數據庫)
  • 如果有這種問題的標準模式
  • 如果您可以指向我的文章辯論這類問題。
  • 什麼是解決這個問題的最有效的方法。

因此,我在這裏的是,數據庫必須拆分表不同實體之間進行處理,並想知道做到這一點的最好辦法。我幾乎認爲我是第一個處理這個問題的人,並且想知道你的想法。 另外,請注意,這些記錄可分批通過一個非常簡單的標準(比如,batchId)

親切的問候,
安德烈被拆分。

+0

請添加一些格式到您的問題和要求特定的東西,它將很難通過這個長長的描述。 – Rachel

+0

謝謝;格式添加。我同意它有點長,但不能做其他事情。第一部分總結了描述;第二部分增加了一些解釋。 – Andrei

回答

1

嗯,從你所描述的,我沒有看到如何數據庫記錄鎖定將做你想做的。 DB鎖定說「如果此記錄不可用,請等待」,而不是「如果此記錄不可用,請選擇另一個」。

問題:批處理時,它是「完成」?我的意思是,假設節點A開始處理批次1.然後節點B出現,然而你這樣做,發現批次1在工作,所以它從批次2開始。然後節點A結束。然後節點C出現。第1批當前未處理。節點C應該獲得批1嗎?或者是第一批完成,第二批正在工作,所以我們必須繼續進行第三批?如果一個批處理完成,那麼任何數據庫鎖定顯然都不起作用,因爲它不記得過去只有一條記錄被訪問過,只有現在發生的事情。

也許別人有一個更聰明的解決方案,但我認爲你將不得不這樣做與狀態標誌。我會說:

創建一個單獨的批處理表,每批一個記錄。將外鍵放在指向批處理表的工作隊列表中。這樣我們保持數據正常化。

在批處理表中,添加狀態標誌,其中包含工作中和非工作中的值;或未經處理,在工作和處理。 (取決於批次是否完成一次「完成」。)還創建一個「處理實體」字段,用於標識正在處理此批次的實體,否則爲空。 (如果唯一的狀態是在工作中並且不在工作中,則該字段可以與在工作標誌一樣加倍:空=不工作,不空=在工作。)

當實體開始處理批處理,它將處理實體字段設置爲實體標識。完成後,它將該字段重置爲空。當實體正在尋找要處理的批次時,它會選擇「where processing_entity爲null」(當然還有其他任何條件)。

然後爲了確保一個實體沒有崩潰離開該標誌集,每當一個實體啓動時,它會檢查是否有一個表示它正在處理它的批處理記錄。如果是這樣,它肯定崩潰了,所以它重置標誌並做任何清理。

只有當一組實體是固定的,例如,如果一個實體是一個服務器,或者它是一個來自線程池的線程。如果他們能來來去去任意線程這是行不通的,因爲你不能在線程中重新啓動來告訴它留下未完成的工作指望。

我用另一種方法是把一個時間戳,說當我們開始處理批記錄。然後我有另一個過程,每隔一段時間運行一次,檢查時間戳,並比較一些合理的最大時間。如果說,我們知道這個過程應該採取幾秒鐘,我們可以看到一個帶有時間戳這是一個小時的時候,那麼處理死亡或掛,而我們應該做清理適當。這確實有一個問題,它需要你能夠說出最大的時間。

+0

處理完特定記錄後,將從隊列中刪除。另外,實體可能會改變,所以我不能指望它們重新啓動並清除處理標誌。關於與時間戳的想法 - 我發現了一些問題:如果設置足夠短的時間,那麼,根據系統負載,它可能是不夠的,它可能會與其他實體碰撞。如果你設置了足夠長的時間,那麼,如果一個實體崩潰了,需要一些時間直到另一個實體拿起它並對它做些什麼。這可能是最好的妥協,但:)謝謝! – Andrei

+0

是的,這正是時間戳的問題。 '希望我有更神奇的解決方案。以下是我想到的另一種想法,但我從未嘗試過:將實體ID放入記錄中。有一個定期喚醒的進程,並可以詢問這些實體詢問「你在使用X嗎?」如果實體回答「是」,那好,它仍然有效。如果它說「不」或者沒有回答,那肯定會發生崩潰。這當然假設你可以做某種消息傳遞。 – Jay

+0

抱歉,他們無法溝通(上面已經提到)。另外,我認爲這會帶來與那些時間戳相同的問題,爲什麼不使用它們,因爲它們更簡單? :) – Andrei

1

我對這個解決方案在過去是更新表中的列「BATCH_ID」與「獨特的無」,然後從表中使用獨特的批號選擇。

你的情況實體1

因此走來: 「UPDATE TBL SET BATCH_ID = '123456789' WHERE BATCH_ID = '0' LIMIT 1」 然後 「SELECT * FROM TBL WHERE BATCH_ID = '123456789'」

實體2出現並重復該過程與其獨特的編號'15791579'(所以它不能更新批次1),並選擇批次2等等。