IM訊息送達保證機制實現 保證離線訊息的可靠投遞

2021-08-19 05:56:59 字數 2939 閱讀 8152

如上圖所述,通常此類情況下訊息的傳送流程如下:

關於 「step 4」 的補充說明:

① 儲存離線消看書的表主要字段大致如下: 01

02

03

04

05

06

07

08

09

10

11

12

13

-- 訊息接收者id

receiver_uidvarchar(50),

-- 訊息的唯一指紋碼(即訊息id),用於去重等場景,單機情況下此id可能是個自增值、分布式場景下可能是類似於uuid這樣的東西

msg_idvarchar(70),

-- 訊息發出時的時間戳(如果是個跨國im,則此時間戳可能是gmt-0標準時間)

send_timetime,

-- 訊息傳送者id

sender_uidvarchar(50),

msg_typeint,

msg_contentvarchar(1024),

② 離線訊息拉取模式:

接收方b要拉取傳送方a給ta傳送的離線訊息,只需在receiver_uid(即接收方b的使用者id), sender_uid(即傳送方a的使用者id)上查詢,然後把離線訊息刪除,再把訊息返回b即可。

③ 離線訊息的拉取,如果用sql語句來描述的話,它可以是: 1

2

3

selectmsg_id, send_time, msg_type, msg_content

fromoffline_msgs

wherereceiver_uid = ?andsender_uid = ?

④ 離線拉取的整體流程如下圖所示:

如果使用者b有很多好友,登陸時客戶端需要對所有好友進行離線訊息拉取,客戶端與伺服器互動次數就會比較多。

① 拉取好友離線訊息的客戶端偽**: 1

2

3

4

5

// 登陸時所有好友都要拉取

for(all uid in b』s friend-list)

② 優化方案1:

先拉取各個好友的離線訊息數量,真正使用者b進去看離線訊息時,才往伺服器傳送拉取請求(手機端為了節省流量,經常會使用這個按需拉取的優化)。

③ 優化方案2:

如下圖所示,一次性拉取所有好友傳送給使用者b的離線訊息,到客戶端本地再根據sender_uid進行計算,這樣的話,離校訊息表的訪問模式就變為->只需要按照receiver_uid來查詢了。登入時與伺服器的互動次數降低為了1次。

④ 方案小結:

使用者b一次性拉取所有好友發給ta的離線訊息,訊息量很大時,乙個請求包很大、速度慢,容易卡頓怎麼辦?

正如上圖所示,我們可以分頁拉取:根據業務需求,先拉取最新(或者最舊)的一頁訊息,再按需一頁頁拉取,這樣便能很好地解決使用者體驗問題。

如果使用者b拉取了一頁離線訊息,卻在ack之前crash了,下次登入時會拉取到重複的離線訊息麼?

確實,拉取了離線訊息卻沒有ack,伺服器不會刪除之前的離線訊息,故下次登入時系統層面還會拉取到。但在業務層面,可以根據msg_id去重。smc理論:系統層面無法做到訊息不丟不重,業務層面可以做到,對使用者無感知。

優化後的拉取過程,如下圖所示:

假設有n頁離線訊息,現在每個離線訊息需要乙個ack,那麼豈不是客戶端與伺服器的互動次數又加倍了?有沒有優化空間?

如上圖所示,不用每一頁訊息都ack,在拉取第二頁訊息時相當於第一頁訊息的ack,此時伺服器再刪除第一頁的離線訊息即可,最後一頁訊息再ack一次(實際上:最後一頁拉取的肯定是空返回,這樣可以極大地簡化這個分頁過程,否則客戶端得知道當前離線訊息的總頁數,而由於訊息讀取延遲的存在,這個總頁數理論上並非絕對不變,從而加大了資料讀取不一致的可能性)。這樣的效果是,不管拉取多少頁離線訊息,只會多乙個ack請求,與伺服器多一次互動。

正如本文中所列舉的問題所描述的那樣,保證「離線訊息」的可達性比大家想象的要複雜一些,常見優化總結如下:

Storm如何保證可靠的訊息處理

內容簡介 storm可以保證從spout發出的每個訊息都能被完全處理。storm的可靠性機制是完全分布式的 distributed 可伸縮的 scalable 容錯的 fault tolerant 本文介紹了storm如何保證可靠性以及作為storm使用者,我們需要怎麼做,才能充分利用storm的可...

如何保證kafka 的訊息機制

1.kafka 知識總結 1 kafka是什麼 類jms訊息佇列,結合jms中的兩種模式,可以有多個消費者主動拉取資料,在jms中只有點對點模式才有消費者主動拉取資料。kafka是乙個生產 消費模型。producer 生產者,只負責資料生產,生產者的 可以整合到任務系統中。資料的分發策略由produ...

《RabbitMQ》如何保證訊息的可靠性

1.1 事務機制 amqp協議提供了事務機制,在投遞訊息時開啟事務支援,如果訊息投遞失敗,則回滾事務。自定義事務管理器 configuration public class rabbittranscation bean public rabbittemplate rabbittemplate con...