QQ狀態(tài)同步究竟是推還是拉?

2018-09-06 17:21 更新

前面兩篇講即時通訊核心技術(shù)的文章

微信為什么不丟消息?

http如何像tcp一樣實時的收消息?

反饋還可以,故繼續(xù)即時通訊這一個系列吧,今天聊聊即時通訊中的“狀態(tài)”。


需求緣起

在線狀態(tài)一致性”(好友在線狀態(tài),群友在線狀態(tài))是即時通訊領(lǐng)域較難解決的一個技術(shù)問題,如何精準實時的獲得好友、群友的在線狀態(tài),是今天將要探討的話題。


好友狀態(tài)一致性

問題一:用戶uid-A登錄時,如何獲取自己全部好友的在線狀態(tài)?

回答:

用戶在線狀態(tài)

(1)服務(wù)器要存儲所有用戶的在線狀態(tài)(往往存儲在保證高可用的緩存集群里) -> 保證狀態(tài)可查


用戶離線狀態(tài)
(2)用戶狀態(tài)實時變更,任何用戶登錄時,需要將服務(wù)端自己的在線狀態(tài)置為online;任何用戶登出時,需要將服務(wù)端自己的狀態(tài)置為offline -> 保證服務(wù)端狀態(tài)存儲的一致性與實時性

好友狀態(tài)獲取的一致性與實時性

(3)uid-A登錄時,先去數(shù)據(jù)庫拉取自己的好友列表,再去緩存獲取所有好友的在線狀態(tài) -> 保證登錄時好友狀態(tài)獲取的一致性與實時性


問題二:用戶uid-A的好友uid-B狀態(tài)改變時(由登錄、登出、隱身等動作觸發(fā)),uid-A如何知道這一事件?

方案一:uid-A向服務(wù)器輪詢拉取uid-B(其實是自己的全部好友)的狀態(tài),例如每1分鐘一次

缺點

(1)如果uid-B的狀態(tài)改變,uid-A獲取不實時,可能有1分鐘時延

(2)如果uid-B的狀態(tài)不改變,uid-A會有大量無效的輪詢請求,占用服務(wù)器資源


方案二:uid-B狀態(tài)改變時(由登錄、登出、隱身等動作觸發(fā)),服務(wù)器不僅在緩存中修改uid-B的狀態(tài),還要將這個狀體改變的通知推送給uid-B的在線反向好友(反向好友是指:加了uid-B為好友的人,而不是uid-B的好友,這個細節(jié)要注意)
在線反向好友推送

優(yōu)點:

(1)實時

缺點:

(2)當在線好友量很大時,任何一個用戶狀態(tài)的改變,會擴散成N個實時通知,這個N叫做“消息風暴擴散系數(shù)”。

假設(shè)一個im系統(tǒng)平均每個用戶有200個反向好友,平均有20%的反向好友在線,那么消息風暴擴散系數(shù)N=40,這意味著,任何一個狀態(tài)的變化會變成40個推送請求。


群友狀態(tài)一致性

問題三:群友狀態(tài)一致性有什么不同,和好友狀態(tài)一致性相比復雜在哪里?為什么不能采用實時推送?

回答:

理論上群友狀態(tài)也可以通過實時推送的方式實現(xiàn),以保證實時性。但實際上,群友狀態(tài)一般都是采用拉取的方式獲得,因為群友狀態(tài)“消息風暴擴散系數(shù)”N實在太大,全部實時獲取系統(tǒng)往往承受不了。

假設(shè)平均每個用戶加了20個群,平均每個群有200個用戶,依然假設(shè)20%的用戶在線,那么為了保證群友狀態(tài)的實時性,每個用戶登錄,就要將自己的狀態(tài)改變通知發(fā)送給20*200*20%=800個群友,N=800,意味著,任何一個狀態(tài)的變化會變成800個推送請求。

XXX系統(tǒng)使用的是群友狀態(tài)推送,不存在的這樣的問題?那很可能是,XXX系統(tǒng)的用戶量和活躍度還不夠高吧。


問題四:輪詢拉取群友狀態(tài)也會給服務(wù)器帶來過大的壓力,還有什么優(yōu)化方式?

回答:

群友的數(shù)據(jù)量太大,雖然每個用戶平均加入了20個群,但實際上并不會每次登錄都進入每一個群。不采用輪詢拉取,而采用按需拉取,延時拉取的方式,在真正進入一個群時才實時拉取群友的在線狀態(tài),是既能滿足用戶需求(用戶感覺是狀態(tài)是實時、一致的,但其實是進入群才拉取的),又能降低服務(wù)器壓力。這是一種常見方法。


關(guān)于更多按需拉取,延時拉取的討論,可移步《微信為啥這么省流量》。

延伸討論:系統(tǒng)消息/開屏廣告的推送與拉取

問題五:系統(tǒng)消息/開屏廣告一般采用推送還是拉?。?/strong>

回答:

不考慮APP端的push(APP端的push,不需要啟動APP,不依賴client與server之間的TCP長連接),個人強烈建議系統(tǒng)消息/開屏廣告這類消息采用“拉取”的方式,原因是:

(1)這類業(yè)務(wù)對消息的實時性往往要求不高

(2)如果集中推送,“消息風暴擴散系數(shù)”過大,容易引發(fā)系統(tǒng)抖動;而拉取的方式,可以攤平這個抖動,用戶登錄時均勻的發(fā)起請求

(3)如果集中推送,往往不在意用戶是否“在線”,往往會造成大量離線垃圾消息;而拉取的方式,保證只有在線的用戶才會收到請求

(4)…

有不同的建議,歡迎評論討論。


總結(jié)與建議

狀態(tài)的實時性與一致性是一個較難解決的技術(shù)問題,不同的業(yè)務(wù)接受度,不同的數(shù)據(jù)量并發(fā)量在線量,實現(xiàn)方式不同,個人建議的方式是:

(1)好友狀態(tài),如果對實時性要求較高,可以采用推送的方式同步;如果實時性要求不高,可以采用輪詢拉取的方式同步

(2)群友的狀態(tài),由于消息風暴擴散系數(shù)過大,可以采用按需拉取,延時拉取的方式同步

(3)系統(tǒng)消息/開屏廣告等對實時性要求不高的業(yè)務(wù),可以采的方式獲取消息

(4)“消息風暴擴散系數(shù)”是指一個消息發(fā)出時,變成N個消息的擴散系數(shù),這個系數(shù)與業(yè)務(wù)及數(shù)據(jù)相關(guān),一定程度上它的大小決定了技術(shù)采用推送還是拉取


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號