《即時消息技術剖析與實戰》學習筆記4——IM系統如何保證消息的可靠性

IM 系統中,保證消息的可靠投遞主要體如今兩方面,一是消息的不丟失,二是消息的不重複。安全

1、消息不丟失

消息丟失的緣由

首先看一下發送消息的流程,以下圖所示:

服務器

圖片來源於《即時消息技術剖析與實戰》第 04 講

用戶 A 發出的消息,先到達IM服務端(步驟1),由服務端暫存(步驟2),成功後,服務端將成功的結果返回給用戶A(步驟3),同時將消息推送給用戶B(步驟4)。
在這個過程當中,丟失消息有如下幾種狀況:
1)步驟 1 由於網絡不通等緣由致使用戶A把消息發送到IM服務器失敗;
2)步驟 2 IM服務器存儲消息失敗;
3)步驟 3 用戶A在超時時間內未收到IM服務器返回的結果;
4)步驟 4 因爲IM服務器斷電等緣由致使消息未能成功推送給用戶B(但步驟 3 用戶A能夠收到IM服務器返回的響應成功結果);
5)步驟 4 消息成功推送給用戶B的設備,但用戶B的設備由於一些緣由如設備寫入本地DB失敗等,也會致使消息丟失。
前三種狀況,用戶A將被提示消息發送失敗;後兩種狀況,用戶B未收到消息。網絡

消息丟失的解決方案

大部分場景中,業務層ACK確認機制 + 消息重傳機制 + 消息完整性檢查,能解決消息丟失的問題。
1.業務層的ACK確認機制和重傳機制blog

ACK是確認字符(Acknowledge character)的意思,TCP協議默認提供了ACK機制,若是接收方成功接收到數據,就會回覆一個ACK數據,表示發送方發出的數據已確認接收無誤,在「三次握手」、「四次揮手」中常常見到。
ACK確認機制:TCP傳輸時將每一個字節的數據都進行編號,即序列號。TCP傳輸的過程當中,每次接收方收到數據後,都會對傳輸方進行確認應答,也就是發送ACK報文。這個ACK報文當中帶有對應的確認序列號,告訴發送方,接收到了哪些數據,下一次的數據從哪裏發。有了序列號可以將接收到的數據根據序列號排序,而且去掉重複序列號的數據。這也是TCP傳輸可靠性的保證之一。
重傳機制:發送方發送一部分數據後,都會等待接收方發送的ACK報文,並解析ACK報文,判斷數據是否傳輸成功。發送方遲遲收不到ACK報文的緣由可能有兩個:
1)數據在傳輸過程當中因爲網絡緣由等直接全體丟包,接收方沒有接收到;
2)接收方接收到了響應的數據,可是發送的ACK報文響應卻因爲網絡緣由丟包了。
超時重傳機制就是發送方在發送完數據後等待一個時間,若是在超時時間內沒有接收到ACK報文,就從新發送數據。若是是上述的第一個緣由,接收方收到二次重發的數據後,便進行ACK應答。若是是第二個緣由,接收方發現接收的數據已存在,就直接丟棄,仍舊發送ACK應答。排序

業務層的ACK確認機制參考了TCP的ACK確認機制,其策略是IM服務器在推送消息時,攜帶一個標識SID(安全標識符,相似TCP的sequenceId),推送出消息後會將當前消息添加到「待ACK消息列表」,客戶端B成功接收完消息後,會給IM服務器回一個業務層的ACK包,包中攜帶有本條接收消息的SID,IM服務器接收後,會從「待ACK消息列表」記錄中刪除此條消息,本次推送纔算真正結束。隊列

業務層的消息重傳機制也參考了TCP協議的重傳機制,IM服務器的「等待ACK隊列」通常會維護一個超時計時器,必定時間內若是沒有收到用戶B發回的ACK包,就從「等待ACK隊列」中從新拉取並進行重推。圖片

爲何有了TCP協議自己的ACK機制,還須要業務層的ACK機制?
這是由於TCP屬於傳輸層,而IM服務屬於應用層。TCP的ACK保證網絡傳輸層的可靠性,即消息是否送達,但不能保證數據可以被應用層正確可靠處理;業務層ACK進行消息是否送達和是否正確處理的邏輯,達到不丟消息、消息不重複的目的。同步

2.時間戳比對檢查消息完整性
在上面列舉的丟失消息的第 4 種可能性中,若是步驟 4 IM服務器將消息推送出去後就宕機了,而這條消息又由於某些緣由丟失了,服務器因爲宕機沒法觸發重傳機制,致使用戶B收不到該消息。能夠採起「時間戳比對」機制進行完整性檢查。

請求

圖片來源於《即時消息技術剖析與實戰》第 04 講

時間戳比對過程以下:
1)IM服務器給用戶B推送msg1,同時帶上一個最新時間戳timestamp1。用戶B收到msg1後,更新本地的時間戳爲timestamp1;
2)IM服務器給用戶B推送msg2,同時帶上一個最新時間戳timestamp2。因爲某種緣由,用戶B和IM服務器的鏈接斷開,致使msg2沒有成功推送到用戶B;
3)用戶B和IM服務器從新創建鏈接後,將本地的時間戳timestamp1發送給IM服務器,IM服務器將時間戳大於timestamp1的全部消息所有發送給用戶B,同時帶上時間戳timestamp2(這裏假設時間戳大於timestamp1的消息只有msg2,若是有msg三、msg4等多條消息,應取最新消息的時間戳);
4)用戶B收到msg2後,更新本地的時間戳爲timestamp2。
經過這樣的比對能夠有效解決消息丟失的問題。但時間戳因爲有時鐘不一樣步、或者一個時間戳內多條消息的可能性,存在偏差,所以可使用全局的自增序列版本號來代替。im

2、消息不重複

消息重複的緣由

在上面列舉的丟失消息的幾種可能性中,第 3 種可能性存在一種場景,步驟 4 將消息成功推送給用戶B,但步驟 3 由於某些緣由致使超時、用戶A收不到響應,這個時候會觸發重傳機制,用戶A從新發送請求,用戶B可能會收到重複消息。

消息重複的解決方案

IM服務器推送消息時,攜帶一個Sequence ID,這個Sequence ID在本次鏈接會話中惟一,同時針對同一條消息不變。當接收方接收到消息後,會根據這個Sequence ID來進行業務層的去重,能夠有效地保證消息的不重複。

3、小結

經過業務層的ACK機制、重傳機制和完整性檢查,能夠有效解決推送過程當中消息丟失的問題; 經過客戶端的去重機制,能夠有效解決消息重複的問題。

相關文章
相關標籤/搜索