即時通訊訊息不遺失,不是靠單一重試,而是靠傳送端確認、伺服器端先落盤、接收端補拉三步協同。鏈路中任何一個節點只做「發出去」,不確認、不持久化、不補拉,訊息就會在斷線或程序重啟時消失。
先回答什麼是IM即時通訊:它是支援文字、圖片、音視訊等訊息即時雙向傳輸的系統。即時通訊軟體有哪些類型?按使用情境,主流即時通訊軟體可分為個人社交、遠距辦公和客戶溝通三類。本文討論的「不遺失」具體指三種情形:傳送端顯示成功但接收方未收到、接收方離線後訊息漏掉、同一訊息在多端重複或缺失。
即時通訊系統架構中,決定訊息可靠性的四個節點
即時通訊系統架構設計要點可以收斂到四個節點:用戶端、長連線接入層、訊息佇列、持久化儲存。每個節點都有對應的遺失風險,可靠性設計必須明確每一層「誰負責確認、誰負責重試」。
- 用戶端:負責本機未確認佇列和逾時重試。傳送後未收到伺服器端ACK前,訊息必須留在本機。
- 長連線接入層:維護TCP/WebSocket連線狀態,承擔心跳與斷線偵測。連線假死而用戶端未感知,會導致訊息卡在傳送佇列。
- 訊息佇列:在流量高峰削峰,同時提供非同步重試。佇列不做持久化時,處理程序當機就會丟訊息。
- 持久化儲存:先寫入訊息再回ACK,按工作階段或訊息ID順序寫入磁碟。這層是離線訊息和多端同步的基礎。
排查訊息遺失時也按同樣分層推進,從網路、伺服器端到用戶端逐層定位能避免誤判。
傳送端到伺服器端:ACK、重試與冪等是必達的第一道閘門
用戶端發出訊息後,只有在收到伺服器端明確ACK後才能從本機未確認佇列刪除。未確認前,用戶端應把訊息持久化在本機資料庫;斷線或應用程式被終止後重啟,佇列中的訊息繼續按同一訊息ID重傳。伺服器端收到重複ID時直接去重並回傳ACK,這就是冪等。
如果用戶端「傳送成功」只是寫入作業系統層就刪除副本,伺服器端在真正持久化前崩潰,訊息就會遺失。需要排查時,訊息發不出去或發出後未見達,可依端側、連線層、伺服器端三層檢查確認與重試日誌。
伺服器端到接收端:持久化、離線佇列與多端同步
伺服器端收到訊息後必須先落盤,再向傳送端回 ACK,同時轉發給接收端線上會話。接收方離線時,訊息寫入該使用者專屬離線佇列;上線後用戶端補拉佇列中的訊息,伺服器端依游標或訊息 ID 返回未同步部分。
多端場景不能簡單廣播。每個裝置應各自擁有同步游標,伺服器端依裝置記錄已確認訊息 ID。一端拉到訊息不代表其他端已同步,否則切換裝置就會出現漏訊息。離線訊息收不到通常不是網路差,而是伺服器端未儲存、用戶端未補拉或多端同步覆蓋。
可靠性邊界:什麼情況下仍可能丟,如何取捨
沒有任何 IM 能在所有極端條件下做到絕對不丟。弱網中用戶端重試次數耗盡、本機快取被使用者手動清理、儲存節點發生不可復原故障,都可能造成訊息遺失。設計時需要在「至少一次投遞(At least once)」和「恰好一次投遞(Exactly once)」之間做取捨:At least once 會引入重複,需要用戶端按訊息 ID 去重;Exactly once 則要額外協調狀態,延遲和複雜度更高。
個人社交可以接受偶發重複,企業協作和客服溝通則通常要求至少一次且可對帳。如果預算有限,中小企業 IM 選型應重點核對離線訊息、多端同步和伺服器端持久化能力,上線後再補可靠性成本更高。
常見問題
多端同時在線時,為什麼有的裝置會漏訊息?
伺服器端沒有為每個裝置維護獨立同步游標,或者一端拉取後直接清除了全域未讀標記。多端同步必須按裝置記錄已確認的訊息ID範圍。
採用至少一次投遞後,用戶端收到重複訊息怎麼辦?
按訊息ID去重。用戶端本機保存最近若干條已接收ID,伺服器端在短時間內對同一ID只返回一次業務訊息,重複到達直接丟棄。
離線訊息應該保存多久?
個人社交通常7至30天,企業協作和客服溝通建議至少30天。超過保存窗口仍未拉取的訊息進入歸檔,重新上線只同步有效窗口。
自建與SaaS在訊息可靠性上主要差在哪?
SaaS預設提供ACK、持久化和離線補拉,但保存時長、QoS等級和排查深度受限;自建可調整閾值與儲存策略,但必須自己承擔多端同步設計和維運可靠性。
