天天看點

如何有效縮短閑魚消息處理時長

作者:閑魚技術——書閑

背景

随着使用者數的快速增長,閑魚的IM也迎來了前所未有的挑戰。多年的業務疊代,端側IM的代碼已經因為多年的疊代層次結構不足夠清晰,之前消息一些隐藏起來的資料同步問題,也随着使用者數的增大而被放大。

現狀分析

背景需要同步到使用者端側的資料包,背景會根據資料包的業務類型劃分成不同的資料域,資料包在對應域裡面存在唯一且連續的編号,每一個資料包發送到端側并且被成功消費後,端側會記錄目前每一個資料域已經同步過的版本編号,下一次資料同步就以本地資料域的編号開始,不斷的同步到用戶端。

當然使用者不會一直線上等待消息,是以之前這裡端側采用了推拉結合的方式保證資料的同步。

  • 線上時使用ACCS實時的将最新的資料内容推送到用戶端。ACCS是淘寶無線向開發者提供全雙工、低延時、高安全的通道服務。
  • 離線啟動後,根據本地的資料域編号,拉取不線上時候的資料差。
  • 當資料擷取出現黑洞(資料包Version不連續的狀态)時,觸發資料同步拉取。

這樣的一個同步政策是可以基本保障IM的資料同步的,但是也伴随着一些隐含的問題:

  1. 短時間密集資料推送時,會快速的觸發多次資料域同步。域同步回來的資料如果存在問題,又會觸發新一輪的同步,造成網絡資源的浪費。備援資料包/無效的資料内容會占用有效内容的處理資源,又對CPU和記憶體資源造成浪費。
  2. 資料域中的資料包用戶端是否正常消費,服務端側無感覺,隻能被動地根據目前資料域資訊傳回資料。
  3. 資料收取/消息資料體解析/存儲落庫邏輯拆分不夠清晰,無法針對性的對某一層的代碼拆分替換進行ABTest。

要做什麼

針對遇見的這些問題,對閑魚IM進行分層改造,抽離資料同步層。除了希望以後這個資料的同步内容可以用在IM之外,也希望随着穩定性的增加,賦能其他的業務場景。

本文重點來看下端側閑魚IM資料同步的一些解決思路。

資料同步優化

拆分&分層

對于服務端來說,業務側産出資料包後,會拼接上目前的資料域資訊,然後通過資料同步層将資料推送到端側。

對于用戶端來說,接收到資料包後,會根據目前的資料域資訊,來确定需要消費資料包的業務方,確定資料包在資料域内完整連續後,将資料體脫殼後交于業務側消費,并且應答消費的狀況。

資料同步層的抽取,把資料同步中的加殼、脫殼、校驗,重試流程封裝到一起,可以讓上層業務隻需要關心自己需要監聽的資料域資訊,然後當這些資料域更新資料的時候,可以擷取到這些資料進行消費,而不再需要關心資料包是否完整。

業務側隻需要關心業務側對接的協定,資料側隻需要關心資料側包裝的協定,網絡層負責真實的資料傳輸。

  1. 對齊資料層資料傳輸協定、描述目前資料包體資料域資訊
  2. 将消息的處理/合并/落庫抽離成資料消費者
  3. 上下樓依賴抽象化,去除對于具體實作的依賴

資料層結構模型

基于對于資料模型剝離和對當下遇見的問題的解決方案規整,将資料同步層拆分為這樣的架構:

如何有效縮短閑魚消息處理時長

step1:App啟動時建立ACCS長連結服務,保證推推送信道連結,并且根據目前本地資料域資訊觸發一次資料拉取。

step2:資料消費者注冊消費者資訊和需要監聽的資料域資訊,這裡是一對多的關系。

step3:新的資料抵達端側後,将資料包放到指定的資料域的緩沖池,一批資料歸納結束後,重新出發資料的讀取。

step4:根據目前資料域優先級彈出最高優的資料包,判斷資料域版本是否符合消費者要求,符合則将資料包脫殼後丢給消費者消費,不符合則根據上一次正确的資料包的域資訊觸發增量的資料域同步拉取。

step5:觸發資料域同步拉取時,block資料讀取,此時通過ACCS觸達的資料依舊會在繼續歸納到指定的資料域隊列中,等待資料域同步拉取結果,将資料包進行排序、去重,合并到對應的資料域隊列中。然後重新激活資料讀取。

step6:資料包體被消費者正确消費後,更新域資訊并且通過上行信道告知服務端已經正确的資料域資訊。

資料域同步協定

Region中攜帶的資料不必過多,但是又需要将資料包的内容描述清楚

  • 目标使用者的ID,用以确定目标資料包是否正确
  • 資料域ID和優先級資訊
  • 目前資料包的域優先級版本

排序政策

針對于域資料歸納,無論是在寫入資料的時候進行排序還是在讀取的時候進行查找都需要進行一次排序的操作,時間複雜度最優也是O(logn)級别的,在實際coding中發現由于在一個資料域裡面,資料包的Version資訊是連續唯一并且不存在斷層的,上一個穩定消費的資料體的Version資訊自增就是下一個資料包的Version,是以這裡采用了以Versio為主鍵的Map存儲,既降低了時間複雜度,也使得唯一辨別的資料包後抵達端側的包内容可以覆寫之前的包内容。

一些問題&解決政策

多資料來源和唯一資料消費的平衡

每當産生一條針對于目前使用者的資料包,如果目前ACCS長連結存在,就會通過ACCS将資料包推送到用戶端,如果App切換到背景一段時間,或者直接被殺死,ACCS連結斷開,那麼隻能通過離線推送到使用者的通知面闆。是以每當App切換到活躍狀态,都需要根據目前本地存儲的資料域資訊從背景觸發一次資料同步

資料包觸達到端側的來源主要是ACCS長連結的推送和域同步時拉的取到,但是資料包的消費是根據資料域的監聽劃分的唯一消費者,也就是同一時間内隻能消費一個資料包。

在壓力測試中,當背景短時間内密集的将資料包通過ACCS推送到端側時,端側接收到的資料包并不有序,不連續的資料包域版本又會觸發新的資料域同步,導緻同樣的一份資料包會通過兩個不同的管道多次的觸達到端側,浪費了不必要的流量。

當資料域同步時,這個時間節點産生的新資料包也會推送到端側,資料體有效,并且需要被正确的消費。

針對這些問題的解決政策:

在資料消費和資料擷取中間裝載一個資料中間層,當觸發資料域同步的時候block資料的讀取并且ACCS推送下來的資料包會被存放在一個資料的中轉站裡面,當資料域同步拉取的資料回來後,對資料進行合并後再重新開機資料讀取流程。

資料域優先級

需要推送到端側的資料包,根據業務的不同優先級也有不同的劃分,使用者和使用者的聊天産生的資料包會比營運類的消息的資料包優先級要高一些,是以要當多優先級的資料包快速的抵達端側時,高優先級資料域的資料包需要被優先消費,而資料域的優先級也是需要動态調整,不斷變換的優先級政策。

針對這個問題的解決政策:

不同的資料域,産生不同的資料隊列,高優隊列裡面的資料包會被優先讀取消費。

每一個資料包體中帶回的資料域資訊,都可以标注目前的資料域優先級,當資料域優先級發生變化的時候,調整資料包消費優先級政策。

優化效果

除去結構上分層梳理,使得資料同步層和依賴的服務内容可便捷解耦/每一個環節可插拔之外,資料同步中對于消息消費時長/流量節省,壓力測試場景下優化效果更加明顯。

壓力測試場景:500ms内100條全亂序資料包推送

消息處理時長(接收-上屏)提升 31%

流量損耗(最終拉取到端側資料包累積大小)降低35%

後續計劃

資料同步層能力提升

資料同步側的目标,既要保證資料包完整的到達端側,又要在保證穩定性的前提下盡可能的減少資料的拉取,使得每一次資料的擷取都有效。後續資料同步層會着手于有效資料率和到達率進行更進一步的優化。

  • 針對不同的場景,動态智能調整資料同步的優先級政策。
  • 阻塞式長連結推送,保證同一時間隻存在推模式或者拉模式,進一步減少備援資料包的推送。

閑魚IM端側整體架構更新

更新資料同步層政策主要還是要提升閑魚IM的能力,将資料同步分層後,接下來就是将消息的處理流程化,對每一個流程都可監控可回溯,提升IM資料包的正确解析存儲和落庫率。

  • 在資料來源側剝離開後,後續對IM的整改也會逐漸的将消息的處理分層剝離
  • 消息處理關鍵節點的流程式上報、建立完整的監控體系,讓問題發現先于使用者輿情
  • 消息完整性的動态自檢,最小化資料補償補全。

後續閑魚端側IM體驗更新系列文章歡迎大家關注

注: 該改造更新将于十一月中旬的版本和大家見面,敬請期待

繼續閱讀