天天看點

由SQL資料庫轉換Redis的執行個體

深圳市的士查詢軟體(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中寫入資料)。