石清
摘? 要:在“互聯(lián)網(wǎng)+”概念的影響下,越來越多的信息技術(shù)應(yīng)用于體育產(chǎn)業(yè)。本文通過構(gòu)建基于MEAN框架的體育競(jìng)賽實(shí)時(shí)數(shù)據(jù)管理系統(tǒng),設(shè)計(jì)了一種結(jié)合本地存儲(chǔ)與遠(yuǎn)端云數(shù)據(jù)庫(kù)的分布式存儲(chǔ)方案,既實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)分享,又保障數(shù)據(jù)的可靠性。并通過實(shí)驗(yàn)的方式比較了基于HTML5 Local Storage本地存儲(chǔ)的兩種方法與本地NoSQL數(shù)據(jù)庫(kù)的性能差異,從而實(shí)現(xiàn)系統(tǒng)存儲(chǔ)方案的優(yōu)化。
關(guān)鍵詞:實(shí)時(shí)數(shù)據(jù)共享;競(jìng)賽系統(tǒng);MEAN框架;RESTful接口
中圖分類號(hào):TP311? ? ?文獻(xiàn)標(biāo)識(shí)碼:A
Abstract: Under the influence of the Internet + concept, more and more information technology is used in sports industry. By constructing a real-time data management system for sports competitions based on the MEAN (MongoDB +
Express + AngularJS + NodeJS) framework, this paper proposes to design a distributed storage scheme that combines local storage and remote cloud database, which realizes real-time data sharing and guarantees data reliability. Performance difference between the two methods based on HTML5 Local Storage and local NOSQL (Not Only SQL) database is compared through experiment, so to optimize the system storage scheme.
Keywords: real-time data sharing; competition system; MEAN framework; RESTful interface
1? ?引言(Introduction)
隨著互聯(lián)網(wǎng)信息技術(shù)的發(fā)展,云計(jì)算和云數(shù)據(jù)庫(kù)以其可伸縮性、高可靠性等特點(diǎn)受到了開發(fā)者和企業(yè)的青睞,越來越多的企業(yè)將其服務(wù)和數(shù)據(jù)轉(zhuǎn)移到云上。這些海量的數(shù)據(jù)如果可以通過接口的形式實(shí)現(xiàn)共享,將為大數(shù)據(jù)的分析和挖掘提供數(shù)據(jù)。然而沖突數(shù)據(jù)和時(shí)效錯(cuò)誤數(shù)據(jù)相疊加而產(chǎn)生的錯(cuò)誤數(shù)據(jù)將產(chǎn)生嚴(yán)重的后果,德國(guó)數(shù)據(jù)分析機(jī)構(gòu)的調(diào)查顯示:美國(guó)每年因?yàn)榱淤|(zhì)數(shù)據(jù)而造成的損失高達(dá)6,000 億美元[1]。因此,保證數(shù)據(jù)的可靠性乃是數(shù)據(jù)最重要的因素之一,建立在低質(zhì)量數(shù)據(jù)基礎(chǔ)之上的數(shù)據(jù)分析、數(shù)據(jù)挖掘?qū)?huì)變成一紙空談,甚至?xí)a(chǎn)生重大的錯(cuò)誤。
有時(shí)為了確保數(shù)據(jù)的可靠性,往往會(huì)以犧牲數(shù)據(jù)的實(shí)時(shí)性為代價(jià)。而體育賽事信息的變動(dòng)和不確定性,要求信息傳播最大程度地追求時(shí)效性與接收的便捷性[2]。而傳統(tǒng)競(jìng)賽服務(wù)系統(tǒng)多采用C/S構(gòu)架,前期需要較大的硬件成本投入,同時(shí)開發(fā)周期長(zhǎng)、成本高,除個(gè)別大型綜合性賽事外,單項(xiàng)體育比賽的競(jìng)賽系統(tǒng)幾乎不具備實(shí)時(shí)分享數(shù)據(jù)的能力。而基于B/S
架構(gòu)的系統(tǒng)除了開發(fā)周期端、成本低、系統(tǒng)可擴(kuò)展性高之外,數(shù)據(jù)信息服務(wù)通過連接特定的數(shù)據(jù)接口,實(shí)現(xiàn)數(shù)據(jù)實(shí)時(shí)通訊,既能服務(wù)于電視直播、現(xiàn)場(chǎng)大屏幕的數(shù)據(jù)需求,還能為所有對(duì)實(shí)時(shí)數(shù)據(jù)有需求的應(yīng)用提供數(shù)據(jù)支持。賽后,所有的數(shù)據(jù)還可用于其他分享和數(shù)據(jù)挖掘,以達(dá)到數(shù)據(jù)價(jià)值利用最大化。本文研究的目的就是建立一套體育競(jìng)賽數(shù)據(jù)管理系統(tǒng),既要滿足實(shí)時(shí)傳播的需要,又要建立在高可靠性的數(shù)據(jù)基礎(chǔ)之上。
2? ?系統(tǒng)框架(System framework)
2.1? ?相關(guān)技術(shù)介紹
本文采用MEAN框架進(jìn)行系統(tǒng)開發(fā)。MEAN框架是一個(gè)JavaScript平臺(tái)下現(xiàn)代Web開發(fā)框架的總稱,是MongoDB、Express、Angular、Node.js四個(gè)框架的第一個(gè)字母組合的簡(jiǎn)稱。Node.js是一個(gè)基于Chrome JavaScript運(yùn)行時(shí)建立的平臺(tái),用于搭建響應(yīng)速度快、易于擴(kuò)展的網(wǎng)絡(luò)應(yīng)用[3]。Node.js本身的特點(diǎn)非常適合在分布式設(shè)備上運(yùn)行數(shù)據(jù)密集型的實(shí)時(shí)應(yīng)用。它采用一系列“非阻塞”I/O模型庫(kù)來支持事件循環(huán)方式,為文件系統(tǒng)、數(shù)據(jù)庫(kù)等資源提供接口,通過異步的方式實(shí)現(xiàn)數(shù)據(jù)的非阻塞傳輸。Express是一款基于Node.js的Web應(yīng)用開發(fā)框架。Express雖然規(guī)模小巧,卻為Web和移動(dòng)應(yīng)用程序提供一組強(qiáng)大的功能。Angular是由Google公司開發(fā)和維護(hù)前端的應(yīng)用框架,其核心特點(diǎn)包括MVVM、模塊化、自動(dòng)化雙向數(shù)據(jù)綁定、語(yǔ)義化標(biāo)簽、依賴注入等。MongoDB是NoSQL的一種,可以方便地存儲(chǔ)復(fù)雜的數(shù)據(jù)類型。其由于高性能、易部署、易使用,以及存儲(chǔ)數(shù)據(jù)方便等特點(diǎn),是目前應(yīng)用最廣泛的NoSQL數(shù)據(jù)庫(kù)。
2.2? ?RESTful接口
在系統(tǒng)設(shè)計(jì)和實(shí)現(xiàn)的過程中,始終以RESTful接口的形式實(shí)行數(shù)據(jù)的互聯(lián)共享。無(wú)論是現(xiàn)場(chǎng)比分、歷史戰(zhàn)績(jī),還是賽隊(duì)或隊(duì)員的相關(guān)信息都可以通過統(tǒng)一的數(shù)據(jù)接口實(shí)現(xiàn)訪問,從而避免了運(yùn)動(dòng)項(xiàng)目或賽事因業(yè)務(wù)與功能的不同,建立數(shù)據(jù)彼此獨(dú)立、相互封閉信息的“信息孤島”[4];以資源的方式提供數(shù)據(jù)服務(wù)可以提高體育信息數(shù)據(jù)的有效集成,擴(kuò)大媒介的傳播效果[5]。以信息服務(wù)為目標(biāo),提供體育賽事相關(guān)資料的綜合性服務(wù),必將成為大型體育賽事信息服務(wù)變革的方式,對(duì)于實(shí)現(xiàn)信息服務(wù)系統(tǒng)化、標(biāo)準(zhǔn)化以及提高信息利用率,具有重要意義[6]。
進(jìn)行RESTful風(fēng)格的API設(shè)計(jì)時(shí),需要客戶端和服務(wù)器之間的交互在請(qǐng)求之間是無(wú)狀態(tài)的。所謂無(wú)狀態(tài)即所有的資源都是通過URI進(jìn)行定位的,而且該URI提供的資源與其他資源無(wú)關(guān),也不會(huì)因?yàn)槠渌Y源的變化而改變[7]。例如,查詢某運(yùn)動(dòng)員的成績(jī),如果查詢成績(jī)時(shí)需要登錄成績(jī)管理系統(tǒng),進(jìn)入特定的成績(jī)查詢頁(yè)面,執(zhí)行相關(guān)操作后獲取該名運(yùn)動(dòng)員的歷史成績(jī),上述情況則屬于有狀態(tài),因?yàn)椴樵冞\(yùn)動(dòng)員歷史成績(jī)的每一步操作都依賴于前一步操作的結(jié)果,只要前置操作失敗,則后續(xù)操作就無(wú)法執(zhí)行。如果在瀏覽器地址欄中輸入一個(gè)URL地址即可返回某運(yùn)動(dòng)員的歷史成績(jī),則該情況屬于無(wú)狀態(tài),因?yàn)楂@取運(yùn)動(dòng)員成績(jī)資源不依賴于其他資源或狀態(tài),而是與一個(gè)URL地址相對(duì)應(yīng),可以通過HTTP的GET方法得到該資源。
3? ?數(shù)據(jù)存儲(chǔ)方案設(shè)計(jì)(Design of data storage)
高質(zhì)量的數(shù)據(jù)信息服務(wù),除了追求數(shù)據(jù)在分享方面的高效之外,對(duì)數(shù)據(jù)的準(zhǔn)確性也有相當(dāng)高的要求。不以數(shù)據(jù)質(zhì)量為前提的數(shù)據(jù)服務(wù),其后果必然是災(zāi)難性的。因此,系統(tǒng)的數(shù)據(jù)存儲(chǔ)方案就顯得格外重要,既要保證數(shù)據(jù)便于分享,也要保證數(shù)據(jù)準(zhǔn)確。如果僅僅采用單一性的數(shù)據(jù)庫(kù)將很難滿足需求。
系統(tǒng)存儲(chǔ)方案采用的是本地與云端同步存儲(chǔ)的模式,如圖1所示。系統(tǒng)前端通過AJAX發(fā)送數(shù)據(jù)到云數(shù)據(jù)庫(kù),并通過云數(shù)據(jù)庫(kù)實(shí)現(xiàn)數(shù)據(jù)的實(shí)時(shí)分享,但由于不可預(yù)測(cè)的網(wǎng)絡(luò)原因,存儲(chǔ)過程有可能會(huì)出現(xiàn)長(zhǎng)時(shí)間延遲,甚至失敗。而競(jìng)技體育賽事往往無(wú)法重賽,如果出現(xiàn)數(shù)據(jù)丟失的情況將是非常嚴(yán)重的事故。這不僅無(wú)法滿足數(shù)據(jù)分享的需求,更有可能因?yàn)楦?jìng)賽數(shù)據(jù)的丟失導(dǎo)致賽事無(wú)法正常進(jìn)行。本地存儲(chǔ)由于沒有網(wǎng)絡(luò)依賴,能保證數(shù)據(jù)的完整性和準(zhǔn)確性。系統(tǒng)通過同時(shí)向本地和云端存儲(chǔ)數(shù)據(jù),確保競(jìng)賽數(shù)據(jù)不會(huì)丟失。同時(shí),將本地?cái)?shù)據(jù)與云數(shù)據(jù)庫(kù)進(jìn)行數(shù)據(jù)一致性校對(duì),避免由于網(wǎng)絡(luò)原因造成云端數(shù)據(jù)丟失,確保云端數(shù)據(jù)的完整性。用戶通過向云數(shù)據(jù)庫(kù)發(fā)送請(qǐng)求,獲取準(zhǔn)確的競(jìng)賽實(shí)時(shí)數(shù)據(jù)。
在數(shù)據(jù)庫(kù)選擇方面,以MySQL為代表的傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)在處理海量數(shù)據(jù)文檔時(shí)有其固有的局限性,很難滿足海量數(shù)據(jù)的柔性管理需求[8]。而以MongoDB為代表的NoSQL數(shù)據(jù)庫(kù)卻能夠很好地應(yīng)對(duì)非結(jié)構(gòu)化的數(shù)據(jù)存儲(chǔ),對(duì)于表結(jié)構(gòu)需要臨時(shí)調(diào)整、字段不固定、快速響應(yīng)海量數(shù)據(jù)寫入等方面都具有相當(dāng)明顯的優(yōu)勢(shì)。同時(shí)有研究表明,MongoDB數(shù)據(jù)庫(kù)與MySQL數(shù)據(jù)庫(kù)相比,多線程、高并發(fā)情況下的數(shù)據(jù)插入性能明顯高得多[7]。最終,系統(tǒng)服務(wù)器端選擇以MongoDB為存儲(chǔ)數(shù)據(jù)庫(kù)。
本地存儲(chǔ)的選擇,同樣將MongoDB作為主要的候選對(duì)象,同時(shí),由于整個(gè)競(jìng)賽系統(tǒng)只需要存儲(chǔ)與比賽相關(guān)的數(shù)據(jù)信息,而運(yùn)動(dòng)員信息、賽隊(duì)信息、往期賽事成績(jī)等相關(guān)數(shù)據(jù)無(wú)須進(jìn)行存儲(chǔ),數(shù)據(jù)量并不大。在確認(rèn)云端數(shù)據(jù)完整無(wú)誤之后,本地?cái)?shù)據(jù)可以刪除。所以,HTML5 Local Storage也可作為候選對(duì)象。
4? 存儲(chǔ)性能優(yōu)化(Storage performance optimization)
在明確存儲(chǔ)方案之后,為進(jìn)一步優(yōu)化該方案,在系統(tǒng)設(shè)計(jì)過程中,對(duì)本地各存儲(chǔ)備選方案進(jìn)行了性能測(cè)試,以選出最優(yōu)本地存儲(chǔ)方案。
4.1? ?測(cè)試環(huán)境
測(cè)試環(huán)境使用的是Intel Core i7 2.5 GHz CPU,16 GB
內(nèi)存、AMD Radeon R9 M370X 2048 MB顯存的GPU,操作系統(tǒng)為macOS Sierra 10.12.1,測(cè)試用的瀏覽器分別是Safari、Chrome和Opera。由于在macOS中不支持Windows操作系統(tǒng)下常用的IE瀏覽器,因此沒有在IE瀏覽器中進(jìn)行測(cè)試。
4.2? ?測(cè)試方法
分別調(diào)用HTML5原生Local Storage方法、自定義基于Angular Service規(guī)范的HTML5 Local Storage方法(以下簡(jiǎn)稱Angular Local Storage Service),以及本地MongoDB Service方法,比較它們?cè)谙嗤鎯?chǔ)次數(shù)下所消耗的時(shí)間。存儲(chǔ)的對(duì)象是一個(gè)不斷增加的MongoDB ObjectId對(duì)象數(shù)組。設(shè)置這樣的存儲(chǔ)測(cè)試方法,一方面是因?yàn)槟ν型н@類環(huán)圈競(jìng)速賽比賽規(guī)則的原因;另一方面這也是NoSQL數(shù)據(jù)庫(kù)的優(yōu)勢(shì)所在,無(wú)須像SQL數(shù)據(jù)庫(kù)一樣,每條數(shù)據(jù)順序插入數(shù)據(jù)庫(kù)中,而只需要修改文檔數(shù)據(jù)庫(kù)的字段內(nèi)容即可。同時(shí),該數(shù)據(jù)結(jié)構(gòu)也更有利于進(jìn)行與云端的數(shù)據(jù)一致性校驗(yàn)。
測(cè)試的存儲(chǔ)次數(shù)分別為100、1,000、2,000、3,000、4,000和5,000,最終判斷Safari、Chrome和Opera三款瀏覽器的性能優(yōu)劣。由于在真實(shí)比賽過程中,系統(tǒng)存儲(chǔ)數(shù)據(jù)I/O的頻次遠(yuǎn)低于實(shí)驗(yàn)設(shè)計(jì),同時(shí)實(shí)驗(yàn)的主要目的是為了找出在較低頻次下,各個(gè)儲(chǔ)存方案的性能差異,因此本次實(shí)驗(yàn)的最大測(cè)試次數(shù)設(shè)置為5,000,沒有繼續(xù)增大循環(huán)測(cè)試次數(shù)。
實(shí)際測(cè)試過程中,通過在循環(huán)開始前后分別調(diào)用Date.now()方法獲取系統(tǒng)時(shí)間,通過比較兩次系統(tǒng)時(shí)間的時(shí)間差來確定循環(huán)運(yùn)行所消耗的時(shí)間。以HTML5 Local Storage測(cè)試的實(shí)驗(yàn)代碼為例:
saveByLocalStorage(data){
let tempArray = [];
let tempObject = {};
let startTime = Date.now();
for(let i=0;i tempArray.push(data); tempObject['result'] = tempArray; localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(tempObject)); } let endTime = Date.now(); console.log("LocalStorage Testing Duration Time :" + (endTime - startTime));} Angular的結(jié)構(gòu)框架不推薦直接使用組件獲取或者保存數(shù)據(jù),雖然直接調(diào)用HTML5 Local Storage方法可以實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)和讀取,但是與Angular的理念不一致。因此在開發(fā)的過程中獨(dú)立編寫了一個(gè)基于HTML5 Local Storage的Service,再通過Angular的依賴注入機(jī)制應(yīng)用于系統(tǒng)之中。 class LocalStorageService { constructor(storage) { this.storage = storage; } get(key) { try { return JSON.parse(this.storage.getItem(key)); } catch (error) { return null; } } set(key, value) { this.storage.setItem(key, JSON.stringify (value));} remove(key) { this.storage.removeItem(key); } } 保存到本地MongoDB數(shù)據(jù)庫(kù)時(shí),利用Angular的Observable對(duì)象,借助RxJS庫(kù)對(duì)數(shù)據(jù)流進(jìn)行異步處理,在Angular中幾乎都使用該方法來處理AJAX請(qǐng)求和響應(yīng)。在Angular前端設(shè)置比賽成績(jī)的Service的數(shù)據(jù)服務(wù)之前,需要在服務(wù)器端創(chuàng)建RESTful風(fēng)格的數(shù)據(jù)接口用以滿足前端的需要。由于是以競(jìng)賽成績(jī)?yōu)闇y(cè)試內(nèi)容,而競(jìng)賽成績(jī)本身屬于敏感信息,不能允許任意用戶進(jìn)行隨意的創(chuàng)建、修改和刪除,因此在接口設(shè)計(jì)時(shí)除GET方法外,其他所有方法都進(jìn)行了權(quán)限管理,必須管理員用戶才可以訪問這些接口。 5? ?實(shí)驗(yàn)結(jié)果(Experimental results) 在實(shí)際測(cè)試中,分別在Safari、Chrome和Opera三款瀏覽器運(yùn)行測(cè)試程序,所有測(cè)試結(jié)果均在console面板中顯示。從測(cè)試結(jié)果來看,Safari、Chrome和Opera三款瀏覽器在HTML5 Local Storage、Angular Local Storage Service和本地MongoDB Service這三項(xiàng)測(cè)試中,所表現(xiàn)出的性能沒有顯著差異。這三款瀏覽器在HTML5 Local Storage和Angular Local Storage Service的測(cè)試對(duì)比中,均表現(xiàn)出用Angular Service標(biāo)準(zhǔn)寫出的方法比直接調(diào)用HTML5 Local Storage有5%左右的性能優(yōu)勢(shì)。用Angular Service標(biāo)準(zhǔn)編寫的服務(wù)本身調(diào)用的就是HTML5 Local Storage,雖然只是用Angular Service的規(guī)范將HTML5 Local Storage進(jìn)行封裝,但Angular Service服務(wù)由于在構(gòu)建Component時(shí)已經(jīng)加載成功,因此會(huì)表現(xiàn)出5%左右的性能優(yōu)勢(shì)。 而無(wú)論是HTML5 Local Storage還是Angular Local Storage Service,在測(cè)試次數(shù)在3,000以下時(shí),與本地MongoDB Service都存在著數(shù)量級(jí)上的優(yōu)勢(shì)。隨著測(cè)試次數(shù)增多,它們之間的差異雖然縮小,性能差距依然在三倍以上。 具體測(cè)試結(jié)果如表1—表3所示。 從整體的測(cè)試結(jié)果來看,使用Local Storage的存儲(chǔ)方案明顯會(huì)更加具有優(yōu)勢(shì)。Angular Local Storage Service的方法雖然在開發(fā)過程中比直接調(diào)用HTML5 Local Storage要復(fù)雜一些,但是其兼顧Angular Service的模式,同時(shí)還具備5%左右的性能優(yōu)勢(shì),所以在最終開發(fā)過程中選用的是Angular Local Storage Service的開發(fā)方式。 6? ?結(jié)論(Conclusion) 對(duì)于追求時(shí)效性的B/S架構(gòu)系統(tǒng)來說,以RESTful風(fēng)格進(jìn)行API設(shè)計(jì)將極大地方便數(shù)據(jù)分享和協(xié)同開發(fā)的效率,降低開發(fā)過程中出錯(cuò)的概率。同時(shí),將所有的數(shù)據(jù)以資源的形式為外界提供服務(wù)時(shí),將最大程度消除信息化障礙,確保所有人能夠暢通地獲取體育服務(wù)信息。 數(shù)據(jù)存儲(chǔ)方案采用本地與云端同步存儲(chǔ)的模式設(shè)計(jì)與開發(fā),提高了系統(tǒng)的容錯(cuò)率,增加了數(shù)據(jù)的可靠性。在本地存儲(chǔ)方案選擇方面,采用Web瀏覽器提供的Local Storage足以滿足臨時(shí)性的需求,且性能與本地MongoDB數(shù)據(jù)庫(kù)相比,在低頻次的使用時(shí)具有數(shù)量級(jí)上的優(yōu)勢(shì),可優(yōu)先考慮以HTML5 Local Storage作為臨時(shí)存儲(chǔ)數(shù)據(jù)庫(kù)對(duì)象。在以Angular為前端開發(fā)框架時(shí),基于Angular標(biāo)準(zhǔn)的service存儲(chǔ)性能比直接調(diào)用HTML5 Local Storage具有5%左右的性能優(yōu)勢(shì),可優(yōu)先考慮。 參考文獻(xiàn)(References) [1] 杜岳峰,申德榮,聶鐵錚.基于關(guān)聯(lián)數(shù)據(jù)的一致性和時(shí)效性清洗方法[J].計(jì)算機(jī)學(xué)報(bào),2017,40(1):92-105. [2] 冉榮.自媒體背景下體育微博的發(fā)展及價(jià)值[J].新媒在線,2017(11):147-148. [3] 王伶俐.基于NodeJS + Express框架的輕應(yīng)用定制平臺(tái)的設(shè)計(jì)與實(shí)現(xiàn)[J].計(jì)算機(jī)科學(xué),2017(11):596-599. [4] 王家宏,孫晉海,伊超.基于數(shù)據(jù)集成的水上項(xiàng)目國(guó)家隊(duì)數(shù)據(jù)庫(kù)網(wǎng)絡(luò)管理平臺(tái)的設(shè)計(jì)與開發(fā)[J].山東體育學(xué)院學(xué)報(bào),2015(1):1-7. [5] 林寧波.大數(shù)據(jù)時(shí)代體育信息傳播改革路徑[J].大統(tǒng)計(jì),2018(3):31-33. [6] 王廣田,張文蓮.大型體育賽事檔案信息服務(wù)的困境與變革[J].山西檔案,2018(7):130-132. [7] Haviv, Amos Q. MEAN Web Development: Master real-time web application development using a mean combination of MongoDB, Express, Angular JS, and Node.js[M]. Birmingham, UK: Packet Publishing, 2014:2-8. [8] 胡小春,李陶深,王樂.基于NoSQL的大數(shù)據(jù)應(yīng)用設(shè)計(jì)與性能保障方案研究[J].廣西大學(xué)學(xué)報(bào)(自然科學(xué)版),2014(6):633-640. 作者簡(jiǎn)介: 石? ?清(1981-),男,碩士,講師.研究領(lǐng)域:體育信息技術(shù),人機(jī)工程學(xué).