深圳市的士查詢軟件(gogo查的后臺服務器)
1、現有版本總結
熱點區域信息是根據過去半年的歷史數據計算得出,短期內屬于固定信息,不用做任何改變。現在所用的gogo查的版本中,查詢熱點區域所用的API,是先在servlet中計算出用戶選擇區域周圍的區域ID,構造出
SQL查詢語句,最后從postgresql中讀取所需的熱點區域信息。
SQL語句如下:
Select regionno from sztable.hotregioninfo where dayofweek=’”+ dayofweek+”’ and hour = ‘”+hour+”’ and regionno in “+sBuilder.toString()+”order by amount desc limit ”+return_region_num+”; |
具體操作可在XGO API程序中看到。
數據庫中所存的熱點信息,共有800多W條,在SQL查詢中需要耗時至少2~3秒,查詢效率低下,導致用戶體驗下降。故在此采用Redis解決查詢較慢的問題。
2、熱點區域postgresql轉Redis
Redis數據庫設計:結合原有數據以及查詢需求(需要求周邊區域中前N大),采用Redis中有序集合的數據結構。用“星期:時間”字符串作為key,共有(7*24=168)個;用相應區域號及在該區域成功打車的次數作為value中的memeber和score。
將熱點區域信息從postgresql中導入redis:程序代碼在PostToRedis中,ToRedis為程序入口。直接運行即可將數據從postgresql中以1中設計格式導入redis。注:由于讀取數據量較大,可能會導致計算機為
java分配的內存空間不夠用,應在運行前進行相應設置(Xms)。
3、查詢過程
模擬用戶查詢操作,采用的模式為:用戶提交坐標點及第幾天、時間,在serrvlet中計算出坐標點所在區域號,根據半徑計算出要查詢的范圍內所有的區域ID,并寫入到Redis有序集合T1(臨時,只對本次查詢有效,查詢結束之后即將該集合銷毀)中,然后將T1與之前已經存好的168個key、value中相應時間段的集合求交集。Eg:現在為周三,上午十點鐘,就與key為3:10的集合求交集,交集結果按照降序排列,將前N區域號提取出來,并根據將區域號轉為坐標的算法得到輸出結果。
需要注意的是,每次查詢在redis中新增加的key,在本次查詢結束之后都要進行銷毀或者設置存活時間,使系統能夠較快的釋放掉該key所占用的內存空間,減少累加查詢導致過多無效key存在,一定程度上緩解服務器壓力。
熱點區域查詢的API,在程序包HotRegionRedis中。
4、存在弊端
每次查詢都要向redis中寫入新的數據集合,雖然redis聲稱每秒中可支持10W次寫入操作,但在既有寫又有讀、高并發的情況下會導致Redis性能下降。不過在相當一段時間內,這種模式可以滿足需求。
5、建議
建議之后將熱點區域中分區方法改進,結合Geohash算法。(由于要求前N大,暫時無法避免查詢操作時向Redis中寫入數據)。