摘 要:本文設(shè)計了一種海量傳感器數(shù)據(jù)存儲系統(tǒng),使用MongoDB作為數(shù)據(jù)庫,同時使用Boos.Asio網(wǎng)絡(luò)庫應(yīng)對終端高并發(fā)請求。
【關(guān)鍵詞】MongoDB Asio 傳感器數(shù)據(jù) 存儲系統(tǒng)
1 引言
在物聯(lián)網(wǎng)當(dāng)中,每個終端節(jié)點每隔幾秒鐘就會將多個傳感器采集的數(shù)據(jù)傳輸?shù)椒?wù)器中,在大量終端節(jié)點的情況下會產(chǎn)生海量的數(shù)據(jù)。傳統(tǒng)關(guān)系型數(shù)據(jù)庫已經(jīng)無法滿足海量數(shù)據(jù)的存儲和管理,MongoDB是專門為解決海量數(shù)據(jù)而產(chǎn)生的,本系統(tǒng)使用MongoDB存儲海量傳感器數(shù)據(jù)。服務(wù)器端必須能夠處理大量終端節(jié)點的高并發(fā)請求,本系統(tǒng)使用Boost.Asio網(wǎng)絡(luò)庫應(yīng)對終端海量高并發(fā)請求。
2 MongoDB及其部署
2.1 MongoDB簡介
MongoDB的文檔、集合相當(dāng)于關(guān)系型數(shù)據(jù)庫中的行和表,其文檔使用BSON格式存儲,其典型格式如:{ id:123,temperature:23, humidity: 60}??梢娖浞浅_m合物聯(lián)網(wǎng)終端節(jié)點的傳感器數(shù)據(jù)的存儲。
MongoDB通過分片(Shard)和副本集(replica set)實現(xiàn)對數(shù)據(jù)的備份和高性能處理。分片,就是將一份數(shù)據(jù)分成多個片段,每個分片儲存不同的部分,分片不僅分擔(dān)了數(shù)據(jù)在硬盤的存儲,還分擔(dān)了數(shù)據(jù)操作對機器內(nèi)存、CPU、網(wǎng)絡(luò)的IO和硬盤的讀寫壓力。如圖1所示。
2.2 MongoDB集群部署
典型的MongoDB集群部署模型如圖1所示。每個分片就是mongod程序的實例,在進行數(shù)據(jù)的增刪查改操作時需要通過mongos程序?qū)⒄埱蠓职l(fā)到對應(yīng)的分片上,mongos起到了路由的功能,它需要從配置服務(wù)器(config server)讀分片和路由等元數(shù)據(jù)信息。replica set就是數(shù)據(jù)的備份,也是mongod程序的實例。在生產(chǎn)環(huán)境下根據(jù)業(yè)務(wù)的需求來確定服務(wù)器的數(shù)量和mongos、mongod以及config server的數(shù)量。在程序連接數(shù)據(jù)庫時,只要連接mongos的地址和端口即可。
3 程序設(shè)計
本程序的主要功能是處理終端海量的高并發(fā)請求,將數(shù)據(jù)解析后寫入MongoDB數(shù)據(jù)庫。
3.1 Boost.Asio簡介
Boost.Asio是一款非常優(yōu)秀的C++開源網(wǎng)絡(luò)庫,支持同步編程和異步編程,能夠構(gòu)建出能夠承受數(shù)千并發(fā)連接的應(yīng)用程序,并且不必涉及顯式鎖定和線程并發(fā)模型,從而避免使用多線程編程帶來的死鎖、條件競爭等。
3.2 配置模塊和日志模塊設(shè)計
在程序中,服務(wù)器端口號、MongoDB集群地址、程序并發(fā)執(zhí)行線程數(shù)等配置信息采用JSON格式文件存儲。使用Boost庫中的property_tree作為程序解析JSON文件的工具。日志可以幫助程序員在開發(fā)中快速定位bug,本程序使用boost::log記錄日志。
3.3 MongoDB模塊設(shè)計
在高并發(fā)請求下,為避免每次請求到來頻繁連接和關(guān)閉數(shù)據(jù)庫,MongoDB的C++驅(qū)動提供了線程安全的連接池。本模塊設(shè)計了Mymongo類,內(nèi)部封裝了mongo::ScopedDBConnection類,實例化該類,便獲得一個數(shù)據(jù)庫連接。在Mymongo類的構(gòu)造函數(shù)中完成對數(shù)據(jù)庫的連接認證等,在析構(gòu)函數(shù)中釋放連接到連接池。本程序只需要將終端數(shù)據(jù)插入到數(shù)據(jù)庫中,因此Mymongo類只實現(xiàn)了數(shù)據(jù)的插入功能。
3.4 請求處理模塊
本模塊實現(xiàn)了Service類,包含start()、accept_handler()、read_handler()三個成員函數(shù)。使用該類時,其執(zhí)行流程如圖2所示:首先執(zhí)行其start成員函數(shù),在函數(shù)中采用異步accept方式等待連接到來,其回調(diào)函數(shù)為accept_handler,當(dāng)連接到來后,執(zhí)行回調(diào)函數(shù),在其中采用異步方式讀取套接字,并注冊回調(diào)函數(shù)read_handler,因為是異步讀取,不等待讀取完畢,再次調(diào)用start函數(shù),等待下一個連接到來。當(dāng)套接字讀取完畢后,會調(diào)用read_handler,在函數(shù)中會解析終端發(fā)來的請求,并使用Mymongo類將數(shù)據(jù)寫入MongoDB數(shù)據(jù)庫。如圖2所示。
3.5 io_service模型選擇
io_service類是Boost.Asio的核心,相當(dāng)于前攝器模式中的Proactor角色,asio的任何操作都需要其參與。在主函數(shù)中首先實例化一個io_service對象,在實例化Service對象時作為其參數(shù),啟動Service對象的start()函數(shù)后,在多個線程中調(diào)用這個io_service對象的run()函數(shù)。這相當(dāng)于在多個線程中同時阻塞等待異步操作的完成,當(dāng)有異步操作完成時,便會調(diào)用相應(yīng)的回調(diào)函數(shù)。這是其最為常用的模型,可以編寫出非常健壯的應(yīng)用程序,本程序選擇一個io_service實例多個線程的模型。
4 結(jié)語
本文所設(shè)計的傳感器數(shù)據(jù)存儲系統(tǒng),使用了MongoDB數(shù)據(jù)庫存儲管理海量數(shù)據(jù),并使用Boost.Asio網(wǎng)絡(luò)庫的異步編程方式,配合多線程技術(shù),編寫了能夠接收海量高并發(fā)請求的服務(wù)器端程序,在程序中使用MongoDB連接池來連接數(shù)據(jù)庫,避免資源的浪費。
參考文獻
[1]郭匡宇.基于MongoDB的傳感器數(shù)據(jù)分布式存儲的研究與應(yīng)用[D].南京郵電大學(xué),2013.
[2]MongoDB.sharding. https://docs.mongodb.org/manual/core/sharding-introduction/.
[3]Boost.Asio. http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio.html.
作者簡介
李曉(1989-),男,現(xiàn)為中國海洋大學(xué)信息科學(xué)與工程學(xué)院信號與信息處理專業(yè)在讀研究生。
作者單位
中國海洋大學(xué)信息科學(xué)與工程學(xué)院 山東省青島市 266100