如上圖所述,通常此類情況下訊息的傳送流程如下:
關於 「step 4」 的補充說明:
① 儲存離線消看書的表主要字段大致如下: 01
02
03
04
05
06
07
08
09
10
11
12
13
-- 訊息接收者id
receiver_uid
varchar
(50),
-- 訊息的唯一指紋碼(即訊息id),用於去重等場景,單機情況下此id可能是個自增值、分布式場景下可能是類似於uuid這樣的東西
msg_id
varchar
(70),
-- 訊息發出時的時間戳(如果是個跨國im,則此時間戳可能是gmt-0標準時間)
send_time
time
,
-- 訊息傳送者id
sender_uid
varchar
(50),
msg_type
int
,
msg_content
varchar
(1024),
…
② 離線訊息拉取模式:
接收方b要拉取傳送方a給ta傳送的離線訊息,只需在receiver_uid(即接收方b的使用者id), sender_uid(即傳送方a的使用者id)上查詢,然後把離線訊息刪除,再把訊息返回b即可。
③ 離線訊息的拉取,如果用sql語句來描述的話,它可以是: 1
2
3
select
msg_id, send_time, msg_type, msg_content
from
offline_msgs
where
receiver_uid = ?
and
sender_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...