天天看點

大規模手機定位采集系統設計一、業務場景分析二、抽象的系統架構三、技術選型四、異步讀寫設計五、總結

一、業務場景分析

基本的業務需求可分為兩大部分,第一部分是手機端間隔一定時間上報一次位置資訊,第二部分是背景系統可以實時看看手機裝置目前所在的位置,并繪制軌迹。

總之就是使用者安裝了此應用,就相當于給自己裝上了一個跟蹤器,所到之處,都将有所記錄。

我們先來保守計算一組資料,假定使用者基數為10萬,每隔5秒上報一次位置資訊,而這5秒期間,地圖SDK大概會給出2次定位資料,由此得出,一次上報的瞬時峰值大概是20萬條資料,一天将會達到300多萬的資料。

這樣的QPS已經算是很高了,當然,絕大多數情況下是不會觸頂的。

另外一方面,背景系統在查詢的時候,也面臨着一個巨大的挑戰:如何從海量的資料中找尋符合條件的那一部分?

查詢的條件無非是圍繞三個次元展開的:時間、對象和區域。

類似“查詢某塊地理位置栅欄内的所有使用者在一段時間内的位置資訊”,這就是一個典型的查詢業務需求,涵蓋了三個次元的條件。

當然,還有一些距離的測算和排序的需求也是在所難免的。

綜上所述,我們要解決兩個難點:

1、上報使用者的實時位置資訊;

2、處理海量資料的讀寫請求。

以上兩個難點是任何LBS應用不得不攻克的,這是支撐業務發展的關鍵點。

二、抽象的系統架構

我們可以将整個請求連結進行拆解,分别用對應的政策解決這部分的難題:

1、用戶端收集資料。這一部分有四個基本要求:準實時,不丢資料,低功耗,高效率。

2、網關限流。主要為了避免湧入大量無效請求,消耗系統資源,拖跨伺服器。

3、負載均衡。為了應對不斷增長的通路量,服務執行個體必須支援橫向擴充,多個執行個體之間按照一定的政策進行負載均衡。

4、異步化讀寫資料。需要借助中間件,起到削峰的作用,這一部分的設計會重點闡述。

5、資料存儲層高可用。采集的資料不要求強一緻性,依據CAP理論,滿足AP兩個條件即可。解決辦法通常是叢集化,避免單點故障,進而實作程式上的讀寫分離政策。

大規模手機定位采集系統設計一、業務場景分析二、抽象的系統架構三、技術選型四、異步讀寫設計五、總結

三、技術選型

接下來是針對上述五大部分在技術實作上的考量。

目前用戶端是蘋果機和安卓機,未來很可能會接入友商的車載OS。

在網絡狀況良好的時候,可以實時采集,實時上報,倘若網絡狀況不好,也不會丢資料,采用MMAP實作本地緩沖區。當然,為了上報效率,綜合考慮還是按批次上傳,過于頻繁的上報也會緻使耗電量攀升。

網關限流和負載均衡交給了nginx,學習和開發成本低,重要的是效果很好,并且能夠達到服務橫向擴充的目的。

我們使用了nginx基于ip位址的限流政策,同一個ip在1秒鐘内最多允許3個請求,burst=5,為了應對突然的流量的爆發,還有一個nodelay參數,我們選擇不加了,意味着請求隊列和緩沖區都被塞滿之後,直接傳回503錯誤碼,不再等待了。

目前,是1個master程序,5個worker子程序,此外,逾時時間、最大連接配接數以及緩沖區的設定值得斟酌,伺服器性能好的話,可以設定得高一些。負載均衡的政策不是基于權重的設定,而是使用的最少連接配接 (least_conn),因為在我看來,每個服務執行個體都是可以被同等對待的,哪台空閑,就優先請求哪台。如果非要在此基礎上設定一個weight,那就把性能高的伺服器設定成較高的權重。

為了應對大量的位置上報請求,必然需要引入消息隊列。因為技術團隊一直在使用RabbitMQ,并且一番壓測後,表現依然堅挺,是以成為了我們的不二選擇。

此外,為了減輕存儲層的壓力,在資料落盤前有一個緩沖機制,是典型的主從雙Buffer緩沖池,避免與存儲層頻繁互動,占用過多connection,提高了存儲層的工作效率,但是緩沖池Flush的時候,會帶來一次“IO尖刺”,可以調整緩沖池的Threshold,把“IO尖刺”控制在一個合理的範圍内。

最後,也是最引人關注的是存儲層的選型。我們面臨的選擇比較多,我們預研了4種有可能的方案:MySQL,Redis,PostGIS,MongoDB。

MySQL的方案有兩條路可走,第一是使用純SQL進行計算,很明顯這條路子受限于資料量,随着資料量的增大,計算量劇增,系統性能急劇下降。第二是使用MySQL的Spatial Indexes,但是這類空間索引是MySQL5.7版本引入的,不巧的是,我們用的是阿裡雲RDS,MySQL版本是5.6.16,不得不放棄MySQL的方案。

基于Redis GeoHash的方案,在性能方面是沒任何問題的,但是有一個重大的缺憾,就是非常受限于距離查詢,而無法友善的比對另外的附加屬性,也就是上述三維需求(時間、對象、區域)中,隻能滿足區域查詢的需求,若想進一步過濾,還需要借助其他的存儲技術。

留下來的PostGIS和MongoDB是現在比較通用的解決方案。

PostGIS的專業性很高,是地圖服務商的首選,對OGC的标準支援得非常全面,提供的函數庫也十分豐富。當然,MongoDB也不賴,3.0版本引入的WiredTiger存儲引擎,給MongoDB增色了不少,性能和并發控制都有了較大幅度的提升。

單就LBS應用來說,兩者都可以很好的滿足各方面的業務需求,性能也不是我們首要考慮的因素,因為兩者的可擴充性都很強,不容易觸及瓶頸。最後我們選擇了MongoDB,是因為技術團隊對此接受程度更高,MongoDB本來就是公司技術棧中的一員。PostGIS相對來說學習成本較高,因為Postgresql是一種關系型資料庫,如果隻接入普通的資料類型,其實相當于是維護了另一種MySQL,完全沒必要,但是如果想用上GIS相關資料類型,現有的ORM架構支援得并不友好,開發效率低,維護成本高。

四、異步讀寫設計

出于對使用者體驗的考慮,不能因為讀寫速度慢讓使用者傻傻的等待,這類問題有一個通用的解決方案:異步化。

異步化的寫請求很好實作,如前述所說,通過消息中間件來解決此問題,對于用戶端的位置上報請求,不需要強一緻性,能确定資料被塞入消息隊列中即可。

除此之外,還在消息隊列和存儲層之間加入了雙Buffer緩沖池,用以增加flush的效率。

大規模手機定位采集系統設計一、業務場景分析二、抽象的系統架構三、技術選型四、異步讀寫設計五、總結

上圖中的Buffer-1和Buffer-2共同組成一個循環隊列,每次隻有一個Buffer用了緩沖資料。圖中的Flush Point表示每個Buffer達到一定的門檻值(Threshold)後,将會觸發資料落盤,并且會在此刻切換Buffer。圖中所示的門檻值是50%,可以根據實際情況上下調整。

值得注意的是,在Flush Point,應該是先切換Buffer,再flush資料,也就是在flush的同時,還能接收上報的位置資訊。如果要等待flush完畢再切換,将會導緻流量過渡不平滑,出現一段時間的隊列擁塞。

接下來要解決大量讀請求,應對這種問題,有一個不二法門就是:拆。

非常類似“分表”的思想,但是在這個場景下,沒有傳統意義上“分表”所帶來的諸多副作用。

“分表”有一個規則,比如按Hash(user_id)進行“橫向分表”,按照常用字段進行“縱向分表”。受到Hadoop關于資源管理的啟發,在此位置采集系統中,使用了“中繼資料”來代替分表規則,這裡的“中繼資料”相當于NameNode,是管理資料的資料,将散落在不同位置的資料集中化管理。

大規模手機定位采集系統設計一、業務場景分析二、抽象的系統架構三、技術選型四、異步讀寫設計五、總結

如上圖所示,按城市級别進行分庫,每個城市的位置資料相對獨立,展現在用戶端的功能就是“切換城市”。“分表”意即分成多份Collection,以一天為最小粒度,因為一個城市的當天資料通常是“最熱”的,衆多查詢請求都需要這份資料,分頁,聚合,排序等需求都不是問題了,是以一天一個Collection是比較合理的切分。當然,如果一天的資料量過少,可以适當延長資料切分的周期。

那麼,如果查詢請求的時間段跨天了,該怎麼辦呢?

這時候,“中繼資料”就發揮威力了。

大規模手機定位采集系統設計一、業務場景分析二、抽象的系統架構三、技術選型四、異步讀寫設計五、總結

查詢請求分為兩部分,第一個是定位中繼資料,就是在meta data中找尋符合條件的所有Collection(s),為了盡可能縮小查詢範圍,需要指定一定的時間區段,這個也是有現實意義的。所有的位置資料被分為了三種等級:Hot,Cold,Freeze,Hot等級通常是指當天的資料,讀寫最頻繁的部分;Cold等級被界定為過去一個月内的資料,應對的各類查詢和分析的需求;Freeze等級是已歸檔的資料,沒有特殊情況不會被解凍。

通過時間區段拿到N個Collection(s)後,附加上其他的查詢條件,循環N次,成功循環一次,就渲染一次擷取到的資料,直到循環結束。

上述N>1的業務場景隻可能出現在背景管理系統,也就是移動端不會出現跨天的業務需求,提供的API都是針對Hot級别的資料。如果一旦出現了這種情況,可以限制時間區段,比如隻能擷取兩天内的資料。

五、總結

本文詳細闡述了手機定位采集系統的設計,整個系統的複雜性集中在了資料的存儲和呈現,我在此文中都給出了相應的解決方案。除此之外,整個采集系統還會有其他的功能子產品,諸如日志采集與分析,實時監控等,限于篇幅,不再逐一叙述了。

以下是擴充閱讀,對于了解整個系統會有所幫助,建議閱讀之。

1、細說雙Buffer緩沖池

2、物聯網裝置網關系統架構設計

掃描下方二維碼,進入原創幹貨,搞“技”聖地。

大規模手機定位采集系統設計一、業務場景分析二、抽象的系統架構三、技術選型四、異步讀寫設計五、總結

繼續閱讀