無處不在的“網(wǎng)絡(luò)2將軍”問題,重要性超出預(yù)期
越常識的事情越總是被忽視,從而帶來認(rèn)知盲區(qū)和錯(cuò)誤的技術(shù)方案。網(wǎng)絡(luò)2將軍就是這樣一個(gè)典型例子。
網(wǎng)絡(luò)2將軍本來的故事是這樣的:
兩個(gè)將軍 A1 和 A2 決定共同攻打同一個(gè)敵人 B ,敵軍正好位于兩個(gè)將軍之間,意味著任何一方派出的信使可能會被敵軍抓住。
將軍 A1 給將軍 A2 送信說明天進(jìn)攻,但信使出發(fā)后,A1 是沒有辦法確認(rèn)信使是不是真的把信送到了的,這樣 A1 就會選擇不進(jìn)攻。要讓事情確定一些,A2 需要收到信之后給 A1 一個(gè)確認(rèn)信息,說“我已經(jīng)收到了你給我的要明天進(jìn)攻的信息了”。信使在給 A1 回信的路上也可能會被抓,這樣, A2 會傾向于不進(jìn)攻,因?yàn)樗?A1 如果收不到他的確認(rèn)信息是不會發(fā)動進(jìn)攻的。所以這里的邏輯順推下來,不管雙方試圖確認(rèn)多少次,都不能最終確認(rèn)跟彼此達(dá)成了共識。每個(gè)將軍都會懷疑最后給對方發(fā)的那條信息是否送到了,兩軍問題又被稱為“兩軍悖論”,是一個(gè)無解問題。
網(wǎng)絡(luò)2將軍問題在日常工作中最典型的例子就是“網(wǎng)絡(luò)超時(shí)”:
客戶端給服務(wù)器發(fā)一個(gè)網(wǎng)絡(luò)請求(假設(shè)http接口),然后網(wǎng)絡(luò)超時(shí),請問,服務(wù)器是收到了這個(gè)網(wǎng)絡(luò)請求呢?還是沒收到?
答案是:不確定。如果這是一個(gè)更新數(shù)據(jù)的http接口,意味著服務(wù)器可能接收到網(wǎng)絡(luò)請求然后更新數(shù)據(jù)成功了,也可能壓根沒收到網(wǎng)絡(luò)請求,數(shù)據(jù)沒更新成功。
那客戶端怎么辦呢?超時(shí)重試,重試就必須要求服務(wù)器對于這個(gè)接口做到冪等。
這正是網(wǎng)絡(luò)2將軍問題,對于我們做技術(shù)方案最重要的啟示之1:理論上,服務(wù)端提供的任何數(shù)據(jù)更新類的接口,都必須做到“冪等”,因?yàn)?/span>沒有辦法避免客戶端的超時(shí)重試!不冪等,重試之后,就可能產(chǎn)生臟數(shù)據(jù)。
那如何實(shí)現(xiàn)接口“冪等”呢?有N種辦法,下次再續(xù)。
另外補(bǔ)充一點(diǎn):分布式事務(wù)問題,很大部分原因也是“網(wǎng)絡(luò)超時(shí)”引起的,后續(xù)來專門討論。
