2015-10-31 77 views
1

在我們公司,我們有一個分佈在少數實例中的服務器。服務器處理用戶請求。可以並行處理來自不同用戶的請求。應該強烈地按順序執行來自同一用戶的請求。但由於平衡,他們可以到達不同的實例。目前我們使用基於Redis的分佈式鎖,但這很容易出錯,需要更多的關於併發性的工作,而不是業務邏輯。大量的單線程任務隊列

我想是這樣的(更像是一個概念):

  • 爲每個用戶
  • 隊列用戶ID命名的鮮明隊列
  • 通過請求ID標識的每個請求
  • 想象一下,來自同一用戶的兩個請求同時到達兩個不同的實例:

    1. 每個實例將其請求標識放入此用戶隊列中。
    2. 另外,它們都在本地存儲它們的請求ID。
    3. 那麼一些券商採取從「some_user_queue」頂部請求ID,並將其移動到「some_user_queue_processing」
    4. 兩個實例監聽「some_user_queue_processing」。他們偷看它,看看這是否是他們本地存儲的請求ID。如果是,那麼請處理。如果不是,那麼忽略並等待。
    5. 工作完成後,服務器將此ID從「some_user_queue_processing」中刪除。
    6. 然後再次執行步驟3。

而這一切對於很多同時發生(幾千條)不同的用戶(以及他們的隊列)的。

現在,我知道這聽起來很像的演員,但:

  1. 我們需要的解決方案需要的微小變化可能使從鎖的快速轉換。阿卡會迫使我們從頭開始重寫幾乎所有的東西。
  2. 我們需要生產準備解決方案。類星體聽起來不錯,但尚未準備好生產(更準確地說,它們的Galaxy系列)。
  3. 我工作的頂部非常保守,他們根本不想要我們需要支持的另一個依賴。但是我們已經使用Redis(用於分佈式鎖),所以我想也許它可以幫助解決這個問題。

感謝

+0

也許您可以評估Hazelcas對分佈式鎖的支持,請參閱http://hazelcast.org/#lock。 –

+0

假設粘性會話,它的簡單寫一個[dispatch queue](http://stackoverflow.com/questions/29889885/java-divide-incoming-work-uniformly-via-hashing-in-multithreaded-evnironments/29893297#29893297 )在Java 8中。 –

+0

你能告訴我,如果我的答案是你實際需要的嗎? –

回答

0

符合您的問題的描述是Redis Cluster的最佳解決方案。

基本上,集羣解決您的併發問題,以下列方式:

兩個(或更多)來自同一用戶的請求,將總是去同一個實例,假設你使用的用戶id作爲鍵和請求作爲值。該值必須實際上是請求的list。當你收到一個,你會將它附加到該列表。換句話說,這是您的請求隊列(每個用戶都有一個)。

集羣實現的設計使這種匹配成爲可能。它基於散佈在所有實例上的一系列散列槽。

當一個集合命令被執行時,集羣執行一個哈希操作,這會產生一個值(我們將要寫入的哈希槽),它位於特定的實例上。羣集找到包含正確範圍的實例,然後執行寫入過程。

此外,當執行得到時,羣集將執行相同的過程:它找到包含該密鑰的實例,然後獲取該值。

從鎖過渡很容易執行,因爲您只需要準備好實例(啓用集羣的指令設置爲「yes」),然後從redis-trib.rb運行集羣創建命令腳本。

去年夏天我在生產環境中使用集羣,它的表現非常好。