偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

微信:群消息,我們絕對(duì)不可能丟!

開(kāi)發(fā) 架構(gòu)
微信的群消息,是怎么做到不丟的?做過(guò)幾十年IM架構(gòu),今天和大家聊聊消息的可靠投遞。

前幾天聊了1v1在線(xiàn)消息,離線(xiàn)消息的可達(dá)性:

微信:我們絕不丟消息!》

微信:我絕不丟離線(xiàn)消息!

有水友問(wèn)我說(shuō),微信的群消息,是怎么做到不丟的?

做過(guò)幾十年IM架構(gòu),今天和大家聊聊消息的可靠投遞。

群聊的核心需求,群友在群內(nèi)發(fā)消息,期望:

  • 在線(xiàn)的群友能第一時(shí)間收到消息;
  • 離線(xiàn)的群友能在登錄后收到消息;

群消息的實(shí)時(shí)性、可達(dá)性、離線(xiàn)消息的復(fù)雜度,要遠(yuǎn)高于1v1消息。

群業(yè)務(wù)的核心數(shù)據(jù)結(jié)構(gòu)如何?

群成員表:記錄群里的群成員。

t_group_users(group_id, user_id)

群離線(xiàn)消息表:記錄群里的離線(xiàn)消息。

t_offine_msgs(user_id, group_id, sender_id, time, msg_id, msg_detail)

常見(jiàn)的群消息流程如何?

  1. 假設(shè)一個(gè)群中有x,A,B,C,D共5個(gè)成員,x發(fā)了一個(gè)群消息;
  2. A與B在線(xiàn),期望實(shí)時(shí)收到消息;
  3. C與D離線(xiàn),期望未來(lái)拉取到離線(xiàn)消息;

首先,是群在線(xiàn)消息。 圖片 典型群消息投遞流程,如1-5所述:

  1. x向server發(fā)出群消息;
  2. server去db中查詢(xún)?nèi)河脩?hù)(x,A,B,C,D);
  3. server去cache中查詢(xún)?nèi)河脩?hù)在線(xiàn)狀態(tài);
  4. 在線(xiàn)的用戶(hù)A與B,進(jìn)行實(shí)時(shí)推送;
  5. 離線(xiàn)的用戶(hù)C與D,進(jìn)行離線(xiàn)存儲(chǔ);

然后,是群離線(xiàn)消息。 圖片 典型的群離線(xiàn)消息拉取流程,如1-3所述:

  1. C重新登陸的時(shí)候,向server拉取群離線(xiàn)消息;
  2. server從db中拉取離線(xiàn)消息并返回群用戶(hù)C;
  3. server從db中刪除群用戶(hù)C的群離線(xiàn)消息;

那么,問(wèn)題來(lái)了!對(duì)于同一份群消息的內(nèi)容,多個(gè)離線(xiàn)用戶(hù)似乎要存儲(chǔ)很多份。假設(shè)群中有200個(gè)用戶(hù)離線(xiàn),離線(xiàn)消息則冗余了200份,這極大地增加了數(shù)據(jù)庫(kù)的存儲(chǔ)壓力。

如何優(yōu)化,減少消息冗余量?

為了減少離線(xiàn)消息的冗余度,增加一個(gè)群消息表,用來(lái)存儲(chǔ)所有群消息的內(nèi)容,離線(xiàn)消息表只存儲(chǔ)用戶(hù)的群離線(xiàn)消息msg_id,就能大大的降低數(shù)據(jù)庫(kù)的冗余存儲(chǔ)量。

群消息表:存儲(chǔ)群中所有的消息。

t_group_msgs(group_id, sender_id, time, msg_id, msg_detail)

群離線(xiàn)消息表,需要進(jìn)行優(yōu)化,只存儲(chǔ)msg_id:

t_offine_msgs(user_id, group_id, msg_id)

這樣優(yōu)化后,群在線(xiàn)消息發(fā)送需要做對(duì)應(yīng)的調(diào)整:

  • 3.每次發(fā)送在線(xiàn)群消息之前,要先存儲(chǔ)群消息的內(nèi)容;
  • 6.每次存儲(chǔ)離線(xiàn)消息時(shí),只存儲(chǔ)msg_id,而不用為每個(gè)用戶(hù)存儲(chǔ)msg_detail;

拉取離線(xiàn)消息,也需要做對(duì)應(yīng)的修改:

  • 1.先拉取所有的離線(xiàn)消息msg_id;
  • 3.再根據(jù)msg_id拉取msg_detail;
  • 5.刪除離線(xiàn)msg_id;

優(yōu)化后的流程,能保證消息的可達(dá)性么?

  1. 在線(xiàn)消息的投遞可能出現(xiàn)消息丟失,例如服務(wù)器重啟,路由器丟包,客戶(hù)端crash;
  2. 離線(xiàn)消息的拉取也可能出現(xiàn)消息丟失,原因同上;

很容易想到,必須和1v1消息投遞一樣,需要加入應(yīng)用層的ACK。

群消息,如何通過(guò)應(yīng)用層ACK,保證消息的可靠投遞?

應(yīng)用層ACK優(yōu)化后,群在線(xiàn)消息發(fā)送又做了調(diào)整:

  • 3.在消息msg_detail存儲(chǔ)到群消息表后,不管用戶(hù)是否在線(xiàn),都先將msg_id存儲(chǔ)到離線(xiàn)消息表里;
  • 6.在線(xiàn)的用戶(hù)A和B收到群消息后,需要增加一個(gè)應(yīng)用層ACK,來(lái)標(biāo)識(shí)消息到達(dá);
  • 7.在線(xiàn)的用戶(hù)A和B在應(yīng)用層ACK后,將他們的離線(xiàn)消息msg_id刪除掉;

對(duì)應(yīng)到群離線(xiàn)消息的拉取也一樣:

  • 1.先拉取msg_id;
  • 2.再拉取msg_detail;
  • 5.最后應(yīng)用層ACK;
  • 6.server收到應(yīng)用層ACK才能刪除離線(xiàn)消息表里的msg_id;

如果拉取了消息,卻沒(méi)來(lái)得及應(yīng)用層ACK,會(huì)收到重復(fù)的消息么?

會(huì),但可以在客戶(hù)端去重,對(duì)于重復(fù)的msg_id,對(duì)用戶(hù)不展現(xiàn),從而不影響用戶(hù)體驗(yàn)。

對(duì)于離線(xiàn)的每一條消息,雖然只存儲(chǔ)了msg_id,但是每個(gè)用戶(hù)的每一條離線(xiàn)消息都將在數(shù)據(jù)庫(kù)中保存一條記錄,有沒(méi)有辦法減少離線(xiàn)消息的記錄數(shù)呢?

對(duì)于一個(gè)群用戶(hù),在ta登出后的離線(xiàn)期間內(nèi),肯定是所有的群消息都沒(méi)有收到的,不用對(duì)所有的每一條離線(xiàn)消息存儲(chǔ)一個(gè)離線(xiàn)msg_id,而只需要存儲(chǔ)最近一條拉取到的離線(xiàn)消息的time(或者msg_id),下次登錄時(shí)拉取在那之后的所有群消息即可,而沒(méi)有必要存儲(chǔ)每個(gè)人未拉取到的所有離線(xiàn)消息msg_id。

群成員表,增加一個(gè)屬性,記錄每個(gè)群成員最近一條ACK的群消息msg_id(或者time)。 t_group_users(group_id, user_id, last_ack_msg_id)

群消息表,不變,依然存儲(chǔ)群中所有的消息: t_group_msgs(group_id, sender_id, time, msg_id, msg_detail)

群離線(xiàn)消息表:不再需要。

離線(xiàn)消息表優(yōu)化后,群在線(xiàn)消息的投遞流程:

  • 3.在消息msg_detail存儲(chǔ)到群消息表后,不再需要操作離線(xiàn)消息表(優(yōu)化前需要將msg_id插入離線(xiàn)消息表);
  • 7.在線(xiàn)的用戶(hù)A和B在應(yīng)用層ACK后,將last_ack_msg_id更新即可(優(yōu)化前需要將msg_id從離線(xiàn)消息表刪除);

群離線(xiàn)消息的拉取流程也類(lèi)似:

  • 1.拉取離線(xiàn)消息;
  • 3.ACK離線(xiàn)消息;
  • 4.更新last_ack_msg_id;

加入ACK機(jī)制,假設(shè)1個(gè)群有500個(gè)用戶(hù),“每條”群消息都會(huì)變?yōu)?00個(gè)應(yīng)用層ACK,似乎會(huì)對(duì)服務(wù)器造成巨大的沖擊。有沒(méi)有辦法減少ACK請(qǐng)求量呢?

批量ACK,是一種常見(jiàn)的,降低請(qǐng)求量的方式。

批量ACK,批量ACK的方式又有兩種方式:

  1. 每收到N條群消息ACK一次,這樣請(qǐng)求量就降低為原來(lái)的1/N了;
  2. 每隔時(shí)間間隔T進(jìn)行一次群消息ACK,也能達(dá)到類(lèi)似的效果;

批量ACK有可能導(dǎo)致新的問(wèn)題:如果還沒(méi)有來(lái)得及ACK群消息,用戶(hù)就退出了,這樣下次登錄似乎會(huì)拉取到重復(fù)的離線(xiàn)消息,怎么辦?

仍然在客戶(hù)端去重,對(duì)于重復(fù)的msg_id,對(duì)用戶(hù)不展現(xiàn),不影響用戶(hù)體驗(yàn)。

群離線(xiàn)消息過(guò)多,拉取過(guò)慢,怎么辦?

分頁(yè)拉?。ò葱枥。?,都是常見(jiàn)的優(yōu)化方案。

總結(jié)

群消息還是非常有意思的,做個(gè)簡(jiǎn)單總結(jié):

  • 不管是群在線(xiàn)消息,還是群離線(xiàn)消息,應(yīng)用層的ACK是可達(dá)性的保障;
  • 群消息可以只存一份,不用為每個(gè)用戶(hù)存儲(chǔ)離線(xiàn)群msg_id,只需存儲(chǔ)一個(gè)最近ack的群消息id/time;
  • 為了減少消息風(fēng)暴,可以批量ACK;
  • 如果收到重復(fù)消息,需要msg_id去重,讓用戶(hù)無(wú)感知;
  • 離線(xiàn)消息過(guò)多,可以分頁(yè)拉取(按需拉?。﹥?yōu)化;

知其然,知其所以然。 思路比結(jié)論更重要。

責(zé)任編輯:趙寧寧 來(lái)源: 架構(gòu)師之路
相關(guān)推薦

2025-03-31 10:49:16

2013-12-09 15:50:20

2021-04-20 08:11:33

Css前端@property

2016-10-11 16:31:56

微信服務(wù)器消息

2025-04-15 09:00:00

2016-11-02 13:12:31

微信離線(xiàn)消息

2014-07-17 10:38:30

大數(shù)據(jù)

2016-03-14 14:45:18

中華網(wǎng)

2021-02-21 14:05:02

區(qū)塊鏈比特幣安全

2012-04-10 08:58:26

小米

2019-01-02 06:26:02

API應(yīng)用程序編程接口應(yīng)用安全

2013-12-13 10:01:16

諾基亞安卓手機(jī)

2023-12-05 07:19:43

CAP定理分布式

2016-09-01 16:37:24

2014-04-16 15:10:10

2023-05-09 08:59:09

ChatGPT程序員裁員

2024-01-24 13:08:00

2012-03-24 21:26:56

2018-07-26 08:13:31

根服務(wù)器網(wǎng)絡(luò)TCP

2013-07-02 09:26:11

IntelCEO代工
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)