redis Distributed locks(7)

1.需要保證的屬性

Safety property: Mutual exclusion(互斥). At any given moment, only one client can hold a lock.
Liveness property A: Deadlock free. Eventually it is always possible to acquire a lock, even if the client that locked a resource crashes or gets partitioned.
Liveness property B: Fault tolerance. As long as the majority of Redis nodes are up, clients are able to acquire and release locks.

2.基于備份的實(shí)現(xiàn)無法保證

//在實(shí)例中創(chuàng)建一個key牙捉,用于lock
The simplest way to use Redis to lock a resource is to create a key in an instance. The key is usually created with a limited time to live, using the Redis expires feature, so that eventually it will get released (property 2 in our list). When the client needs to release the resource, it deletes the key.
//問題霜运,如果master死了弦赖,那么無法保證挂滓,因?yàn)楦北臼钱惒降?br> Superficially this works well, but there is a problem: this is a single point of failure in our architecture. What happens if the Redis master goes down? Well, let’s add a slave! And use it if the master is unavailable. This is unfortunately not viable. By doing so we can’t implement our safety property of mutual exclusion, because Redis replication is asynchronous.
There is an obvious race condition with this model:

  • Client A acquires the lock in the master.
  • The master crashes before the write to the key is transmitted to the slave.
  • The slave gets promoted to master.
  • Client B acquires the lock to the same resource A already holds a lock for. SAFETY VIOLATION!

3.Correct implementation with a single instance

只是對于單實(shí)例仔雷,不適用集群
To acquire the lock, the way to go is the following:
//設(shè)置key的時候水醋,只有不存在NX選項(xiàng)

SET resource_name my_random_value NX PX 30000

The command will set the key only if it does not already exist (NX option), with an expire of 30000 milliseconds (PX option). The key is set to a value “myrandomvalue”. This value must be unique across all clients and all lock requests.
Basically the random value is used in order to release the lock in a safe way, with a script that tells Redis: remove the key only if it exists and the value stored at the key is exactly the one I expect to be. This is accomplished by the following Lua script:

if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

//有效避免了,鎖的沖突糯钙,安全性問題
This is important in order to avoid removing a lock that was created by another client. For example a client may acquire the lock, get blocked in some operation for longer than the lock validity time (the time at which the key will expire), and later remove the lock, that was already acquired by some other client. Using just DEL is not safe as a client may remove the lock of another client. With the above script instead every lock is “signed” with a random string, so the lock will be removed only if it is still the one that was set by the client trying to remove it.


4.The Redlock algorithm

redis的分布式算法斩箫,使用N個完全獨(dú)立Master,而不是基于復(fù)制的模式
In the distributed version of the algorithm we assume we have N Redis masters. Those nodes are totally independent, so we don’t use replication or any other implicit coordination system. We already described how to acquire and release the lock safely in a single instance. We take for granted that the algorithm will use this method to acquire and release the lock in a single instance. In our examples we set N=5, which is a reasonable value, so we need to run 5 Redis masters on different computers or virtual machines in order to ensure that they’ll fail in a mostly independent way.
In order to acquire the lock, the client performs the following operations:

  • (1)It gets the current time in milliseconds.
    獲取時間戳
  • (2)It tries to acquire the lock in all the N instances sequentially, using the same key name and random value in all the instances. During step 2, when setting the lock in each instance, the client uses a timeout which is small compared to the total lock auto-release time in order to acquire it. (設(shè)置一個timeout過期時間)For example if the auto-release time is 10 seconds, the timeout could be in the ~ 5-50 milliseconds range. This prevents the client from remaining blocked for a long time trying to talk with a Redis node which is down: if an instance is not available, we should try to talk with the next instance ASAP.
  • (3)The client computes how much time elapsed in order to acquire the lock, by subtracting from the current time the timestamp obtained in step 1. If and only if the client was able to acquire the lock in the majority of the instances (at least 3), and the total time elapsed to acquire the lock is less than lock validity time, the lock is considered to be acquired.(只有當(dāng)大部分的master同意,并且獲取鎖的時間小于鎖的有效時間)
  • (4)If the lock was acquired, its validity time is considered to be the initial validity time minus the time elapsed, as computed in step 3.
  • (5)If the client failed to acquire the lock for some reason (either it was not able to lock N/2+1 instances or the validity time is negative), it will try to unlock all the instances (even the instances it believed it was not able to lock).(如果獲取失敗會釋放所有masters的鎖定)

5. 要點(diǎn)

(1)Retry on failure 當(dāng)獲取鎖失敗的時候要快速重試城瞎,減少裂變的可能!疾瓮!

When a client is unable to acquire the lock, it should try again after a random delay in order to try to desynchronize multiple clients trying to acquire the lock for the same resource at the same time (this may result in a split brain condition where nobody wins). Also the faster a client tries to acquire the lock in the majority of Redis instances, the smaller the window for a split brain condition (and the need for a retry), so ideally the client should try to send the SET commands to the N instances at the same time using multiplexing.

https://redis.io/topics/distlock

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脖镀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狼电,更是在濱河造成了極大的恐慌蜒灰,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肩碟,死亡現(xiàn)場離奇詭異强窖,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)腾务,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門毕骡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來削饵,“玉大人岩瘦,你說我怎么就攤上這事×耍” “怎么了启昧?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長劈伴。 經(jīng)常有香客問我密末,道長,這世上最難降的妖魔是什么跛璧? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任严里,我火速辦了婚禮,結(jié)果婚禮上追城,老公的妹妹穿的比我還像新娘刹碾。我一直安慰自己,他們只是感情好座柱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布迷帜。 她就那樣靜靜地躺著,像睡著了一般色洞。 火紅的嫁衣襯著肌膚如雪戏锹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天火诸,我揣著相機(jī)與錄音锦针,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛伞插,可吹牛的內(nèi)容都是我干的割粮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼媚污,長吁一口氣:“原來是場噩夢啊……” “哼舀瓢!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耗美,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤京髓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后商架,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堰怨,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年蛇摸,在試婚紗的時候發(fā)現(xiàn)自己被綠了备图。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡赶袄,死狀恐怖揽涮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饿肺,我是刑警寧澤蒋困,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站敬辣,受9級特大地震影響雪标,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜溉跃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一村刨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撰茎,春花似錦嵌牺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绎签,卻和暖如春枯饿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背诡必。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工奢方, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留搔扁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓蟋字,卻偏偏與公主長得像稿蹲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子鹊奖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容