徐芳芳,張勁松
(1.武漢郵電科學(xué)研究院 湖北 武漢 430070;2.武漢長江通信智聯(lián)技術(shù)有限公司 湖北 武漢430070)
一種基于Redis的車輛軌跡信息的獲取方式
徐芳芳1,張勁松2
(1.武漢郵電科學(xué)研究院 湖北 武漢 430070;2.武漢長江通信智聯(lián)技術(shù)有限公司 湖北 武漢430070)
目前大多數(shù)公司主要是通過車載終端與GPS通信,獲取GPS上面車輛軌跡信息,存入數(shù)據(jù)庫。但針對運(yùn)輸企業(yè)來說,上述獲取車輛軌跡信息的做法,會造成很大的經(jīng)濟(jì)負(fù)擔(dān)。為此,文章提出了一種Java Timer和Guava cache結(jié)合的方式從Redis數(shù)據(jù)庫上獲取運(yùn)輸企業(yè)車輛的軌跡信息,存儲到本地?cái)?shù)據(jù)庫,便于運(yùn)輸企業(yè)了解車輛信息,查詢車輛歷史軌跡。
Guava cache;Redis;Java定時(shí)器
隨著我國經(jīng)濟(jì)的快速發(fā)展,車輛逐年增加,同時(shí)所造成的交通事故也在逐年上升,車輛監(jiān)管越來越受人們的重視。目前,車輛管理中,獲取車輛歷史軌跡信息的方式有兩種:一種是通過車載終端與GPS通信[1],在GPS接收端獲取車輛軌跡信息,傳回控制中心后存儲到本地?cái)?shù)據(jù)庫;另一種是通過與上述這種有條件的企業(yè)合作,動態(tài)獲取他們得到的車輛軌跡信息。
對于不是專門做GPS與車載終端通信的企業(yè)來說,一般會選取第二種方式。選用第二種方式時(shí),有多種實(shí)現(xiàn)方法。如當(dāng)需要車輛軌跡數(shù)據(jù)時(shí),我們可以調(diào)用對方發(fā)送的接口直接獲取數(shù)據(jù);也可以主動去對方那里取數(shù)據(jù),存到本地的數(shù)據(jù)庫,當(dāng)我們需要數(shù)據(jù)時(shí),直接從本地?cái)?shù)據(jù)庫取數(shù)據(jù)。選用從對方發(fā)送的接口直接獲取數(shù)據(jù)的方法,一般會受到異網(wǎng)段影響,造成較長時(shí)延,如果網(wǎng)絡(luò)信號不好,可能造成信息丟失。而選用主動去對方那里取數(shù)據(jù),存到本地的數(shù)據(jù)庫時(shí),我們需要考慮如何從對方那里直接取數(shù)據(jù)??梢允褂弥虚g數(shù)據(jù)庫做橋梁。對方往里面存數(shù)據(jù),我們不斷取,然后存入本地?cái)?shù)據(jù)庫。其中比較好的可以做中間數(shù)據(jù)庫的有coherence(可以實(shí)現(xiàn)java應(yīng)用對象和數(shù)據(jù)的共享)和Redis,但使用coherence需要付費(fèi)。
由上可知,采用第二種方式獲取車輛軌跡信息大多會受到異網(wǎng)段傳輸時(shí)間過長,信息丟失,成本過高等影響。為了解決這種問題,本文在第二種方式的基礎(chǔ)上提出一種基于Redis的車輛軌跡信息的獲取的方式。
Guava Cache[2-5]是一個(gè)全內(nèi)存的本地緩存。它提供了一種把數(shù)據(jù)(key-value對)緩存到本地Java虛擬機(jī)(JVM)內(nèi)存中的機(jī)制,適用于很少會改動的數(shù)據(jù)。Guava Cache為了限制內(nèi)存占用,設(shè)有自動回收元素。
Redis是一個(gè)支持網(wǎng)絡(luò)交互的、可基于內(nèi)存也可持久化的Key-Value數(shù)據(jù)庫。和Memcached類似,它擁有豐富的數(shù)據(jù)類型,支持存儲的value類型相對更多,包括 string、list、set、zset(sorted set--有序集合)和hash(哈希類型)。
文中采取Redis與Guava Cache結(jié)合的方式,獲取車輛軌跡信息[6-7],在提高應(yīng)用性能的同時(shí),大大提高響應(yīng)速度。
如圖1,先從Redis上獲取數(shù)據(jù),在SSM(Spring+springMVC+mybatis)框架[15]上得到運(yùn)輸車輛軌跡信息,經(jīng)過處理后,批量存入數(shù)據(jù)庫。當(dāng)需要查看mysql中存入的車輛歷史軌跡信息對車輛數(shù)據(jù)進(jìn)行分析時(shí),由前臺頁面發(fā)出請求[13-14]后,從mysql中取出數(shù)據(jù)處理,展示在引入的地圖[8-12]上。
圖1 業(yè)務(wù)流程圖
1)mysql數(shù)據(jù)表的設(shè)計(jì)
根據(jù)需求設(shè)計(jì)Mysql數(shù)據(jù)表1,定義表名為gpsinfo,對應(yīng)實(shí)體類型為GPSInfo。
表1 車輛信息表(gpsinfo)
其中,lat表示用GPS定位的車輛緯度,elat表示為項(xiàng)目所需經(jīng)過糾偏后的緯度。gTime用GPS定位后采集到此車輛信息的時(shí)間。
2)Redis中結(jié)構(gòu)的設(shè)計(jì)
由圖1可知,從Redis數(shù)據(jù)庫上取數(shù)據(jù)后,要存入Mysql對應(yīng)字段的數(shù)據(jù)表,Redis中hash是最接近關(guān)系數(shù)據(jù)庫結(jié)構(gòu)的數(shù)據(jù)類型,可以將數(shù)據(jù)庫一條記錄或程序中一個(gè)對象轉(zhuǎn)換成hashmap存放在redis中。如表2 Redis數(shù)據(jù)庫上數(shù)據(jù)結(jié)構(gòu)的設(shè)計(jì),表字段基本與mysql數(shù)據(jù)表對應(yīng)。
表2 Redis中hash數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)key-value(hash)
圖2 車輛信息存儲流程圖
如圖2,為了使mysql數(shù)據(jù)庫的數(shù)據(jù)與Redis數(shù)據(jù)庫中的數(shù)據(jù)盡量達(dá)到同步,需要每個(gè)固定的一段時(shí)間去Redis數(shù)據(jù)庫中的獲取數(shù)據(jù)存入Mysql數(shù)據(jù)庫,盡量達(dá)到二者數(shù)據(jù)的同步。這樣的需求可以做一個(gè)線程,線程中做一個(gè)死循環(huán),循環(huán)中執(zhí)行的這個(gè)任務(wù),每執(zhí)行完一次讓線程睡眠一段時(shí)間,這樣就可以達(dá)到這個(gè)需求。最簡單最便捷的方式是使用Java為我們提供的計(jì)時(shí)器的工具類,即Timer和TimerTask。Timer是一個(gè)普通的類,其中有幾個(gè)重要的方法;而TimerTask則是一個(gè)抽象類,其中有一個(gè)抽象方法run(),通過run方法開啟線程。我們使用Timer創(chuàng)建一個(gè)對象,然后使用這對象的schedule方法來完成這種定時(shí)操作。這種通過開啟一個(gè)時(shí)間間隔線程,實(shí)時(shí)獲取redis上車輛軌跡信息,基本上可以實(shí)現(xiàn)本地?cái)?shù)據(jù)庫數(shù)據(jù)與redis上數(shù)據(jù)的同步。具體步驟如下:
1)由圖2可知,首先當(dāng)程序開始的時(shí)候調(diào)用建立java Timer定時(shí)器,使用schedul()方法設(shè)定程序開始30s后調(diào)用線程中run()方法執(zhí)行從redis上取數(shù)據(jù)并處理后存入數(shù)據(jù)庫,然后每30秒執(zhí)行一次,定時(shí)刷新,從而使mysqls的數(shù)據(jù),與Redis的數(shù)據(jù)盡量達(dá)到同步。
2)啟動定時(shí)器Timer后,開始在線程中處理數(shù)據(jù)。 使用 jedis.hgetAll ("gpsInfos")(jedis為 redis的java客戶端),每次取出所有運(yùn)輸企業(yè)的車輛信息放在Map中,同時(shí)設(shè)置一個(gè)list集合 (數(shù)據(jù)類型為GPSInfo)。采用循環(huán)將Map中車輛信息分條取出,將每條數(shù)據(jù)放入與數(shù)據(jù)表對應(yīng)的實(shí)體類gpsInfo(類型為 GPSInfo)中,設(shè)置獲取時(shí)間 gpsInfo.setoTime(new Date()),設(shè)置車輛狀態(tài) gpsInfo.setStatus("在線"),同時(shí)采用糾偏工具將獲取的GPS經(jīng)緯度轉(zhuǎn)換成對應(yīng)地圖的經(jīng)緯度,根據(jù)經(jīng)緯度和地址查詢工具設(shè)置車輛的具體位置,將設(shè)置好的實(shí)體類gpsInfo放在對應(yīng)list集合中,同時(shí)記錄日志,方便后期查詢。當(dāng)循環(huán)結(jié)束后,判斷l(xiāng)ist集合是否存在值,若有值將list中數(shù)據(jù)批量插入數(shù)據(jù)庫。
3)上面2)是一種理想獲取車輛歷史軌跡的狀態(tài),實(shí)際上這里有兩個(gè)問題,其一redis是一個(gè)內(nèi)存數(shù)據(jù)庫,對于程序來說,內(nèi)存是有限且非常重要的,redis本身并沒有自動回收機(jī)制,不斷的向redis存數(shù)據(jù)會造成數(shù)據(jù)庫的崩潰。其二從redis獲取數(shù)據(jù)時(shí),并不知道車輛是在線狀態(tài)還是離線狀態(tài),僅當(dāng)我們獲取到車輛軌跡信息時(shí),我們能判斷此GPS采集時(shí)間車輛的狀態(tài)為在線,如果沒有獲取到相關(guān)車輛軌跡信息,我們怎樣設(shè)置車輛為離線呢?為了解決以上兩種問題,我們引入本地緩存Guava cache。
定義一個(gè)全局變量private LoadingCache<String,GPSInfo> gpsInfosGuaveCache。程序啟動時(shí)自動加載的一個(gè) LoadingCache類型的函數(shù)gpsInfosGuaveCache()并賦值給全局變量gpsInfosGuaveCache,在2)循環(huán)中設(shè)置好實(shí)體類gpsInfo之后,按照Key-value數(shù)據(jù)類型將對應(yīng)車輛信 息按車牌號 存入 Guavacache中 :gpsInfosGuaveCache.put (carNum,gpsInfo)。 由 于Guava cache是本地緩存,為了避免它占用過多的內(nèi)存,本文使用它自帶的回收元素回收內(nèi)存。在函數(shù)gpsInfosGuaveCache()中,先設(shè)置基于大小移除的方法 :CacheBuilder.newBuilder().maximumSize(50000)當(dāng)存入全局變量gpsInfosGuaveCache的key值數(shù)量接近于50000時(shí),Guave Cache就會把不常用的鍵值對從cache中移除,同時(shí)配合基于時(shí)間的移除:expireAfterWrite (30,TimeUnit.SECONDS),當(dāng)超過30s時(shí),對應(yīng)車輛key值沒有數(shù)據(jù)更新,移除此key值。在移除數(shù)據(jù)時(shí)設(shè)置一個(gè)Guava cache自帶的監(jiān)聽器,當(dāng)監(jiān)聽到key值移除時(shí),刪除redis數(shù)據(jù)庫上對應(yīng)的此鍵值:jedis.del("gpsInfos",gpsInfo.getKey()),并在監(jiān)聽函數(shù)中設(shè)置車輛離線狀態(tài),將設(shè)好的數(shù)據(jù)更新到mysql中。這樣使用Guava cache即對redis進(jìn)行了優(yōu)化,又設(shè)置了接收車輛的相關(guān)數(shù)據(jù)。
如圖3所示:(下面車牌號為修改過的測試用的車牌號)。
為了驗(yàn)證車輛歷史軌跡是否正確,本文采用百
圖3 車輛軌跡回放
度地圖展示數(shù)據(jù)。為了精確的找到車輛在一段時(shí)間 的歷史軌跡。需要利用ajax技術(shù)的將車牌號、車牌顏色、車輛運(yùn)行的時(shí)間段發(fā)送到后臺,進(jìn)行請求,請求成功后,判斷是否有數(shù)據(jù)返回,若沒有數(shù)據(jù)給出"沒有查詢到相關(guān)車輛信息!"提示信息,若有數(shù)據(jù),將查詢到的車輛軌跡信息,通過循環(huán)的以new BMap.Point(lon,lat)方式放在 pointArray[i]數(shù)組中,使用Polyline函數(shù),將數(shù)組中的車輛經(jīng)緯度,按照先后順序連接起來。最后設(shè)置一個(gè)功能函數(shù),便于查看車輛在地圖上的運(yùn)行軌跡。
文章介紹了一種基于Redis的車輛軌跡信息的獲取技術(shù),在優(yōu)化性能的同時(shí)提高了響應(yīng)速度,同時(shí)引入百度地圖API觀察獲取到的數(shù)據(jù),直觀、簡單、方便運(yùn)輸企業(yè)查看運(yùn)輸車輛歷史軌跡,了解分析車輛在運(yùn)行中的信息。
[1]毛志宇,張正,曹玉志.基于RFID與GPS的巖土運(yùn)輸車輛管理系統(tǒng)的研究與開發(fā) [J].信息化建設(shè),2016(3):353.
[2]王心妍.Memcached和Redis在高速緩存方面的應(yīng)用[J].無線互聯(lián)科技,2012(9):8-9.
[3]唐誠.Redis數(shù)據(jù)庫在微博系統(tǒng)中的實(shí)踐[J].廈門城市職業(yè)學(xué)院學(xué)報(bào),2012,14(3):55-59.
[4]曾超宇,李金香.Redis在高速緩存系統(tǒng)中的應(yīng)用[J].微型機(jī)與應(yīng)用,2013(12):11-13.
[5]張景云.基于Redis的矢量數(shù)據(jù)組織研究[D].南京:南京師范大學(xué),2013.
[6]范建永,龍明,熊偉.基于HBase的矢量空間數(shù)據(jù)分布式存儲研究 [J].地理與地理信息科學(xué),2012,28(5):39-42.
[7]唐建智.基于云計(jì)算的海量空間信息存儲與計(jì)算研究 [D].北京:中國科學(xué)院遙感應(yīng)用研究所,2012.
[8]邵應(yīng)泉.基于百度地圖API實(shí)現(xiàn)自動氣象站點(diǎn)信息顯示[J].電腦知識與技術(shù),2013(27):6062-6063.
[9]沈娣麗,上官同英,孟雅俊,等.Zigbee和百度地圖API在農(nóng)田信息采集系統(tǒng)中的應(yīng)用[J].中國農(nóng)機(jī)化,2012(4):184-188.
[10]王紅崧,周海晏.基于百度地圖API的旅游地理信息系統(tǒng)開發(fā)[J].現(xiàn)代計(jì)算機(jī)(專業(yè)版),2012(23):60-63.
[11]岳泉.基于谷歌地圖的車輛遠(yuǎn)程監(jiān)控系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)[D].武漢:武漢理工大學(xué),2013.
[12](美)澤卡斯 (Zakas,N.C.),著.JavaScript高級程序設(shè)計(jì)[M].北京:人民郵電出版社,2012.
[13]林國,李偉超.基于AJAX的富互聯(lián)網(wǎng)應(yīng)用框架研究[J].實(shí)驗(yàn)室研究與探索,2012,31(7):92-97.
[14]周楊.AJAX應(yīng)用的典型設(shè)計(jì)模式[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2011(1):128-132.
[15]薛峰,梁鋒,徐書勛,等.基于Spring MVC框架的Web研究與應(yīng)用[J].合肥工業(yè)大學(xué)學(xué)報(bào):自然科學(xué)版,2012(3):337-340.
A method of obtaining vehicle track information based on Redis
XU Fang-fang1,ZHANG Jin-song2
(1.Wuhan Research Institute of Posts and Telecommunications,Wuhan 430070,China;2.Wuhan YCIG iLink Technology Company Limited,Wuhan 430070,China)
Most companies get in the GPS[1]vehicle trace information mainly through the vehicle terminal and GPS communicated,to store in database.For transportation enterprises,the above method to the acquisition of vehicle trace information,will generate a large economic burden.Therefore,this paper proposes a combination way of Java Timer and Guava cache to get the vehicle trace information of transport enterprise from Redis[2-5]database.The aim to make transport enterprise get vehicle trace information and query vehicle trajectory[6].
Guava cache; Redis; Java timer
TN02
A
1674-6236(2017)17-0054-04
2016-07-18稿件編號:201607131
徐芳芳(1991—),女,湖北孝感人,碩士研究生。研究方向:通信與信息工程、軟件設(shè)計(jì)。