日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
【求錘得錘的故事】Redis鎖從面試連環(huán)炮聊到神仙打架

又到了一周一次的分享時(shí)間啦,老規(guī)矩,還是先荒腔走板的聊聊生活。

成都創(chuàng)新互聯(lián)是一家專(zhuān)注于網(wǎng)站建設(shè)、網(wǎng)站制作綿陽(yáng)服務(wù)器托管的網(wǎng)絡(luò)公司,有著豐富的建站經(jīng)驗(yàn)和案例。

有上面的圖是讀大學(xué)的時(shí)候,一次自行車(chē)騎行途中隊(duì)友抓拍的我的照片。拍照的地方,名字叫做牛背山,一個(gè)名字很 low,實(shí)際很美的地方。

那條上山的路很難騎,超級(jí)爛路和極度變態(tài)的陡坡。真是一種折磨,是對(duì)意志力的完全考驗(yàn)。

在我們幾近崩潰,彈盡糧絕,離山頂還有近兩個(gè)多小時(shí)的時(shí)候,一個(gè)卡車(chē)司機(jī)主動(dòng)要求把我們免費(fèi)帶到山頂。我們拒絕了。

因?yàn)橥械男歉缢f(shuō)了一句話:“騎行牛背山這件事情,我這輩子只會(huì)做這一次?,F(xiàn)在的情況還不是那么糟,如果我搭車(chē)上去了,之后想起來(lái)我會(huì)有遺憾的。所以我更情愿推車(chē)?!?/p>

第二天下午山上下了一場(chǎng)暴風(fēng)雪。于是我們幾個(gè)南方孩子在這少見(jiàn)的雪景中肆意打鬧。打雪仗,堆雪人,滑雪......

晚上雪停了之后,我看到了讓我終身難忘的場(chǎng)景。星空,美麗到讓人想哭的星空!

后來(lái),在人生路上的很多場(chǎng)景中,我都會(huì)想起星哥的那句話:這件事,我這輩子只會(huì)做這一次,我不想留下遺憾。還會(huì)想起那晚璀璨的、觸手可及般的星空。

堅(jiān)持不住的時(shí)候再堅(jiān)持一下,確實(shí)是一種難能可貴的精神。

好了,說(shuō)回文章。

背景鋪墊

面試的時(shí)候,不管你的簡(jiǎn)歷寫(xiě)沒(méi)寫(xiě) Redis,它基本上是一個(gè)繞不過(guò)的話題。

為了引出本文要討論的關(guān)于 Redlock 的神仙打架的問(wèn)題,我們就得先通過(guò)一個(gè)面試連環(huán)炮:

  1. Redis 做分布式鎖的時(shí)候有需要注意的問(wèn)題?
  2. 如果是 Redis 是單點(diǎn)部署的,會(huì)帶來(lái)什么問(wèn)題?
  3. 那你準(zhǔn)備怎么解決單點(diǎn)問(wèn)題呢?
  4. 集群模式下,比如主從模式,有沒(méi)有什么問(wèn)題呢?
  5. 你知道 Redis 是怎么解決集群模式也不靠譜的問(wèn)題的嗎?
  6. 那你簡(jiǎn)單的介紹一下 Redlock 吧?
  7. 你覺(jué)得 Redlock 有什么問(wèn)題呢?

很明顯,上面是一個(gè)常規(guī)的面試連環(huán)套路題。中間還可以插入很多其他的 Redis 的考察點(diǎn),我這里就不做擴(kuò)展了。

單點(diǎn)的 Redis 做分布式鎖不靠譜,導(dǎo)致了基于 Redis 集群模式的分布式鎖解決方案的出現(xiàn)。

基于 Redis 集群模式的分布式鎖解決方案還是不靠譜,Redis 的作者提出了 Redlock 的解決方案。

Redis 作者提出的 Redlock 的解決方案,另一位分布式系統(tǒng)的大神覺(jué)得它不靠譜,于是他們之間開(kāi)始了 battle。

基于這場(chǎng) battle,又引發(fā)了更多的討論。

這場(chǎng) battle 難分伯仲,沒(méi)有最后的贏家。如果一定要選出誰(shuí)是最大的贏家的話,那一定是吃瓜網(wǎng)友。因?yàn)閷?duì)于吃瓜網(wǎng)友來(lái)說(shuō)(比如我),可以從兩位大神的交鋒中學(xué)習(xí)到很多東西。

讓你深刻的體會(huì)到:看起來(lái)那么無(wú)懈可擊的想法,細(xì)細(xì)推敲之下,并不是那么天衣無(wú)縫。

所以本文就按照下面的五個(gè)模塊展開(kāi)講述。

先來(lái)一波勸退:本文近1.2w字,謹(jǐn)慎觀看??床幌氯ゲ灰o,拉到最后點(diǎn)個(gè)“在看”。就是對(duì)于我最大的鼓勵(lì)。奧利給!

單點(diǎn)Redis

按照我的經(jīng)驗(yàn),當(dāng)面試聊到 Redis 的時(shí)候,百分之 90 的朋友都會(huì)說(shuō):Redis在我們的項(xiàng)目中是用來(lái)做熱點(diǎn)數(shù)據(jù)緩存的。

然后百分之百的面試官都會(huì)問(wèn):

Redis除了拿來(lái)做緩存,你還見(jiàn)過(guò)基于Redis的什么用法?

接下來(lái)百分之 80 的朋友都會(huì)說(shuō)到:我們還用 Redis 做過(guò)分布式鎖。

(當(dāng)然, Redis 除了緩存、分布式鎖之外還有非常非常多的奇技淫巧,不是本文重點(diǎn),大家有興趣的可以自己去了解一下。)

那么面試官就會(huì)接著說(shuō):

那你給我描述(或者寫(xiě)一下偽代碼)基于Redis的加鎖和釋放鎖的細(xì)節(jié)吧。

注意面試官這里說(shuō)的是加鎖和釋放鎖的細(xì)節(jié),魔鬼都在細(xì)節(jié)里。

問(wèn)這個(gè)問(wèn)題面試官無(wú)非是想要聽(tīng)到下面幾個(gè)關(guān)鍵點(diǎn):

關(guān)鍵點(diǎn)一:原子命令加鎖。因?yàn)橛械摹澳昃檬蕖钡奈恼轮袑?duì)于 Redis 的加鎖操作是先set key,再設(shè)置 key 的過(guò)期時(shí)間。這樣寫(xiě)的根本原因是在早期的 Redis 版本中并不支持原子命令加鎖的操作。不是原子操作會(huì)帶來(lái)什么問(wèn)題,就不用我說(shuō)了吧?如果你不知道,你先回去等通知吧。

而在 2.6.12 版本后,可以通過(guò)向 Redis 發(fā)送下面的命令,實(shí)現(xiàn)原子性的加鎖操作:

SET key random_value NX PX 30000

關(guān)鍵點(diǎn)二:設(shè)置值的時(shí)候,放的是random_value。而不是你隨便扔個(gè)“OK”進(jìn)去。

先解釋一下上面的命令中的幾個(gè)參數(shù)的含義:

random_value:是由客戶(hù)端生成的一個(gè)隨機(jī)字符串,它要保證在足夠長(zhǎng)的一段時(shí)間內(nèi)在所有客戶(hù)端的所有獲取鎖的請(qǐng)求中都是唯一的。

NX:表示只有當(dāng)要設(shè)置的 key 值不存在的時(shí)候才能 set 成功。這保證了只有第一個(gè)請(qǐng)求的客戶(hù)端才能獲得鎖,而其它客戶(hù)端在鎖被釋放之前都無(wú)法獲得鎖。

PX 30000:表示這個(gè)鎖有一個(gè) 30 秒的自動(dòng)過(guò)期時(shí)間。當(dāng)然,這里 30 秒只是一個(gè)例子,客戶(hù)端可以選擇合適的過(guò)期時(shí)間。

再解釋一下為什么 value 需要設(shè)置為一個(gè)隨機(jī)字符串。這也是第三個(gè)關(guān)鍵點(diǎn)。

關(guān)鍵點(diǎn)三:value 的值設(shè)置為隨機(jī)數(shù)主要是為了更安全的釋放鎖,釋放鎖的時(shí)候需要檢查 key 是否存在,且 key 對(duì)應(yīng)的值是否和我指定的值一樣,是一樣的才能釋放鎖。所以可以看到這里有獲取、判斷、刪除三個(gè)操作,為了保障原子性,我們需要用 lua 腳本。

(基本上能答到這幾個(gè)關(guān)鍵點(diǎn),面試官也就會(huì)進(jìn)入下一個(gè)問(wèn)題了。常規(guī)熱身送分題呀,朋友們,得記住了。)

集群模式

面試官就會(huì)接著問(wèn)了:

經(jīng)過(guò)剛剛的討論,我們已經(jīng)有較好的方法獲取鎖和釋放鎖?;赗edis單實(shí)例,假設(shè)這個(gè)單實(shí)例總是可用,這種方法已經(jīng)足夠安全。如果這個(gè)Redis節(jié)點(diǎn)掛掉了呢?

到這個(gè)問(wèn)題其實(shí)可以直接聊到 Redlock 了。但是你別慌啊,為了展示你豐富的知識(shí)儲(chǔ)備(瘋狂的刷題準(zhǔn)備),你得先自己聊一聊 Redis 的集群,你可以這樣去說(shuō):

為了避免節(jié)點(diǎn)掛掉導(dǎo)致的問(wèn)題,我們可以采用Redis集群的方法來(lái)實(shí)現(xiàn)Redis的高可用。

Redis集群方式共有三種:主從模式,哨兵模式,cluster(集群)模式

其中主從模式會(huì)保證數(shù)據(jù)在從節(jié)點(diǎn)還有一份,但是主節(jié)點(diǎn)掛了之后,需要手動(dòng)把從節(jié)點(diǎn)切換為主節(jié)點(diǎn)。它非常簡(jiǎn)單,但是在實(shí)際的生產(chǎn)環(huán)境中是很少使用的。

哨兵模式就是主從模式的升級(jí)版,該模式下會(huì)對(duì)響應(yīng)異常的主節(jié)點(diǎn)進(jìn)行主觀下線或者客觀下線的操作,并進(jìn)行主從切換。它可以保證高可用。

cluster (集群)模式保證的是高并發(fā),整個(gè)集群分擔(dān)所有數(shù)據(jù),不同的 key 會(huì)放到不同的 Redis 中。每個(gè) Redis 對(duì)應(yīng)一部分的槽。

(上面三種模式也是面試重點(diǎn),可以說(shuō)很多道道出來(lái),由于不是本文重點(diǎn)就不詳細(xì)描述了。主要表達(dá)的意思是你得在面試的時(shí)候遇到相關(guān)問(wèn)題,需要展示自己是知道這些東西的,都是面試的套路。)

在上面描述的集群模式下還是會(huì)出現(xiàn)一個(gè)問(wèn)題,由于節(jié)點(diǎn)之間是采用異步通信的方式。如果剛剛在 Master 節(jié)點(diǎn)上加了鎖,但是數(shù)據(jù)還沒(méi)被同步到 Salve。這時(shí) Master 節(jié)點(diǎn)掛了,它上面的鎖就沒(méi)了,等新的 Master 出來(lái)后(主從模式的手動(dòng)切換或者哨兵模式的一次 failover 的過(guò)程),就可以再次獲取同樣的鎖,出現(xiàn)一把鎖被拿到了兩次的場(chǎng)景。

鎖都被拿了兩次了,也就不滿(mǎn)足安全性了。一個(gè)安全的鎖,不管是不是分布式的,在任意一個(gè)時(shí)刻,都只有一個(gè)客戶(hù)端持有。

Redlock簡(jiǎn)介

為了解決上面的問(wèn)題,Redis 的作者提出了名為 Redlock 的算法。

在 Redis 的分布式環(huán)境中,我們假設(shè)有 N 個(gè) Redis Master。這些節(jié)點(diǎn)完全互相獨(dú)立,不存在主從復(fù)制或者其他集群協(xié)調(diào)機(jī)制。

前面已經(jīng)描述了在單點(diǎn) Redis 下,怎么安全地獲取和釋放鎖,我們確保將在 N 個(gè)實(shí)例上使用此方法獲取和釋放鎖。

在下面的示例中,我們假設(shè)有 5 個(gè)完全獨(dú)立的 Redis Master 節(jié)點(diǎn),他們分別運(yùn)行在 5 臺(tái)服務(wù)器中,可以保證他們不會(huì)同時(shí)宕機(jī)。

從官網(wǎng)上我們可以知道,一個(gè)客戶(hù)端如果要獲得鎖,必須經(jīng)過(guò)下面的五個(gè)步驟:

步驟描述來(lái)源:

http://redis.cn/topics/distlock.html

  1. 獲取當(dāng)前 Unix 時(shí)間,以毫秒為單位。
  2. 依次嘗試從 N 個(gè)實(shí)例,使用相同的 key 和隨機(jī)值獲取鎖。在步驟 2,當(dāng)向 Redis 設(shè)置鎖時(shí),客戶(hù)端應(yīng)該設(shè)置一個(gè)網(wǎng)絡(luò)連接和響應(yīng)超時(shí)時(shí)間,這個(gè)超時(shí)時(shí)間應(yīng)該小于鎖的失效時(shí)間。例如你的鎖自動(dòng)失效時(shí)間為 10 秒,則超時(shí)時(shí)間應(yīng)該在 5-50 毫秒之間。這樣可以避免服務(wù)器端 Redis 已經(jīng)掛掉的情況下,客戶(hù)端還在死死地等待響應(yīng)結(jié)果。如果服務(wù)器端沒(méi)有在規(guī)定時(shí)間內(nèi)響應(yīng),客戶(hù)端應(yīng)該盡快嘗試另外一個(gè) Redis 實(shí)例。
  3. 客戶(hù)端使用當(dāng)前時(shí)間減去開(kāi)始獲取鎖時(shí)間(步驟 1 記錄的時(shí)間)就得到獲取鎖使用的時(shí)間。當(dāng)且僅當(dāng)從大多數(shù)(這里是 3 個(gè)節(jié)點(diǎn))的 Redis 節(jié)點(diǎn)都取到鎖,并且使用的時(shí)間小于鎖失效時(shí)間時(shí),鎖才算獲取成功。
  4. 如果取到了鎖,key 的真正有效時(shí)間等于有效時(shí)間減去獲取鎖所使用的時(shí)間(步驟 3 計(jì)算的結(jié)果)。
  5. 如果因?yàn)槟承┰?,獲取鎖失敗(沒(méi)有在至少 N/2+1 個(gè)Redis實(shí)例取到鎖或者取鎖時(shí)間已經(jīng)超過(guò)了有效時(shí)間),客戶(hù)端應(yīng)該在所有的 Redis 實(shí)例上進(jìn)行解鎖(即便某些 Redis 實(shí)例根本就沒(méi)有加鎖成功)。

通過(guò)上面的步驟我們可以知道,只要大多數(shù)的節(jié)點(diǎn)可以正常工作,就可以保證 Redlock 的正常工作。這樣就可以解決前面單點(diǎn) Redis 的情況下我們討論的節(jié)點(diǎn)掛掉,由于異步通信,導(dǎo)致鎖失效的問(wèn)題。

但是,還是不能解決故障重啟后帶來(lái)的鎖的安全性的問(wèn)題。你想一下下面這個(gè)場(chǎng)景:

我們一共有 A、B、C 這三個(gè)節(jié)點(diǎn)。

  1. 客戶(hù)端 1 在 A,B 上加鎖成功。C 上加鎖失敗。
  2. 這時(shí)節(jié)點(diǎn) B 崩潰重啟了,但是由于持久化策略導(dǎo)致客戶(hù)端 1 在 B 上的鎖沒(méi)有持久化下來(lái)。
  3. 客戶(hù)端 2 發(fā)起申請(qǐng)同一把鎖的操作,在 B,C 上加鎖成功。
  4. 這個(gè)時(shí)候就又出現(xiàn)同一把鎖,同時(shí)被客戶(hù)端 1 和客戶(hù)端 2 所持有了。

(接下來(lái)又得說(shuō)一說(shuō)Redis的持久化策略了,全是知識(shí)點(diǎn)啊,朋友們)

比如,Redis 的 AOF 持久化方式默認(rèn)情況下是每秒寫(xiě)一次磁盤(pán),即 fsync 操作,因此最壞的情況下可能丟失 1 秒的數(shù)據(jù)。

當(dāng)然,你也可以設(shè)置成每次修改數(shù)據(jù)都進(jìn)行 fsync 操作(fsync=always),但這會(huì)嚴(yán)重降低 Redis 的性能,違反了它的設(shè)計(jì)理念。(我也沒(méi)見(jiàn)過(guò)這樣用的,可能還是見(jiàn)的太少了吧。)

而且,你以為執(zhí)行了 fsync 就不會(huì)丟失數(shù)據(jù)了?天真,真實(shí)的系統(tǒng)環(huán)境是復(fù)雜的,這都已經(jīng)脫離 Redis 的范疇了。上升到服務(wù)器、系統(tǒng)問(wèn)題了。

所以,根據(jù)墨菲定律,上面舉的例子:由于節(jié)點(diǎn)重啟引發(fā)的鎖失效問(wèn)題,總是有可能出現(xiàn)的。

為了解決這一問(wèn)題,Redis 的作者又提出了延遲重啟(delayed restarts)的概念。

意思就是說(shuō),一個(gè)節(jié)點(diǎn)崩潰后,不要立即重啟它,而是等待一定的時(shí)間后再重啟。等待的時(shí)間應(yīng)該大于鎖的過(guò)期時(shí)間(TTL)。這樣做的目的是保證這個(gè)節(jié)點(diǎn)在重啟前所參與的鎖都過(guò)期。相當(dāng)于把以前的帳勾銷(xiāo)之后才能參與后面的加鎖操作。

但是有個(gè)問(wèn)題就是:在等待的時(shí)間內(nèi),這個(gè)節(jié)點(diǎn)是不對(duì)外工作的。那么如果大多數(shù)節(jié)點(diǎn)都掛了,進(jìn)入了等待。就會(huì)導(dǎo)致系統(tǒng)的不可用,因?yàn)橄到y(tǒng)在TTL時(shí)間內(nèi)任何鎖都將無(wú)法加鎖成功。

Redlock 算法還有一個(gè)需要注意的點(diǎn)是它的釋放鎖操作。

釋放鎖的時(shí)候是要向所有節(jié)點(diǎn)發(fā)起釋放鎖的操作的。這樣做的目的是為了解決有可能在加鎖階段,這個(gè)節(jié)點(diǎn)收到加鎖請(qǐng)求了,也set成功了,但是由于返回給客戶(hù)端的響應(yīng)包丟了,導(dǎo)致客戶(hù)端以為沒(méi)有加鎖成功。所有,釋放鎖的時(shí)候要向所有節(jié)點(diǎn)發(fā)起釋放鎖的操作。

你可以覺(jué)得這不是常規(guī)操作嗎?

有的細(xì)節(jié)就是這樣,說(shuō)出來(lái)后覺(jué)得不過(guò)如此,但是有可能自己就是想不到這個(gè)點(diǎn),導(dǎo)致問(wèn)題的出現(xiàn),所以我們才會(huì)說(shuō):細(xì)節(jié),魔鬼都在細(xì)節(jié)里。

好了,簡(jiǎn)介大概就說(shuō)到這里,有興趣的朋友可以再去看看官網(wǎng),補(bǔ)充一下。

中文:http://redis.cn/topics/distlock.html

英文:https://redis.io/topics/distlock

好了,經(jīng)過(guò)這么長(zhǎng),這么長(zhǎng)的鋪墊,我們終于可以進(jìn)入到神仙打架環(huán)節(jié)。

神仙打架

神仙一:Redis 的作者 antirez 。有的朋友對(duì)英文名字不太敏感,所以后面我就叫他卷發(fā)哥吧。

神仙二:分布式領(lǐng)域?qū)<?Martin Kleppmann,我們叫他長(zhǎng)發(fā)哥吧。

看完上面兩位神仙的照片,再看看我為了寫(xiě)這篇文章又日漸稀少的頭發(fā),我忍不住哭出聲來(lái)??赡苤挥薪o我點(diǎn)贊,才能平復(fù)我的心情吧。

卷發(fā)哥在官網(wǎng)介紹 Redlock 頁(yè)面的最后寫(xiě)到:如果你也是使用分布式系統(tǒng)的人員,你的觀點(diǎn)和意見(jiàn)非常重要,歡迎和我們討論。

于是,“求錘得錘”!這一錘,錘出了眾多的吃瓜網(wǎng)友,其中不乏在相關(guān)領(lǐng)域的專(zhuān)業(yè)人士。

長(zhǎng)發(fā)哥出錘

故事得從 2016年2月8號(hào) 長(zhǎng)發(fā)哥發(fā)布的一篇文章《How to do distributed locking》說(shuō)起:

文章地址:

http://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html

這一部分直接翻譯過(guò)來(lái)就是:

作為本書(shū)(《數(shù)據(jù)密集型應(yīng)用系統(tǒng)設(shè)計(jì)》)研究的一部分,我在Redis網(wǎng)站上 看到了一種稱(chēng)為Redlock的算法。該算法聲稱(chēng)在Redis實(shí)現(xiàn)容錯(cuò)的分布式鎖(或更確切地說(shuō), 租約),并且該頁(yè)面要求來(lái)自分布式系統(tǒng)人員的反饋。這個(gè)算法讓我產(chǎn)生了一些思考,因此我花了一些時(shí)間寫(xiě)了我的這篇文章。

由于Redlock已經(jīng)有10多個(gè)獨(dú)立的實(shí)現(xiàn),而且我們不知道誰(shuí)已經(jīng)在依賴(lài)此算法,因此我認(rèn)為值得公開(kāi)分享我的筆記。我不會(huì)討論Redis的其他方面,其中一些已經(jīng)在其他地方受到了批評(píng) 。

你看這個(gè)文章,開(kāi)頭就是火藥味十足:你說(shuō)要反饋,那我就給你反饋。而且你這個(gè)東西有其他問(wèn)題,我也就不說(shuō)了。(其實(shí)作者在這篇文章中也說(shuō)了,他很喜歡并且也在使用 Redis,只是他覺(jué)得這個(gè) Redlock 算法是不嚴(yán)謹(jǐn)?shù)?

長(zhǎng)發(fā)哥主要圍繞了下面的這張圖進(jìn)行了展開(kāi):

要是一眼沒(méi)看明白,我再給你一個(gè)中文版的,來(lái)自長(zhǎng)發(fā)哥于2017年出版的書(shū)《數(shù)據(jù)密集型應(yīng)用系統(tǒng)設(shè)計(jì)》:

可以看到上面的圖片中提到了申請(qǐng)租約、租約到期的關(guān)鍵詞,租約其實(shí)就是可以理解為帶超時(shí)時(shí)間的鎖。

而在書(shū)中,這張圖片的下面寫(xiě)的描述這樣的,你咂摸咂摸:

拿 HBase 舉例,其設(shè)計(jì)的目標(biāo)是確保存儲(chǔ)系統(tǒng)的文件一次只能由一個(gè)客戶(hù)端訪問(wèn),如果多個(gè)客戶(hù)端試圖同時(shí)寫(xiě)入該文件,文件就會(huì)被破壞。那么上面的圖片解釋起來(lái)就是:

  1. 客戶(hù)端 1 先去申請(qǐng)鎖,并且成功獲取到鎖。之后客戶(hù)端進(jìn)行了長(zhǎng)時(shí)間的 GC 導(dǎo)致了 STW 的情況。
  2. 在 STW 期間,客戶(hù)端 1 獲取的鎖的超時(shí)時(shí)間到了,鎖也就失效了。
  3. 由于客戶(hù)端 1 的鎖已經(jīng)過(guò)期失效了,所以客戶(hù)端 2 去申請(qǐng)鎖就可以成功獲得鎖。
  4. 客戶(hù)端 2 開(kāi)始寫(xiě)文件,并完成文件的寫(xiě)入。
  5. 客戶(hù)端 1 從 STW 中恢復(fù)過(guò)來(lái),他并不知道自己的鎖過(guò)期了,還是會(huì)繼續(xù)執(zhí)行文件寫(xiě)入操作,導(dǎo)致客戶(hù)端 2 寫(xiě)入的文件被破壞。而且可以看到,它沒(méi)有滿(mǎn)足鎖在任意時(shí)刻只有一個(gè)客戶(hù)端持有的原則,即沒(méi)有滿(mǎn)足互斥性。

書(shū)里面沒(méi)有明說(shuō),但是你品一品,這里的鎖服務(wù)難道不是在說(shuō) Redis?

有的朋友就會(huì)說(shuō)了,那客戶(hù)端 1 寫(xiě)入文件的時(shí)候,再判斷一下自己的鎖有沒(méi)有過(guò)期不就可以了嗎?

你可真是個(gè)小機(jī)靈鬼呢,那我問(wèn)你,GC 可能是發(fā)生在任何時(shí)間的,萬(wàn)一 GC 發(fā)生在判斷之后呢?

你繼續(xù)懟我,如果客戶(hù)端使用的是沒(méi)有 GC 的語(yǔ)言呢?

GC 不是導(dǎo)致線程暫停的唯一原因啊,朋友們。發(fā)生這種情況的原因有很多的,你看看長(zhǎng)發(fā)哥書(shū)里舉的例子:

上面的內(nèi)容總結(jié)起來(lái),就是就算鎖服務(wù)是正常的,但是由于鎖是有持有時(shí)間的,由于客戶(hù)端阻塞、長(zhǎng)時(shí)間的 GC 或者網(wǎng)絡(luò)原因,導(dǎo)致共享資源被一個(gè)以上的客戶(hù)端同時(shí)訪問(wèn)了。

其實(shí)上面長(zhǎng)發(fā)哥在書(shū)里直接說(shuō)了:這是不正確的實(shí)現(xiàn)。

你多品一品,上面的圖是不是有點(diǎn)像由于 Redis 鎖的過(guò)期時(shí)間設(shè)置的不合理,導(dǎo)致前一個(gè)任務(wù)還沒(méi)執(zhí)行完成,但是鎖的時(shí)間到期了,后一個(gè)任務(wù)也申請(qǐng)到了鎖。

對(duì)于這種場(chǎng)景,Redission 其實(shí)有自己的看門(mén)狗機(jī)制。但是不在這次 Redlock 的討論范圍內(nèi),所以這里就不描述了。

長(zhǎng)發(fā)哥提出的解決方案是什么呢?

他稱(chēng)為:fencing token。

長(zhǎng)發(fā)哥認(rèn)為使用鎖和租約機(jī)制來(lái)保護(hù)資源的并發(fā)訪問(wèn)時(shí),必須確保因?yàn)楫惓T?,?dǎo)致鎖過(guò)期的那個(gè)節(jié)點(diǎn)不能影響其他正常的部分,要實(shí)現(xiàn)這一目標(biāo),可以采用一直相當(dāng)簡(jiǎn)單的 fencing(柵欄)。

假設(shè)每次鎖服務(wù)在授予鎖或者租約時(shí),還會(huì)同時(shí)返回一個(gè) fencing 令牌,該令牌每次授予都會(huì)遞增。

然后,要求客戶(hù)端每次向存儲(chǔ)系統(tǒng)發(fā)送寫(xiě)請(qǐng)求時(shí),都必須包含所持有的 fencing 令牌。存儲(chǔ)系統(tǒng)需要對(duì)令牌進(jìn)行校驗(yàn),發(fā)現(xiàn)如果已經(jīng)處理過(guò)更高令牌的請(qǐng)求,則拒絕執(zhí)行該請(qǐng)求。

比如下面的圖片:

  1. 客戶(hù)端 1 獲得一個(gè)具有超時(shí)時(shí)間的鎖的同時(shí)得到了令牌號(hào) 33,但隨后陷入了一個(gè)長(zhǎng)時(shí)間的暫停直到鎖到期。
  2. 這時(shí)客戶(hù)端2已經(jīng)獲得了鎖和令牌號(hào) 34 ,然后發(fā)送寫(xiě)請(qǐng)求(以及令牌號(hào) 34 )到存儲(chǔ)服務(wù)。
  3. 接下來(lái)客戶(hù)端 1 恢復(fù)過(guò)來(lái),并以令牌號(hào) 33 來(lái)嘗試寫(xiě)入,存儲(chǔ)服務(wù)器由于記錄了最近已經(jīng)完成了更高令牌號(hào)(34 ),因此拒絕令牌號(hào) 33 的寫(xiě)請(qǐng)求。

這種版本號(hào)的機(jī)制,讓我不禁想起了 Zookeeper。當(dāng)使用 ZK 做鎖服務(wù)時(shí),可以用事務(wù)標(biāo)識(shí) zxid 或節(jié)點(diǎn)版本 cversion 來(lái)充當(dāng) fencing 令牌,這兩個(gè)都可以滿(mǎn)足單調(diào)遞增的要求。

在長(zhǎng)發(fā)哥的這種機(jī)制中,實(shí)際上就是要求資源本身必須主動(dòng)檢查請(qǐng)求所持令牌信息,如果發(fā)現(xiàn)已經(jīng)處理過(guò)更高令牌的請(qǐng)求,要拒絕持有低令牌的所有寫(xiě)請(qǐng)求。

但是,不是所有的資源都是數(shù)據(jù)庫(kù)里面的數(shù)據(jù),我們可以通過(guò)版本號(hào)去支持額外的令牌檢查的,那么對(duì)于不支持額外的令牌檢查資源,我們也可以借助這種思想繞過(guò)這個(gè)限制,比如對(duì)于訪問(wèn)文件存儲(chǔ)服務(wù)的情況,我們可以將令牌嵌入到文件名中。

總之,為了避免在鎖保護(hù)之外發(fā)生請(qǐng)求處理,需要進(jìn)行額外的檢查機(jī)制。

長(zhǎng)發(fā)哥在書(shū)中也說(shuō)到了:在服務(wù)端檢查令牌可能看起來(lái)有點(diǎn)復(fù)雜,但是這其實(shí)是推薦的正確的做法:系統(tǒng)服務(wù)不能假定所有的客戶(hù)端都表現(xiàn)的符合預(yù)期。從安全角度講,服務(wù)端必須防范這種來(lái)自客戶(hù)端的濫用。

這個(gè)就類(lèi)似于我們作為后端開(kāi)發(fā)人員,也不能相信來(lái)自前端或者其他接口過(guò)來(lái)的數(shù)據(jù),必須對(duì)其進(jìn)行校驗(yàn)。

到這里長(zhǎng)發(fā)哥鋪墊完成了,開(kāi)始轉(zhuǎn)頭指向 RedLock,他認(rèn)為 Redlock 是一個(gè)嚴(yán)重依賴(lài)系統(tǒng)時(shí)鐘的分布式鎖。

他舉了一個(gè)例子:

  1. 客戶(hù)端 1 從 Redis 節(jié)點(diǎn) A, B, C 成功獲取了鎖。由于網(wǎng)絡(luò)問(wèn)題,無(wú)法訪問(wèn) D 和 E。
  2. 節(jié)點(diǎn) C 上的時(shí)鐘發(fā)生了向前跳躍,導(dǎo)致它上面維護(hù)的鎖過(guò)期了。
  3. 客戶(hù)端 2 從 Redis 節(jié)點(diǎn) C, D, E 成功獲取了同一個(gè)資源的鎖。由于網(wǎng)絡(luò)問(wèn)題,無(wú)法訪問(wèn) A 和 B。
  4. 現(xiàn)在,客戶(hù)端 1 和客戶(hù)端 2 都認(rèn)為自己持有了鎖。

這樣的場(chǎng)景是可能出現(xiàn)的,因?yàn)?Redlock 嚴(yán)重依賴(lài)系統(tǒng)時(shí)鐘,所以一旦系統(tǒng)的時(shí)間變得不準(zhǔn)確了,那么該算法的安全性也就得不到保障了。

長(zhǎng)發(fā)哥舉這個(gè)例子其實(shí)是為了輔佐他前面提出的觀點(diǎn):一個(gè)好的分布式算法應(yīng)該是基于異步模型的,算法的安全性不應(yīng)該依賴(lài)與任何記時(shí)假設(shè),就是不能把時(shí)間作為安全保障的。在異步模型中,程序暫停、消息在網(wǎng)絡(luò)中延遲甚至丟失、系統(tǒng)時(shí)間錯(cuò)誤這些因素都不應(yīng)該影響它的安全性,只能影響到它的活性。

用大白話說(shuō),就是在極其極端的情況下,分布式系統(tǒng)頂天了也就是在有限的時(shí)間內(nèi)不能給出結(jié)果而已,而不能給出一個(gè)錯(cuò)誤的結(jié)果。

這樣的算法實(shí)際上是存在的,比如 Paxos、Raft。很明顯,按照這個(gè)標(biāo)準(zhǔn), Redlock 的安全級(jí)別是不夠的。

而對(duì)于卷發(fā)哥提出的延遲啟動(dòng)方案,長(zhǎng)發(fā)哥還是一棒子打死:你延遲啟動(dòng)咋的?延遲啟動(dòng)還不是依賴(lài)于合理準(zhǔn)確的時(shí)間度量。

可能是長(zhǎng)發(fā)哥覺(jué)得舉這個(gè)時(shí)鐘跳躍的例子不夠好的,大家都可能認(rèn)為時(shí)鐘跳躍是不現(xiàn)實(shí)的,因?yàn)閷?duì)正確配置NTP就能擺正時(shí)鐘非常有信心。

在這種情況下,他舉了一個(gè)進(jìn)程暫??赡軐?dǎo)致算法失敗的示例:

  1. 客戶(hù)端 1 向 Redis 節(jié)點(diǎn) A, B, C, D, E 發(fā)起鎖請(qǐng)求。
  2. 各個(gè) Redis 節(jié)點(diǎn)已經(jīng)把請(qǐng)求結(jié)果返回給了客戶(hù)端 1,但客戶(hù)端 1 在收到請(qǐng)求結(jié)果之前進(jìn)入了長(zhǎng)時(shí)間的 GC 階段。
  3. 長(zhǎng)時(shí)間的 GC,導(dǎo)致在所有的 Redis 節(jié)點(diǎn)上,鎖過(guò)期了。
  4. 客戶(hù)端 2 在 A, B, C, D, E 上申請(qǐng)并獲取到了鎖。
  5. 客戶(hù)端 1 從 GC 階段中恢復(fù),收到了前面第 2 步來(lái)自各個(gè) Redis 節(jié)點(diǎn)的請(qǐng)求結(jié)果??蛻?hù)端 1 認(rèn)為自己成功獲取到了鎖。
  6. 客戶(hù)端 1 和客戶(hù)端 2 現(xiàn)在都認(rèn)為自己持有了鎖。

其實(shí)只要十分清楚 Redlock 的加鎖過(guò)程,我們就知道,這種情況其實(shí)對(duì)于 Redlock 是沒(méi)有影響的,因?yàn)樵诘?5 步,客戶(hù)端 1 從 GC 階段中恢復(fù)過(guò)來(lái)以后,在 Redlock 算法中,(我們前面 Redlock 簡(jiǎn)介的時(shí)候提到的第四步)如果取到了鎖,key 的真正有效時(shí)間等于有效時(shí)間減去獲取鎖所使用的時(shí)間。

所以客戶(hù)端1通過(guò)這個(gè)檢查發(fā)現(xiàn)鎖已經(jīng)過(guò)期了,不會(huì)再認(rèn)為自己成功獲取到鎖了。

而隨后卷發(fā)哥的回?fù)糁幸蔡岬搅诉@點(diǎn)。

但是,細(xì)細(xì)想來(lái),我覺(jué)得長(zhǎng)發(fā)哥的意圖不在于此。拋開(kāi)上面的問(wèn)題來(lái)講,他更想突出的是,一個(gè)鎖在客戶(hù)端拿到后,還沒(méi)使用就過(guò)期了,這是不好的。從客戶(hù)端的角度來(lái)看,就是這玩意不靠譜啊,你給我一把鎖,我還沒(méi)用呢,你就過(guò)期了?

除了上面說(shuō)的這些點(diǎn)外,長(zhǎng)發(fā)哥還提出了一個(gè)算是自己的經(jīng)驗(yàn)之談吧:

我們獲取鎖的用途是什么?

在他看來(lái)不外乎兩個(gè)方面,效率和正確性。他分別描述如下:

如果是為了效率,那么就是要協(xié)調(diào)各個(gè)客戶(hù)端,避免他們做重復(fù)的工作。這種場(chǎng)景下,即使鎖偶爾失效了,只是可能出現(xiàn)兩個(gè)客戶(hù)端完成了同樣的工作,其結(jié)果是成本略有增加(您最終向 AWS 支付的費(fèi)用比原本多5美分),或者帶來(lái)不便(例如,用戶(hù)最終兩次收到相同的電子郵件通知)。

如果是為了正確性,那么在任何情況下都不允許鎖失效的情況發(fā)生,因?yàn)橐坏┌l(fā)生,就可能意味著數(shù)據(jù)不一致,數(shù)據(jù)丟失,文件損壞,或者其它嚴(yán)重的問(wèn)題。(比如個(gè)患者注射了兩倍的藥劑)

最后,長(zhǎng)發(fā)哥得出的結(jié)論是:neither fish nor fowl(不倫不類(lèi))

對(duì)于提升效率的場(chǎng)景下,使用分布式鎖,允許鎖的偶爾失效,那么使用單 Redis 節(jié)點(diǎn)的鎖方案就足夠了,簡(jiǎn)單而且效率高。用 Redlock 太重。

對(duì)于正確性要求高的場(chǎng)景下,它是依賴(lài)于時(shí)間的,不是一個(gè)足夠強(qiáng)的算法。Redlock并沒(méi)有保住正確性。

那應(yīng)該使用什么技術(shù)呢?

長(zhǎng)發(fā)哥認(rèn)為,應(yīng)該考慮類(lèi)似 Zookeeper 的方案,或者支持事務(wù)的數(shù)據(jù)庫(kù)。

卷發(fā)哥回?fù)?/strong>

長(zhǎng)發(fā)哥發(fā)出《How to do distributed locking》這篇文章的第二天,卷發(fā)哥就進(jìn)行了回?fù)?,發(fā)布了名為《Is Redlock safe?》的文章。

文章地址:http://antirez.com/news/101

要說(shuō)大佬不愧是大佬,卷發(fā)哥的回?fù)魲l理清楚,行文流暢。他總結(jié)后認(rèn)為長(zhǎng)發(fā)哥覺(jué)得 Redlock 不安全主要分為兩個(gè)方面:

  1. 帶有自動(dòng)過(guò)期功能的分布式鎖,需要一種方法(fencing機(jī)制)來(lái)避免客戶(hù)端在過(guò)期時(shí)間后使用鎖時(shí)出現(xiàn)問(wèn)題,從而對(duì)共享資源進(jìn)行真正的互斥保護(hù)。馬丁說(shuō)Redlock沒(méi)有這種機(jī)制。
  2. 馬丁說(shuō),無(wú)論問(wèn)題“1”如何解決,該算法本質(zhì)上都是不安全的,因?yàn)樗鼘?duì)系統(tǒng)模型進(jìn)行了記時(shí)假設(shè),而這些假設(shè)在實(shí)際系統(tǒng)中是無(wú)法保證的。

對(duì)于第一個(gè)點(diǎn),卷發(fā)哥列了5大點(diǎn)來(lái)反駁這個(gè)問(wèn)題,其中一個(gè)重要的觀點(diǎn)是他認(rèn)為雖然 Redlock 沒(méi)有提供類(lèi)似于fencing機(jī)制那樣的單調(diào)遞增的令牌,但是也有一個(gè)隨機(jī)串,把這個(gè)隨機(jī)串當(dāng)做token,也可以達(dá)到同樣的效果啊。當(dāng)需要和共享資源交互的時(shí)候,我們檢查一下這個(gè)token是否發(fā)生了變化,如果沒(méi)有再執(zhí)行“獲取-修改-寫(xiě)回”的操作。

最終得出的結(jié)論是一個(gè)靈魂反問(wèn):既然在鎖失效的情況下已經(jīng)存在一種fencing機(jī)制能繼續(xù)保持資源的互斥訪問(wèn)了,那為什么還要使用一個(gè)分布式鎖并且還要求它提供那么強(qiáng)的安全性保證呢?

然而第二個(gè)問(wèn)題,對(duì)于網(wǎng)絡(luò)延遲或者 GC 暫停,我們前面分析過(guò),對(duì) Redlock 的安全性并不會(huì)產(chǎn)生影響,說(shuō)明卷發(fā)哥在設(shè)計(jì)的時(shí)候其實(shí)是考慮過(guò)時(shí)間因素帶來(lái)的問(wèn)題的。

但是如果是長(zhǎng)發(fā)哥提出的時(shí)鐘發(fā)生跳躍,很明顯,卷發(fā)哥知道如果時(shí)鐘發(fā)生跳躍, Redlock 的安全性就得不到保障,這是他的命門(mén)。

但是對(duì)于長(zhǎng)發(fā)哥寫(xiě)時(shí)鐘跳躍的時(shí)候提出的兩個(gè)例子:

  1. 運(yùn)維人員手動(dòng)修改了系統(tǒng)時(shí)鐘。
  2. 從NTP服務(wù)收到了一個(gè)大的時(shí)鐘更新事件。

卷發(fā)哥進(jìn)行了回?fù)簦?/p>

第一點(diǎn)這個(gè)運(yùn)維人員手動(dòng)修改時(shí)鐘,屬于人為因素,這個(gè)我也沒(méi)辦法啊,人家就是要搞你,怎么辦?加強(qiáng)管理,不要這樣做。

第二點(diǎn)從NTP服務(wù)收到一個(gè)大的時(shí)鐘更新,對(duì)于這個(gè)問(wèn)題,需要通過(guò)運(yùn)維來(lái)保證。需要將大的時(shí)間更新到服務(wù)器的時(shí)候,應(yīng)當(dāng)采取少量多次的方式。多次修改,每次更新時(shí)間盡量小。

關(guān)于這個(gè)地方的爭(zhēng)論,就看你是信長(zhǎng)發(fā)哥的時(shí)間一定會(huì)跳躍,還是信卷發(fā)哥的時(shí)間跳躍我們也是可以處理的。

關(guān)于時(shí)鐘跳躍,有一篇文章可以看看,也是這次神仙打架導(dǎo)致的產(chǎn)物:

https://jvns.ca/blog/2016/02/09/til-clock-skew-exists/

文章得出的最終結(jié)論是:時(shí)鐘跳躍是存在的。

其實(shí)我們大家應(yīng)該都經(jīng)歷過(guò)時(shí)鐘跳躍的情況,你還記得2016年的最后一天,當(dāng)時(shí)有個(gè)“閏秒”的概念嗎?導(dǎo)致2017年1月1日出現(xiàn)了07:59:60的奇觀。

打架的焦點(diǎn)

經(jīng)過(guò)這樣的一來(lái)一回,其實(shí)雙方打架的焦點(diǎn)就很明確了,就是大延遲對(duì)分布式鎖帶來(lái)的影響。

而對(duì)于大延遲給Redlock帶來(lái)的影響,就是長(zhǎng)發(fā)哥分析的那樣,鎖到期了,業(yè)務(wù)還沒(méi)執(zhí)行完。卷發(fā)哥認(rèn)為這種影響不單單針對(duì) Redlock ,其他具有自動(dòng)釋放鎖的分布式鎖也是存在一樣的問(wèn)題。

而關(guān)于大延遲的問(wèn)題,我在某社交平臺(tái)上找到了兩位神仙的下面的對(duì)話:

卷發(fā)哥問(wèn):我想知道,在我發(fā)文回復(fù)之后,我們能否在一點(diǎn)上達(dá)成一致,就是大的消息延遲不會(huì)給Redlock的運(yùn)行造成損害。

長(zhǎng)發(fā)哥答:對(duì)于客戶(hù)端和鎖服務(wù)器之間的消息延遲,我同意你的觀點(diǎn)。但客戶(hù)端和被訪問(wèn)資源之間的延遲還是有問(wèn)題的。

所以通過(guò)卷發(fā)哥的回?fù)粑恼潞湍成缃黄脚_(tái)的記錄,他是同意大的系統(tǒng)時(shí)鐘跳躍會(huì)造成 Redlock 失效的。在這一點(diǎn)上,他與長(zhǎng)發(fā)哥的觀點(diǎn)的不同在于,他認(rèn)為在實(shí)際系統(tǒng)中是可以通過(guò)好的運(yùn)維方式避免大的時(shí)鐘跳躍的。

所以到這里,兩位神仙好像又達(dá)到了一個(gè)平衡,實(shí)現(xiàn)了爭(zhēng)論上的求同存異。

打架總結(jié)

作為一個(gè)互聯(lián)網(wǎng)行業(yè)的從業(yè)者,也是分布式系統(tǒng)的使用者,讀完他們的文章以及由此文章衍生出來(lái)的知識(shí)點(diǎn)后,受益良多,于是寫(xiě)下此文作為學(xué)習(xí)總結(jié),也與大家分享。本文還有很多不足之處,還請(qǐng)各位海涵。

如同文章開(kāi)篇說(shuō)的,這場(chǎng)爭(zhēng)論沒(méi)有最后的贏家。很明顯卷發(fā)哥是沒(méi)有說(shuō)服長(zhǎng)發(fā)哥的,因?yàn)樵陂L(zhǎng)發(fā)哥2017年出版的《數(shù)據(jù)密集型應(yīng)用系統(tǒng)設(shè)計(jì)》一書(shū)中,專(zhuān)門(mén)有一小節(jié)的名稱(chēng)叫做:不可靠的時(shí)鐘

其實(shí)在這場(chǎng)爭(zhēng)論的最后,長(zhǎng)發(fā)哥對(duì)這場(chǎng)爭(zhēng)論進(jìn)行了一個(gè)非常感性的總結(jié),他說(shuō):

下面翻譯來(lái)自:

https://www.jianshu.com/p/dd66bdd18a56

對(duì)我來(lái)說(shuō)最重要的一點(diǎn)在于:我并不在乎在這場(chǎng)辯論中誰(shuí)對(duì)誰(shuí)錯(cuò) —— 我只關(guān)心從其他人的工作中學(xué)到的東西,以便我們能夠避免重蹈覆轍,并讓未來(lái)更加美好。前人已經(jīng)為我們創(chuàng)造出了許多偉大的成果:站在巨人的肩膀上,我們得以構(gòu)建更棒的軟件。

對(duì)于任何想法,務(wù)必要詳加檢驗(yàn),通過(guò)論證以及檢查它們是否經(jīng)得住別人的詳細(xì)審查。那是學(xué)習(xí)過(guò)程的一部分。但目標(biāo)應(yīng)該是為了獲得知識(shí),而不應(yīng)該是為了說(shuō)服別人相信你自己是對(duì)的。有時(shí)候,那只不過(guò)意味著停下來(lái),好好地想一想。

吃瓜網(wǎng)友的收獲

這里的吃瓜網(wǎng)友就是指我啦。

寫(xiě)這篇文章我的收獲還是挺大的,首先我買(mǎi)了長(zhǎng)發(fā)哥的《數(shù)據(jù)密集型應(yīng)用系統(tǒng)設(shè)計(jì)》一書(shū),讀了幾節(jié),發(fā)現(xiàn)這書(shū)是真的不錯(cuò),豆瓣評(píng)分9.6,當(dāng)當(dāng)最近也在搞活動(dòng),52元就能拿下,強(qiáng)推:

廣告數(shù)據(jù)密集型應(yīng)用系統(tǒng)設(shè)計(jì)

作者:[美] Martin Kleppmann(馬丁·科勒普曼) 著 譯者:趙軍平 呂云松 耿煜 李三平

其次完成了這周的周更任務(wù),雖然寫(xiě)的很艱難,從周六中午,寫(xiě)到周日凌晨3點(diǎn)。。。

然后還吃到了另外的一個(gè)瓜,可謂是瓜中瓜。

這周五的時(shí)候 Redis 官網(wǎng)不是出現(xiàn)了短暫的宕機(jī)嗎,宕機(jī)其實(shí)也沒(méi)啥稀奇的,但是頁(yè)面上顯示的是連不上 Redis 。這就有點(diǎn)意思了。

我在寫(xiě)這篇文章的時(shí)候,在卷發(fā)哥的某社交平臺(tái)上發(fā)現(xiàn)了這個(gè):

我關(guān)心的并不是 OOM,而是卷發(fā)哥居然讓 Redis 官網(wǎng)運(yùn)行在一臺(tái)一個(gè)月僅 5 美元,內(nèi)存只有 1G 的虛擬機(jī)上。哈哈哈,震驚,這瓜味道不錯(cuò)。

最后,由于卷發(fā)哥是個(gè)意大利人,由于最近疫情,四川專(zhuān)家組馳援意大利的事,big thank 中國(guó)人。其實(shí)這個(gè)網(wǎng)友的回答挺好的:投桃報(bào)李。

疫情早點(diǎn)過(guò)去吧,世界和平。

最后說(shuō)一句(求關(guān)注)

我寫(xiě)到這里的時(shí)候,不知不覺(jué)已經(jīng)凌晨3點(diǎn)多了,但是因?yàn)橐恢备@兩位大神的激烈討論,我的思維異常的清晰。

寫(xiě)完之后我也說(shuō)不出誰(shuí)對(duì)誰(shuí)錯(cuò)。我覺(jué)得對(duì)于系統(tǒng)的設(shè)計(jì),每個(gè)人的出發(fā)點(diǎn)都不一樣,沒(méi)有完美的架構(gòu),沒(méi)有普適的架構(gòu),但是在完美和普適能平衡的很好的架構(gòu),就是好的架構(gòu)。

瞟了一眼文章字?jǐn)?shù),快突破了1.2w字??赡苡质且黄獙?xiě)了沒(méi)人看的勸退文吧,但是沒(méi)有關(guān)系,只要有一個(gè)人看了我的文章覺(jué)得有幫助就行。

點(diǎn)個(gè)“在看”吧,寫(xiě)文章很累的,不要白嫖我,需要一點(diǎn)正反饋。

才疏學(xué)淺,難免會(huì)有紕漏,如果你發(fā)現(xiàn)了錯(cuò)誤的地方,還請(qǐng)你留言給我指出來(lái),我對(duì)其加以修改。(我每篇技術(shù)文章都有這句話,我是認(rèn)真的說(shuō)的。)


當(dāng)前標(biāo)題:【求錘得錘的故事】Redis鎖從面試連環(huán)炮聊到神仙打架
網(wǎng)址分享:http://m.5511xx.com/article/dpcpppi.html