Redis中的GEO詳解
Redis GEO
Redis GEO 主要用于存儲地理位置信息,并對存儲的信息進(jìn)行操作,該功能在 Redis 3.2 版本新增。
Redis GEO 操作方法有:
- geoadd:添加地理位置的坐標(biāo)。
- geopos:獲取地理位置的坐標(biāo)。
- geodist:計算兩個位置之間的距離。
- georadius:根據(jù)用戶給定的經(jīng)緯度坐標(biāo)來獲取指定范圍內(nèi)的地理位置集合。
- georadiusbymember:根據(jù)儲存在位置集合里面的某個地點獲取指定范圍內(nèi)的地理位置集合。
- geohash:返回一個或多個位置對象的 geohash 值。
Redis 的 GEO(Geographic)模塊是用于處理地理位置信息的工具集,主要支持存儲地理位置數(shù)據(jù)、計算位置間距離、查詢指定范圍內(nèi)的位置等功能。其底層基于有序集合(ZSET)實現(xiàn),利用了 ZSET 的排序特性來管理地理位置的排序和查詢。以下從核心原理、常用命令、應(yīng)用場景及注意事項等方面詳細(xì)說明:
?一、核心原理:基于 Geohash 和 ZSET?
Redis GEO 的底層數(shù)據(jù)結(jié)構(gòu)是 ?ZSET(有序集合)?,每個地理位置的成員(member)在 ZSET 中存儲為:
- ?鍵(key)??:GEO 數(shù)據(jù)的鍵名(如
stores)。 - ?分?jǐn)?shù)(score)??:成員的 Geohash 編碼值(一個 52 位的浮點數(shù),由經(jīng)緯度轉(zhuǎn)換而來)。
- ?成員(member)??:位置的標(biāo)識(如店鋪名
shop1)。
?Geohash 算法?
Geohash 是一種將二維經(jīng)緯度(latitude, longitude)編碼為一維字符串的算法。其核心思想是通過二分法將經(jīng)緯度分別劃分為網(wǎng)格,最終生成一個由數(shù)字和字母組成的短字符串(長度越短,精度越低,覆蓋范圍越大)。例如:
- 北京天安門的經(jīng)緯度約為
(116.405285, 39.904989),對應(yīng)的 Geohash 是wx4g0s8q3jf9。 - 相鄰位置的 Geohash 字符串前綴相同,因此可通過比較前綴快速判斷位置的遠(yuǎn)近。
Redis 利用 Geohash 的這一特性,將地理位置存儲為 ZSET 的分?jǐn)?shù)(score),從而借助 ZSET 的有序性實現(xiàn)高效的距離計算和范圍查詢。
?二、常用命令詳解?
Redis GEO 提供了一系列命令,用于位置管理、距離計算和范圍查詢。以下是最核心的命令:
?1. GEOADD:添加/更新地理位置?
?語法?:GEOADD key longitude latitude member [longitude latitude member ...]
key:GEO 數(shù)據(jù)的鍵名。longitude:經(jīng)度(范圍:-180° ~ 180°,?注意順序:經(jīng)度在前,緯度在后)。latitude:緯度(范圍:-90° ~ 90°)。member:位置的唯一標(biāo)識(如店鋪名、用戶 ID)。
?功能?:向 key 中添加一個或多個地理位置(若成員已存在,則更新其經(jīng)緯度)。
?示例?:
# 添加北京天安門(經(jīng)度116.405285,緯度39.904989)和上海東方明珠(經(jīng)度121.473701,緯度31.230416) GEOADD stores 116.405285 39.904989 "天安門" 121.473701 31.230416 "東方明珠"
?返回值?:成功添加的新成員數(shù)量(重復(fù)成員不計入)。
?2. GEODIST:計算兩個位置的距離?
?語法?:GEODIST key member1 member2 [unit]
unit:距離單位,可選值:m(米,默認(rèn))、km(千米)、mi(英里)、ft(英尺)。
?功能?:計算 member1 和 member2 之間的直線距離。
?示例?:
# 計算天安門到東方明珠的距離(千米) GEODIST stores "天安門" "東方明珠" km # 輸出:約 1067.4702 km(實際計算值可能因精度略有差異)
?注意?:若任一成員不存在,返回 nil。
?3. GEORADIUS:查詢指定中心點附近的成員?
?語法?:GEORADIUS key longitude latitude radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT n] [ASC|DESC]
longitude/latitude:中心點的經(jīng)緯度。radius:搜索半徑。unit:半徑單位(同GEODIST)。WITHCOORD:返回成員的經(jīng)緯度坐標(biāo)(數(shù)組形式)。WITHDIST:返回成員到中心點的距離(浮點數(shù))。WITHHASH:返回成員的 Geohash 編碼值(整數(shù))。COUNT n:限制返回結(jié)果數(shù)量(默認(rèn)返回所有符合條件的成員)。ASC|DESC:按距離升序(ASC,默認(rèn))或降序(DESC)排序。
?功能?:以給定的經(jīng)緯度為中心,查詢半徑范圍內(nèi)的所有成員,并可選返回額外信息。
?示例?:
# 查詢天安門(116.405285, 39.904989)周圍 2 公里內(nèi)的店鋪,返回距離和坐標(biāo) GEORADIUS stores 116.405285 39.904989 2 km WITHDIST WITHCOORD
?返回值?(示例):
1) 1) "天安門" # 成員名
2) "0.0000" # 到中心點的距離(km)
3) 1) "116.405285" # 經(jīng)度
2) "39.904989" # 緯度?4. GEORADIUSBYMEMBER:以成員為中心查詢附近?
?語法?:GEORADIUSBYMEMBER key member radius unit [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT n] [ASC|DESC]
member:作為中心點的已有成員(如已存在的店鋪)。
?功能?:與 GEORADIUS 類似,但中心點由已有成員的位置決定(無需手動輸入經(jīng)緯度)。
?示例?:
# 查詢以“天安門”為中心,周圍 5 公里的店鋪 GEORADIUSBYMEMBER stores "天安門" 5 km WITHDIST
?5. GEOHASH:獲取成員的 Geohash 編碼?
?語法?:GEOHASH key member [member ...]
?功能?:返回一個或多個成員的 Geohash 字符串(基于 ZSET 的分?jǐn)?shù)轉(zhuǎn)換而來)。
?示例?:
# 獲取“天安門”的 Geohash GEOHASH stores "天安門" # 輸出:"wx4g0s8q3jf9"(實際值可能因 Redis 版本略有差異)
?應(yīng)用場景?:通過比較 Geohash 前綴快速判斷位置的相似性(前綴越長,位置越接近)。
?6. GEORADIUSBYMEMBER_RO / GEORADIUS_RO:只讀查詢(Redis 3.2.10+)??
為了支持集群模式下的只讀操作,Redis 提供了 GEORADIUSBYMEMBER_RO(基于成員)和 GEORADIUS_RO(基于經(jīng)緯度)命令,避免在集群環(huán)境中因重定向?qū)е碌男阅軉栴}。
?三、關(guān)鍵注意事項?
- ?經(jīng)緯度順序?:必須嚴(yán)格遵循
經(jīng)度在前,緯度在后(與地理常識中的“緯度優(yōu)先”不同),否則會導(dǎo)致位置錯誤。 - ?數(shù)據(jù)刪除?:GEO 數(shù)據(jù)存儲在 ZSET 中,因此刪除成員需使用
ZREM key member(而非GEODEL,Redis 未提供獨立刪除命令)。 - ?性能限制?:
- 底層是 ZSET,因此
GEOADD、GEORADIUS等操作的時間復(fù)雜度與 ZSET 一致(如GEORADIUS為 O(N + log(M)),N 是結(jié)果數(shù)量,M 是總成員數(shù))。 - 大數(shù)據(jù)量(如百萬級)下,范圍查詢可能變慢,建議結(jié)合業(yè)務(wù)場景優(yōu)化(如分區(qū)域緩存、限制
COUNT參數(shù))。
- 底層是 ZSET,因此
- ?精度問題?:Geohash 編碼長度固定為 52 位(對應(yīng) double 類型的精度),足夠覆蓋絕大多數(shù)場景(誤差約 0.5 米),但極端情況下需注意。
- ?集群支持?:Redis 集群模式下,GEO 數(shù)據(jù)會被分散存儲在不同節(jié)點(因 ZSET 的哈希槽分配),因此
GEORADIUS等跨節(jié)點查詢需通過代理節(jié)點聚合結(jié)果,可能影響性能。
?四、典型應(yīng)用場景?
?附近的人/店鋪?:如外賣 App 查詢用戶附近的餐廳,社交 App 查找附近的好友。
# 用戶當(dāng)前位置(經(jīng)度121.475,緯度31.230),查詢 3 公里內(nèi)的餐廳 GEORADIUS restaurants 121.475 31.230 3 km WITHDIST
- ?物流追蹤?:記錄包裹的實時位置,查詢某區(qū)域內(nèi)的待配送訂單。
- ?地理圍欄?:判斷移動對象(如車輛)是否進(jìn)入或離開指定區(qū)域(結(jié)合
GEORADIUS和定時任務(wù))。
?五、總結(jié)?
Redis GEO 是一個輕量級的地理位置解決方案,適合需要快速存儲和查詢位置數(shù)據(jù)的場景。其核心優(yōu)勢是利用 ZSET 的有序性實現(xiàn)了高效的距離計算和范圍查詢,但也需注意經(jīng)緯度順序、數(shù)據(jù)刪除方式和性能限制。實際使用中,需根據(jù)業(yè)務(wù)需求選擇合適的命令(如 GEORADIUS 或 GEORADIUSBYMEMBER),并結(jié)合 WITH* 參數(shù)優(yōu)化返回結(jié)果。
到此這篇關(guān)于Redis中的GEO詳解的文章就介紹到這了,更多相關(guān)Redis GEO內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Redis實現(xiàn)限流器的三種方法(小結(jié))
本文主要介紹了Redis實現(xiàn)限流器的三種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05
為何Redis使用跳表而非紅黑樹實現(xiàn)SortedSet
本篇文章主要介紹了為何Redis使用跳表而非紅黑樹實現(xiàn)SortedSet,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表使用學(xué)習(xí)
這篇文章主要為大家介紹了Redis數(shù)據(jù)結(jié)構(gòu)之跳躍表使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
Redis中LRU算法和LFU算法的區(qū)別小結(jié)
在Redis中,LRU算法和LFU算法是兩種常用的緩存淘汰算法,它們可以幫助我們優(yōu)化緩存性能,本文主要介紹了Redis中LRU算法和LFU算法的區(qū)別,感興趣的可以了解一下2023-12-12
基于redis實現(xiàn)世界杯排行榜功能項目實戰(zhàn)
前段時間,做了一個世界杯競猜積分排行榜。對世界杯64場球賽勝負(fù)平進(jìn)行猜測,猜對+1分,錯誤+0分,一人一場只能猜一次。下面通過本文給大家分享基于redis實現(xiàn)世界杯排行榜功能項目實戰(zhàn),感興趣的朋友一起看看吧2018-10-10
Redis基本數(shù)據(jù)類型Zset有序集合常用操作
這篇文章主要為大家介紹了redis基本數(shù)據(jù)類型Zset有序集合常用操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

