Redis計算地理位置距離-GeoHash


最近在公司接收到一個需求,用戶定位后,返回用戶所在位置附近的人。

第一版

  通過埋點或者登陸定位時的經緯度,存到mysql數據庫中。通過sql查詢返回對應的附近人的數據。

遇到了問題如下:

  1.用戶經緯度表更新太過頻繁。導致mysql連接資源長期占用。

  2.通過sql計算出附近的人,損耗mysql運算資源,雖然sql能在1秒內返回。

  3.測試反饋的切換定位后,暫無數據。新用戶注冊,暫無數據

 

因為發現以上問題,我們調整了我們技術的方案:

Redis GEO

Redis 在 3.2 版本以后增加了地理位置 GEO 模塊。

地圖元素的位置數據使用二維的經緯度表示,經度范圍 (-180, 180],緯度范圍 (-90, 90],緯度正負以赤道為界,北正南負,經度正負以本初子午線 (英國格林尼治天文台) 為 界,東正西負。比如廣州的辦公室經緯度(113.380627,23.132107)都是正數,因為中國位於東北半球。

當兩個元素的距離不是很遠時,可以直接使用勾股定理就能算得元素之間的距離。我們平時使用的「附近的人」的功能,元素距離都不是很大,勾股定理算距離足矣。不過需要注意的是,經緯度坐標的密度不一樣 (經度總共 360 度,緯度總共 180 度)

 

有效經度為-180 ~ 180度。
有效緯度為-85.05112878 ~ 85.05112878度。

 

勾股定律計算平方差時之后再求和時,需要按一定的系數比加權求和。

現在,如果要計算「附近的人」,也就是給定一個元素的坐標,然后計算這個坐標附近的其它元素,按照距離進行排序,該如何下手?

如果現在元素的經緯度坐標使用關系數據庫 (元素 id, 經度 x, 緯度 y) 存儲,你該如何計算?

GeoHash 算法

Redis 的 GEO 特性將在 Redis 3.2 版本釋出, 這個功能可以將用戶給定的地理位置信息儲存起來, 並對這些信息進行操作   
將指定的地理空間項目(緯度,經度,名稱)添加到指定的鍵。數據作為排序集存儲到密鑰中,使得可以使用GEORADIUS或GEORADIUSBYMEMBER命令使用半徑查詢稍后檢索項目。

注意:沒有GEODEL命令,可以使用ZREM來刪除元素。地理索引結構只是一個排序集。

 

Redis GEO實現主要包含了以下兩項技術:
1、使用geohash保存地理位置的坐標。
2、使用有序集合(zset)保存地理位置的集合。

 

Redis GEO 操作方法

  • geoadd:添加地理位置的坐標。
  • geopos:獲取地理位置的坐標。
  • geodist:計算兩個位置之間的距離。
  • georadius:根據用戶給定的經緯度坐標來獲取指定范圍內的地理位置集合。
  • georadiusbymember:根據儲存在位置集合里面的某個地點獲取指定范圍內的地理位置集合。
  • geohash:返回一個或多個位置對象的 geohash 值。

geoadd

geoadd 用於存儲指定的地理空間位置,可以將一個或多個經度(longitude)、緯度(latitude)、位置名稱(member)添加到指定的 key 中。

geoadd 語法格式如下:

GEOADD key longitude latitude member [longitude latitude member ...]
geoadd dg:erp:chart:total:user_geo 116.48105 39.996794 38888888

以下我將用戶的經緯度轉換成Redis Geo

 

 批量處理如下:

 

 

 

 

georadius 、georadiusbymember

georadius 以給定的經緯度為中心, 返回鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素。

georadiusbymember 和 GEORADIUS 命令一樣, 都可以找出位於指定范圍內的元素, 但是 georadiusbymember 的中心點是由給定的位置元素決定的, 而不是使用經度和緯度來決定中心點。

georadius 與 georadiusbymember 語法格式如下:

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]

參數說明:

    • m :米,默認單位。
    • km :千米。
    • mi :英里。
    • ft :英尺。
    • WITHDIST: 在返回位置元素的同時, 將位置元素與中心之間的距離也一並返回。
    • WITHCOORD: 將位置元素的經度和維度也一並返回。
    • WITHHASH: 以 52 位有符號整數的形式, 返回位置元素經過原始 geohash 編碼的有序集合分值。 這個選項主要用於底層應用或者調試, 實際中的作用並不大。
    • COUNT 限定返回的記錄數。
    • ASC: 查找結果根據距離從近到遠排序。
    • DESC: 查找結果根據從遠到近排序。

 

georadiusbymember 實例:

實例

 

 

這樣就查出這個用戶附近100公里的用戶了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM