亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.430618.com 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

每當發出一條微信消息,都希望對方盡快看到,并盡快回復,但始終不知道對方是否閱讀。

 

每當收到一條不能立馬回復的微信消息,都默默返回,假裝沒看見。

畫外音:不想回復的人,唉,你只是個好人。

 

微信用于個人社交,產品設計上,在線狀態,強制已讀回執都有可能暴露個人隱私,故微信并無相關功能。

釘釘用于商務交流,其“強制已讀回執”功能,讓職場人無法再“假裝不在線”,“假裝沒收到”。

 

有甚者,釘釘的群有“強制已讀回執”功能,你在群里發出的消息,能夠知道誰讀了消息,誰沒有讀消息。

 

群消息的流程如何,接收方如何確保收到群消息,發送方如何收已讀回執,究竟是拉取,還是推送,是今天要討論的問題。

 

一、群消息投遞流程,以及可達性保證

大家一起跟著樓主的節奏,一步一步來看群消息怎么設計。

p> 

 

核心問題1:群消息,只存一份?還是,每個成員存一份?

存一份,為每個成員設置一個群消息隊列,會有大量數據冗余,并不合適。

 

核心問題2:如果群消息只存一份,怎么知道每個成員讀了哪些消息?

:可以利用群消息的偏序關系,記錄每個成員的last_ack_msgid(last_ack_time),這條消息之前的消息已讀,這條消息之后的消息未讀。該方案意味著,對于群內的每一個用戶,只需要記錄一個值即可。

 

解答上述兩個核心問題后,很容易得到群消息的核心數據結構

群消息表:記錄群消息。

group_msgs(msgid, gid, sender_uid, time, content);

各字段的含義為:消息ID,群ID,發送方UID,發送時間,發送內容。

 

群成員表:記錄群里的成員,以及每個成員收到的最后一條群消息。

group_users(gid, uid, last_ack_msgid);

各字段的含義為:群ID,群成員UID,群成員最后收到的一條群消息ID。

 

在核心數據結構設計完之后,一起來看看群消息發送的流程

 

業務場景:

(1)一個群中有A, uid1, uid2, uid3四名成員

(2)A, uid1, uid2在線,期望實時收到在線消息

(3)uid3離線,期望未來拉取到離線消息

群消息已讀回執(這個diao),究竟是推還是拉?

 

其整個消息發送的流程1-4如上圖:

(1)A發出群消息

(2)server收到消息后,一來要將群消息落地,二來要查詢群里有哪些群成員,以便實施推送

(3)對于群成員,查詢在線狀態

(4)對于在線的群成員,實施推送

 

這個流程里,只要第二步消息落地完成,就能保證群消息不會丟失。

 

核心問題3:如何保證接收方一定收到群消息?

:各個收到消息后,要修改各群成員的last_ack_msgid,以告訴系統,這一條消息確認收到了。

 

在線消息,離線消息的last_ack_msgid的修改,又各有不同。

群消息已讀回執(這個diao),究竟是推還是拉?

 

對于在線的群友,收到群消息后,第一時間會ack,修改last_ack_msgid

群消息已讀回執(這個diao),究竟是推還是拉?

 

對于離線的群友,會在下一次登錄時,拉取未讀的所有群離線消息,并將last_ack_msgid修改為最新的一條消息。

核心問題4:如果ack丟失,群友會不會拉取重復的群消息?

,可以根據msgid在客戶端本地做去重,即使系統層面收到了重復的消息,仍然可以保證良好的用戶體驗。

 

上述流程,只能確保接收方收到消息,發送方仍然不知道哪些人在線閱讀了消息,哪些人離線未閱讀消息,并沒有實現已讀回執,那已讀回執會對系統設計產生什么樣的影響呢?

 

二、已讀回執流程

對于發送方發送的任何一條群消息,都需要知道,這條消息有多少人已讀多少人未讀,就需要一個基礎表來記錄這個關系。

 

消息回執表:用來記錄消息的已讀回執。

msg_acks(sender_uid, msgid, recv_uid, gid,if_ack);

各字段的含義為:發送方UID,消息ID,回執方UID,群ID,回執標記。

 

增加了已讀回執邏輯后,群消息的流程會有細微的改變。

群消息已讀回執(這個diao),究竟是推還是拉?

 

步驟二,server收到消息后,除了要:

  • 將群消息落地
  • 查詢群里有哪些群成員,以便實施推送

之外,還需要:

  • 插入每條消息的初始回執狀態
群消息已讀回執(這個diao),究竟是推還是拉?

 

接收方修改last_ack_msgid的流程,會變為:

(1)發送ack請求

(2)修改last_ack_msgid,并且,修改已讀回執if_ack狀態

(3)查詢發送方在線狀態

(4)向發送方實時推送已讀回執(如果發送方在線)

 

如果發送方不在線,ta會在下次登錄的時候:

(5)從關聯表里拉取每條消息的已讀回執

 

這里的初步結論是:

  • 如果發送方在線,會實時被推送已讀回執
  • 如果發送方不在線,會在下次在線時拉取已讀回執

 

三、流程優化方案

再次詳細的分析下,群消息已讀回執的“消息風暴擴散系數”,假設每個群有200個用戶,其中20%的用戶在線,即40各用戶在線。群用戶每發送一條群消息,會有:

  • 40個消息,通知給群友
  • 40個ack修改last_ack_msgid,發給服務端
  • 40個已讀回執,通知給發送方

可見,其消息風暴擴散系數非常之大。

同時:

  • 需要存儲40條ack記錄

群數量,群友數量,群消息數量越來越多之后,存儲也會成為問題。

 

是否有優化方案呢?

 

群消息的推送,能否改為接收方輪詢拉???

不能,消息接收,實時性是核心指標。

 

對于last_ack_msgid的修改,真的需要每個群消息都進行ack么?

其實不需要,可以批量ack,累計收到N條群消息(例如10條),再向服務器發送一次last_ack_msgid的修改請求,同時修改這個請求之前所有請求的已讀回執,這樣就能將40個發送給服務端的ack請求量,降為原來的1/10。

 

會帶來什么副作用?

:last_ack_msgid的作用是,記錄接收方最近新取的一條群消息,如果不實時更新,可能導致,異常退出時,有一些群消息沒來得及更新last_ack_msgid,使得下次登陸時,拉取到重復的群消息。但這不是問題,客戶端可以根據msgid去重,用戶體驗不會受影響。

 

發送方在線時,對于已讀回執的發送,真的需要實時推送么?

:其實不需要,發送方每發一條消息,會收到40個已讀回執,采用輪詢拉取(例如1分鐘一次,一個小時也就60個請求),可以大大降低請求量。

畫外音:或者直接放到應用層keepalive請求里,做到0額外請求增加。

 

會帶來什么副作用?

已讀回執更新不實時,最壞的情況下,1分鐘才更新回執。當然,可以根據性能與產品體驗來折衷配置這個輪詢時間。

 

如何降低數據量?

答:回執數據不是核心數據

  • 已讀的消息,可以進行物理刪除,而不是標記刪除
  • 超過N長時間的回執,歸檔或者刪除

 

四、總結

對于群消息已讀回執,一般來說:

  • 如果發送方在線,會實時被推送已讀回執
  • 如果發送方不在線,會在下次在線時拉取已讀回執

 

如果要對進行優化,可以:

  • 接收方累計收到N條群消息再批量ack
  • 發送方輪詢拉取已讀回執
  • 物理刪除已讀回執數據,定時刪除或歸檔非核心歷史數據

 

推送還是拉???

任何脫離業務的架構設計都是耍流氓。

來源公眾號:架構師之路

作者:沈劍

分享到:
標簽:消息
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定