2011-07-26 45 views
1

我的Node.js應用程序接受來自外部的連接。每個連接處理程序在Redis上讀取一個SET,最終修改該集合,然後繼續。問題是與此同時另一個異步連接可以嘗試讀取相同的SET並嘗試更新它或根據它讀取的內容決定下一步。有沒有辦法在Redis中獲取鎖定? (Node.js)

我知道Redis盡最大努力成爲原子,但這不足以滿足我的用例。考慮一下:設置被讀取以理解它是否滿(有一個商業規則)。如果它是完整的,那麼會發生一些事情。問題是,如果只剩下一個插槽,則兩個半併發連接可以認爲每個插槽都是最後一個。我得到溢出。

我有一種方法來保持連接「等待」很短的時間,其他最終需要更新設置狀態?

我認爲這是一個極端情況,非常非常unluckely ......但你知道:)

使用另一個關鍵的「鎖」是一種選擇,或者它臭?

+3

我不想在這裏重複Salvatore的答案。他之前曾提到過這個問題。使用SETNX和WATCH來模擬鎖。 https://github.com/antirez/redis/pull/41 – alphazero

回答

2

您可能在尋找WATCHMULTI/EXEC。下面是這兩個線程遵循的模式:

WATCH sentinel_key 
GET value_of_interest 
if (value_of_interest = FULL) 
    MULTI 
    SET sentinel_key = foo 
    EXEC 
    if (EXEC returned 1, i.e. succeeded) 
     do_something(); 
    else 
     do_nothing(); 
else 
    UNWATCH 

這種工作方式是,所有的命令和EXEC之間MULTI排隊等候,但並沒有真正執行,直到EXEC被調用。當調用EXEC時,在實際執行排隊指令之前,它會檢查sentinel_key是否已設置WATCH;如果有,則返回(nil),排隊的命令將被丟棄。否則,命令將作爲一個塊自動執行,並返回執行的命令數(本例中爲1),讓您知道您贏得了比賽,並且可以調用do_something()

它在概念上類似於fork()/exec() Unix系統調用 - fork()的返回值告訴你你是哪個進程(父進程或子進程)。在這種情況下,它會告訴你是否贏得比賽。

3

如何使用blpop來鎖定。 blpop key 5等待5秒鐘以獲得key。在開始處放置項目(以標識隊列不是空的)在鍵。獲取鎖的連接應從鑰匙中刪除項目。下一個連接然後不能獲得鎖,因爲空,但blpop具有以下不錯的屬性:

多個客戶端可以阻塞相同的密鑰。他們被放入一個 隊列中,所以第一個被服務的人將會是早先開始等待 的人,並以第一個BLPOP首先服務的方式。

當獲取鎖定的連接完成任務時,它應該將項目放回隊列中,然後下一個連接等待可以獲取鎖定(項目)。

+1

似乎很需要我。我必須檢查它如何在Node.js過程中執行。 Upovote,至少:) – Claudio

相關問題