梅巧玲,王明哲,張志強,楊立鵬
(中國鐵道科學(xué)研究院 電子計算技術(shù)研究所,北京 100081)
互聯(lián)網(wǎng)售票系統(tǒng)上線以來,以其便捷性迅速得到認可,越來越多的旅客通過互聯(lián)網(wǎng)進行購票,互聯(lián)網(wǎng)售票量呈大幅增長的態(tài)勢,高峰期的大并發(fā)請求對互聯(lián)網(wǎng)售票系統(tǒng)的壓力更是屢創(chuàng)新高。互聯(lián)網(wǎng)售票系統(tǒng)在為旅客提供極大便利的同時,也必須確保在大并發(fā)訪問時穩(wěn)定高效運行,尤其是訂票過程中需要高頻度訪問的功能。
互聯(lián)網(wǎng)余票查詢是互聯(lián)網(wǎng)售票系統(tǒng)的頻繁訪問的功能之一,是旅客購票關(guān)注的焦點,在節(jié)假日期間,系統(tǒng)的訪問量會急劇增加,導(dǎo)致整個系統(tǒng)后臺數(shù)據(jù)庫壓力過大,響應(yīng)速度變慢,用戶的體驗度降低。余票查詢業(yè)務(wù)是具有很多動態(tài)邏輯規(guī)則的實時運算系統(tǒng),數(shù)據(jù)變化頻繁,運算量較多,提高余票查詢的效率顯得尤為重要。在提升查詢效率和并發(fā)性能方面,原有基于關(guān)系型數(shù)據(jù)庫存儲過程編寫的業(yè)務(wù)邏輯已經(jīng)做了接近數(shù)據(jù)庫處理極限的優(yōu)化,但對于互聯(lián)網(wǎng)高并發(fā)的訪問量來說,仍然遠遠不能滿足系統(tǒng)的需求。內(nèi)存數(shù)據(jù)庫技術(shù)為互聯(lián)網(wǎng)余票查詢業(yè)務(wù)提供了較為合適可行的解決方案。
磁盤數(shù)據(jù)庫是把數(shù)據(jù)存放在磁盤上進行管理,需要頻繁的訪問磁盤來進行數(shù)據(jù)的操作,強調(diào)維護數(shù)據(jù)的完整性、一致性和系統(tǒng)的高吞吐量,當(dāng)數(shù)據(jù)量很大時,由于磁盤存取、內(nèi)外存的數(shù)據(jù)傳遞、緩沖區(qū)管理、排隊等待及鎖的延遲等使得事務(wù)實際平均執(zhí)行時間與估算的最壞情況執(zhí)行時間相差很大,數(shù)據(jù)的讀寫性能會下降很多,數(shù)據(jù)的實時性和處理性能也不是很高。
相對于磁盤而言,內(nèi)存使得每個事務(wù)在執(zhí)行過程中沒有I/O,數(shù)據(jù)的讀寫速度要高出幾個數(shù)量級,將數(shù)據(jù)保存在內(nèi)存中相比從磁盤上訪問能夠極大地提高應(yīng)用的性能。內(nèi)存數(shù)據(jù)庫拋棄了磁盤數(shù)據(jù)管理的傳統(tǒng)方式,基于全部數(shù)據(jù)都存儲在內(nèi)存中,重新設(shè)計了體系結(jié)構(gòu),數(shù)據(jù)以Key-Value形式存儲,并且在數(shù)據(jù)緩存、快速算法、并發(fā)控制與恢復(fù)的算法方面也進行了相應(yīng)的改進,可提供高速訪問和動態(tài)擴展。內(nèi)存數(shù)據(jù)庫的最大特點是其“主拷貝”或“工作版本”常駐內(nèi)存,即活動事務(wù)只與實時內(nèi)存數(shù)據(jù)庫的內(nèi)存拷貝打交道。它所處理的數(shù)據(jù)通常是有一定的有效時間,實時產(chǎn)生新的數(shù)據(jù),過期的數(shù)據(jù)會被定期清理掉。分布式內(nèi)存數(shù)據(jù)庫是將海量數(shù)據(jù)基于特定算法分散在多個服務(wù)器節(jié)點上,當(dāng)進行計算時,多個節(jié)點可并發(fā)執(zhí)行數(shù)據(jù)運算任務(wù),大大縮短運算時間。內(nèi)存數(shù)據(jù)庫與磁盤數(shù)據(jù)庫的差異如表1。

表1 內(nèi)存數(shù)據(jù)庫與磁盤數(shù)據(jù)庫的差異
由表1可以看出,內(nèi)存數(shù)據(jù)庫可以提供比磁盤數(shù)據(jù)庫好得多的響應(yīng)時間、事務(wù)吞吐量和查詢性能,這對那些要求事務(wù)在特定期限內(nèi)完成的實時應(yīng)用尤為重要,非常適合處理互聯(lián)網(wǎng)售票系統(tǒng)中實時性強、高并發(fā)、響應(yīng)快的余票查詢業(yè)務(wù)。
內(nèi)存數(shù)據(jù)庫對于互聯(lián)網(wǎng)售票系統(tǒng)來說,并不是產(chǎn)生數(shù)據(jù)的源點,如何把在傳統(tǒng)數(shù)據(jù)庫中產(chǎn)生的業(yè)務(wù)數(shù)據(jù)也就是余票等數(shù)據(jù)同步到內(nèi)存數(shù)據(jù)庫中,需要采用中間件技術(shù)、復(fù)制技術(shù)、消息隊列機制來實現(xiàn)。分布式內(nèi)存數(shù)據(jù)同步流程如圖1所示。
當(dāng)關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)發(fā)生變化時,中間件服務(wù)將偵聽到的日志變化所影響的的數(shù)據(jù)變化,發(fā)送到Message Queue Server服務(wù)器上,再由接收端Receiver將MQ Server中的消息發(fā)送到內(nèi)存數(shù)據(jù)庫中,實現(xiàn)數(shù)據(jù)的同步。
由于接收端 Receiver依賴的庫多并且復(fù)雜,采用直接調(diào)用的方式會導(dǎo)致異構(gòu)系統(tǒng)之間的耦合度太緊密,一旦Client端發(fā)生變化,還需要同時修改接收端的代碼,造成系統(tǒng)的可維護性差。使用Message Queue Server作為異構(gòu)系統(tǒng)之間的中轉(zhuǎn),關(guān)系型數(shù)據(jù)庫和內(nèi)存數(shù)據(jù)庫的客戶端Client并不直接通信,雙方只和Message Queue Server建立連接,這種松耦合的設(shè)計,帶來了互相依賴性小,可維護性高的好處。
在系統(tǒng)初始化時先將全量數(shù)據(jù)導(dǎo)入到內(nèi)存中,建立索引緩存,之后在數(shù)據(jù)修改時,通過listener監(jiān)控觸發(fā)與之相關(guān)的小范圍內(nèi)的索引重建,保證數(shù)據(jù)的及時性。
實時同步的數(shù)據(jù)包括兩類:基礎(chǔ)數(shù)據(jù)和業(yè)務(wù)數(shù)據(jù)。基礎(chǔ)數(shù)據(jù)變化不頻繁,數(shù)據(jù)量小,包括車次數(shù)據(jù)、停靠站數(shù)據(jù)、票價數(shù)據(jù)、調(diào)令數(shù)據(jù)等;業(yè)務(wù)數(shù)據(jù)變化頻繁,數(shù)據(jù)量大,主要是余票相關(guān)數(shù)據(jù)。

圖1 分布式內(nèi)存數(shù)據(jù)庫數(shù)據(jù)同步流程

圖2 分布式內(nèi)存數(shù)據(jù)庫調(diào)用模式
互聯(lián)網(wǎng)查詢客戶端和內(nèi)存數(shù)據(jù)庫服務(wù)器之間也是采用松耦合的方式,只需配置服務(wù)器地址和端口號,任何服務(wù)器端的改動都不會影響到客戶端。Client收到查詢請求后將其劃分為多個子任務(wù),將任務(wù)分配到多個節(jié)點Server上進行并行運算,運算完成后,將結(jié)果進行匯總并返回。分布式內(nèi)存數(shù)據(jù)庫調(diào)用模式,如圖2所示。
互聯(lián)網(wǎng)余票查詢的邏輯運算能力的提高僅僅基于內(nèi)存的架構(gòu)是不能滿足需求的,充分發(fā)揮CPU的計算能力也是必須的。一個復(fù)雜的余票查詢,如上海至南京的車次有300多列,其中一些K字頭的車,還要處理復(fù)雜的共用定義邏輯,循環(huán)次數(shù)非常多。在邏輯算法已經(jīng)優(yōu)化的情況下,一次查詢所要進行的運算量無論存儲計算還是基于內(nèi)存計算其實是相當(dāng)?shù)摹?/p>
提高性能的關(guān)鍵在于大任務(wù)的合理分解,進行分布式運算,再進行結(jié)果的匯總。分布式處理的基本前提是避免分布,或者說盡可能少的網(wǎng)絡(luò)交互,數(shù)據(jù)與處理邏輯在同一片內(nèi)存區(qū)域,只有處理結(jié)果會輸出到同一個點。以此為出發(fā)點,需要在余票查詢所涉及的數(shù)據(jù)中找出一個合適的切分方式,使得相關(guān)數(shù)據(jù)能夠很容易的切分開來而又具備獨立的完整性。
通過分析現(xiàn)有數(shù)據(jù)的分布情況可以看到,余票數(shù)據(jù)、車次數(shù)據(jù)以及共用數(shù)據(jù)涉及復(fù)雜邏輯的數(shù)據(jù)表都是與車次相關(guān)的,因此最終選擇以車次作為數(shù)據(jù)劃分的標(biāo)準(zhǔn)。相同車次的數(shù)據(jù)會集在的一個服務(wù)節(jié)點上,所有的基礎(chǔ)數(shù)據(jù)以全復(fù)制的方式存在于每一個服務(wù)節(jié)點上,每個服務(wù)節(jié)點上都可以獨立運行查詢邏輯。這樣的處理方式,就可以得到一個可擴展的結(jié)構(gòu),通過增加服務(wù)節(jié)點數(shù)量,從而達到降低每個節(jié)點的車次數(shù)量,也即降低了單個節(jié)點的負荷,實現(xiàn)了查詢性能和并發(fā)性能的可控性。
在內(nèi)存數(shù)據(jù)庫中,每個表在邏輯上是以region的方式存放的,region有Partitioned、Replicated(distributed)、Distributed(not replicated)、Local(not distributed)4種類型。基礎(chǔ)數(shù)據(jù)數(shù)據(jù)量小,因此采用全復(fù)制Replicated(distributed)的策略,也就是集群中每個節(jié)點都保留一份相同數(shù)據(jù);而業(yè)務(wù)數(shù)據(jù)的數(shù)據(jù)量比較大,采用partition的方式,每個節(jié)點只保留和該節(jié)點上車次相關(guān)的數(shù)據(jù)。這種數(shù)據(jù)同步的策略確保了數(shù)據(jù)同步的高效和完整。對于一個寫操作,如果該數(shù)據(jù)是Partitioned方式的,則會復(fù)制到其它節(jié)點上;對于一個讀操作,就會被路由到某個節(jié)點上去讀取。在同一個節(jié)點上的數(shù)據(jù),每個不同的表之間是通過一種叫做Colocation的機制根據(jù)某個指定的屬性關(guān)聯(lián)起來。數(shù)據(jù)存儲方式的關(guān)系圖如3所示。

圖3 數(shù)據(jù)存儲方式關(guān)系圖
對于分布式系統(tǒng)來說,網(wǎng)絡(luò)是數(shù)據(jù)傳輸需要考慮的一個極其重要的因素,也就是將對象轉(zhuǎn)換成二進制流傳輸過去,到服務(wù)器上再將二進制流轉(zhuǎn)換成對象進行計算,稱之為序列化的損耗。對于局域網(wǎng)而言,200列車次數(shù)據(jù)的網(wǎng)絡(luò)傳輸?shù)南钠鋵嵑苄 P蛄谢瘯l(fā)生在網(wǎng)絡(luò)交互的過程中,客戶端將Java對象序列化成字節(jié)流,通過網(wǎng)絡(luò)發(fā)送到Server端,Server端將接收到的字節(jié)流再反序列化為Java對象。假設(shè)一個場景,200列車次,10個節(jié)點,通過負載平衡每個節(jié)點上分布了20個左右的車次,如果向每個節(jié)點都傳遞200列車次,序列化要做200×10,反序列化要做200×10;如果只傳遞每個節(jié)點需要的數(shù)據(jù),序列化和反序列化只需做400次,即(200+200)次,有效減少了網(wǎng)絡(luò)傳輸?shù)拇螖?shù)。
如何向每個服務(wù)器只傳遞所需要的數(shù)據(jù),系統(tǒng)的解決方案是采用client-server模式,服務(wù)端負載數(shù)據(jù)和運算邏輯,客戶端比較輕量級,更多的用來處理與外部系統(tǒng)的接口工作。客戶端還要負載向服務(wù)端發(fā)起運算請求,客戶端發(fā)起請求有3種方式:要求與某個數(shù)據(jù)相關(guān)的服務(wù)器執(zhí)行運算。這種調(diào)用方式是data-dependent的,即運算的請求在哪里執(zhí)行會與數(shù)據(jù)分布有關(guān)。按車次將余票、共用定義等數(shù)據(jù)拆分成多個獨立的計算單元,對余票查詢中最耗時的共用定義部分做預(yù)先處理,生成查詢緩存。
分布式內(nèi)存數(shù)據(jù)庫具有良好的擴展及容錯能力,集群支持彈性擴展,可通過動態(tài)增加節(jié)點應(yīng)對變化的數(shù)據(jù)訪問負載,數(shù)據(jù)庫的計算性能呈線性增長,滿足動態(tài)查詢的需要。內(nèi)存數(shù)據(jù)庫集群可配置保存1~N份數(shù)據(jù),將數(shù)據(jù)分布到不同的服務(wù)器節(jié)點上,保留的份數(shù)越多,數(shù)據(jù)丟失的可能性越小,但對系統(tǒng)帶來的多個節(jié)點線性或并行寫并保持數(shù)據(jù)的正確性就非常高。一般建議系統(tǒng)保留1份備份,和原始數(shù)據(jù)保存在不同的物理服務(wù)器上,當(dāng)集群中某個節(jié)點發(fā)生故障時易引發(fā)的數(shù)據(jù)重新分配問題,導(dǎo)致雪崩效用,系統(tǒng)采用一致性hash(Consistent hashing)算法解決了節(jié)點變化時的數(shù)據(jù)遷移問題,增強了緩存平臺的穩(wěn)定性。
自2012年底上線以來,內(nèi)存數(shù)據(jù)庫在互聯(lián)網(wǎng)售票系統(tǒng)中已經(jīng)歷一年半的時間,應(yīng)用效果明顯,相比之前在關(guān)系型數(shù)據(jù)庫中的查詢效率,響應(yīng)時間有幾十甚至幾百倍的提升。目前,使用內(nèi)存數(shù)據(jù)庫的應(yīng)用還有訂單查詢、常用聯(lián)系人查詢和實名制查詢。由于分布式內(nèi)存數(shù)據(jù)庫的引入,為客票系統(tǒng)帶來了極其深刻的影響,為在客票系統(tǒng)其它領(lǐng)域的應(yīng)用提供了實踐經(jīng)驗。當(dāng)處理的數(shù)據(jù)量增加到海量級時,由于內(nèi)存數(shù)據(jù)庫管理的內(nèi)存資源價格比較高,花費比較昂貴的內(nèi)存介質(zhì)來存儲處理海量數(shù)據(jù)代價較大,需引入海量數(shù)據(jù)處理的數(shù)據(jù)倉庫技術(shù),內(nèi)存數(shù)據(jù)庫針對活動的實時數(shù)據(jù),而數(shù)據(jù)倉庫可以針對歷史數(shù)據(jù),把內(nèi)存數(shù)據(jù)庫和分布式數(shù)據(jù)倉庫有機的結(jié)合起來,是形勢所趨,處理大數(shù)據(jù)、高并發(fā)是我們未來研究的方向。
[1]楊 艷,李 煒,王 純.內(nèi)存數(shù)據(jù)庫在高速緩存方面的應(yīng)用[J].計算機科學(xué)技術(shù),2011(12).
[2] The Hardest Problems in Data Management[EB/OL].https://www. vmware.com/files/pdf/Gemfire-Hardest-Problems-Data-Management. pdf.
[3] HighPerformance,DistributedMain-Memoryand Events Platform[EB/OL]. https://www.vmware. com/files/pdf/vmware-vfabric-gemfire-distributed-main-memory-platform-WP.