redis GEO 類型原理及命令詳解

目錄

前言

一、GeoHash 的編碼方法

二、Redis 操作GEO類型


前言

我們有一個需求是用戶搜索附近的店鋪,就是所謂的位置信息服務(Location-Based Service,LBS)的應用。這樣的相關服務我們每天都在接觸,用滴滴打車,中午去美團訂外賣等等。當我們用這些服務方便我們的生活的時候,大家有沒有想過是怎么實現的。目前市場上很多軟件比如Es,Redis 都提供了類似的功能,他們底層都是用的GeoHash 編碼,只不過底層的數據結構不同。今天主要講的是Redis 的 Geo 如何實現這個功能

一、GeoHash 的編碼方法

Redis 常用的數據類型有String(字符串)、List(列表)、Hash(哈希)、Set(集合)和 Sorted Set(有序集合)。位置信息存儲一定是key,value,value 就是經緯度。用List、Hash,Set 去存儲,沒有辦法去排序,當然也是不可以的。最接近的數據結構是Sorted Set,可以根據score 排序同時也滿足范圍獲取。又有一個問題是 score 是 float 類型的,經緯度不是的,好像也不可以,能不能用一種編碼把經緯度變成float 類型的,這種編碼就是GeoHash。

為了能高效地對經緯度進行比較,Redis 采用了業界廣泛使用的 GeoHash 編碼方法,這個方法的基本原理就是“二分區間,區間編碼”。當我們用GeoHash編碼時,我們要先對經度和維度分別編碼,然后再把經緯度各自的編碼組合成一個最終編碼。

我們看看經緯度的編碼過程。

對于一個定理信息來說,它的經度范圍是[-180,180],緯度范圍是[-90,90]。GeoHash編碼會把經,緯度做N次二分區操作,其中N是自定義的。

先拿經度來說,范圍是[-180,180]會被分成兩個子區間:【-180,0)和【0,180】(我稱為左右分區)。此時我們要看下經度是落在左右哪個分區上,落在左分區用0表示,又分區用1 表示。第二次在把落在的分區又分成左右兩個分布,在看下經度是落在哪個分區上,落在左分區用0表示,又分區用1 表示。依次類推,只要分成了N份結束了。最終得到的是N bit 的位數,例如10111 這樣的數據。

緯度也是同樣的,只不過,緯度的范圍是【-90,90】。每次也是平均分成左右兩個分區,落在左分區用0表示,又分區用1 表示。最終得到的也是N bit 的位數,例如10110 這樣的數據。

最終得倒的是2個N bit 的位數,最終進行組合。組合規則是第 0 位是經度的第 0 位 1,第 1 位是緯度的第 0 位 1,第 2 位是經度的第 1 位 1,第 3 位是緯度的第 1 位 0。

下面我們會舉一個例子,來闡述算法具體的實現:經度值 116.37,緯度值 39.86, N是5。

經度分區過程 116.37:

分區次數左分區右分區經度116.37所在的分區編碼
1【-180,0)[0,180][0,180]1
2[0,90)[90,180][90,180]1
3[90,135)[135,180][90,135)0
4[90,112.5)[112.5,135][112.5,135]1
5[112.5,123.75)[123.75,135][112.5,123.75)0

最終編碼是11010

緯度的編碼過程是 39.86

分區次數左分區右分區緯度 39.86所在的分區編碼
1【-90,0)【0,90]【0,90]1
2[0,45)[45,90][45,90]0
3[0,22.5)[22.5,45][22.5,45]1
4[22.5,33.75)[33.75,45][33.75,45]1
5[33.75,39.375)[39.375.45][39.375,45]1

最終編碼是 10111

GeoHash最終編碼是,回顧編碼規則:組合規則是第 0 位是經度的第 0 位 1,第 1 位是緯度的第 0 位 1,第 2 位是經度的第 1 位 1,第 3 位是緯度的第 1 位 0

經度編碼11010
奇偶數(位數)0123456789
緯度編碼10111

經度編碼和緯度編碼合并:一共是10位數, 1110011101,位數不要錯了,這個最終就是 Sorted Set 的 sort 值了。

當然,使用 GeoHash 編碼后,我們相當于把整個地理空間劃分成了一個個方格,每個方格對應了 GeoHash 中的一個分區。舉個例子。我們把經度區間[-180,180]做一次二分區,把緯度區間[-90,90]做一次二分區,就會得到 4 個分區。我們來看下它們的經度和緯度范圍以及對應的 GeoHash 組合編碼。分區一:[-180,0) 和[-90,0),編碼 00;分區二:[-180,0) 和[0,90],編碼 01;分區三:[0,180]和[-90,0),編碼 10;分區四:[0,180]和[0,90],編碼 11。

這 4 個分區對應了 4 個方格,每個方格覆蓋了一定范圍內的經緯度值,分區越多,每個方格能覆蓋到的地理空間就越小,也就越精準。我們把所有方格的編碼值映射到一維空間時,相鄰方格的 GeoHash 編碼值基本也是接近的,如下圖所示:

所以,我們使用 Sorted Set 范圍查詢得到的相近編碼值,在實際的地理空間上,也是相鄰的方格,這就可以實現 LBS 應用“搜索附近的人或物”的功能了。不過,我要提醒你一句,有的編碼值雖然在大小上接近,但實際對應的方格卻距離比較遠。例如,我們用 4 位來做 GeoHash 編碼,把經度區間[-180,180]和緯度區間[-90,90]各分成了 4 個分區,一共 16 個分區,對應了 16 個方格。編碼值為 0111 和 1000 的兩個方格就離得比較遠,如下圖所示:

二、Redis 操作GEO類型

在使用 GEO 類型時,我們經常會用到兩個命令,分別是 GEOADD 和 GEORADIUS。

GEOADD 命令:用于把一組經緯度信息和相對應的一個 ID 記錄到 GEO 類型集合中;

GEORADIUS 命令:會根據輸入的經緯度位置,查找以這個經緯度為中心的一定范圍內的其他元素。當然,我們可以自己定義這個范圍。

操作如下:

GEOADD 如果member 沒有就增加,有就是修改,用 GEOPOS cars:locations 33 可以看到每個member 具體的經緯度

GEORADIUS 可以根據坐標找到相應的member。命令的詳解可以看官網文檔 GEORADIUS | Redis

非常感謝 蔣德鈞的《Redis 核心技術與實戰》以及 redis 官網提供了非常寶貴的資料

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697806.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697806.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697806.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用ENV工具編譯RT-Thread【詳細過程講解:從下載到編譯、設置】

感興趣的寶子,可以點個贊收藏,便于后期有需要的時候能快速找到~~ ENV編譯編譯RT-Thread工程的詳細過程講解 ENV簡介ENV的下載設置ENV使用ENV編譯RT-Thread工程◆ 打開ENV◆ 輸入打包命令◆ 查看并打開工程文件◆ 使用menuconfig 對生成項目的RT-Thread配…

【Git企業實戰開發】Git常用開發流操作總結

【Git企業實戰開發】Git常用開發流操作總結 大家好 我是寸鐵👊 總結了一篇Git常用開發流操作總結的文章? 喜歡的小伙伴可以點點關注 💝 現在剛做項目的伙伴,可能你之前學過git,但是一實戰發現不熟悉 沒關系,看寸鐵這篇…

fastadmin引用 redis 方法2

頁面上引用 use \think\cache\driver\Redis; $redis new Redis();$redis->set(key, value);// 獲取鍵值對的值$value $redis->get(key);echo $value;如果執行后出現 不支持redis, 檢查系統是否開啟 redis 擴展。 如果是小皮系統。 項目-管理-php擴展&#x…

js實現頂部導航欄隨著滾動條下滑顯示背景顏色,上劃到頂部背景顏色消失

有個項目需求,如題目所示。這種展示方式讓首頁的內容可以完美展示而不受到導航欄的干擾,等下滑查看內容時導航欄的背景顏色再顯示出來。下面是一個案例: 導航欄隨滑動條下滑顯示 再下面是我的成果視頻展示: 導航條隨滾動條下滑顯示…

vue怎么實現pdf、excel、word文件離線預覽?2024年2月份最新測試(可行方案和詳細代碼在文章末尾)

Vue.js 中實現Office文檔(Word、Excel、PPT)和PDF文件的預覽,通常會借助于第三方庫或服務。 1. Office文檔在線預覽 使用WPS Web Office SDK WPS提供了Web Office服務,可以將文檔轉換為網頁格式進行在線預覽。首先在項目中引入并注冊WPS提供的SDK,然后在Vue組件中配置一個…

一、平滑發布與灰度發布

目錄 一、平滑發布與灰度發布 一、平滑發布與灰度發布 什么叫平滑:在發布的過程中不影響用戶的使用,系統不會因發布而暫停對外服務,不會造成用戶短暫性無法訪問; 什么叫灰度:發布后讓部分用戶使用新版本,…

【Linux】普通用戶sudo失敗怎么辦

普通用戶,sudo失敗報錯怎么辦 問題分析如何解決成功 問題分析 新建的普通用戶sudo失敗 sudo提權,是以root的身份執行命令。 當我們用sudo提升權限的時候,這里有個問題,Linux會提示我們輸入當前普通用戶的密碼——這就有點不好。…

【Linux取經路】基礎I/O之重定向的實現原理

文章目錄 一、再來理解重定向1.1 輸出重定向效果演示1.2 重定向的原理1.3 dup21.4 輸入重定向效果演示1.5 輸入重定向代碼實現 二、再來理解標準輸出和標準錯誤2.1 同時對標準輸出和標準錯誤進行重定向2.2 將標準輸出和標準錯誤重定向到同一個文件 三、再看一切皆文件四、結語 …

Elasticsearch從入門到精通-01認識Elasticsearch

Elasticsearch從入門到精通-01認識Elasticsearch 👏作者簡介:大家好,我是程序員行走的魚 🍂博主從本篇正式開始ES學習,希望小伙伴可以一起探討 📖 本篇主要介紹和大家一塊簡單認識下ES并了解ES中的主要角色…

游戲身份證實名認證接口-C#語言代碼示例

為助力解決網絡游戲中的未成年人過度沉迷、不規范行為以及個人信息安全等問題,翔云API提供了高效、安全的游戲身份證實名認證接口。該接口的目標是通過核驗身份證三要素的方式實現用戶身份的準確驗證,確保玩家真實身份與游戲賬號對應,并有效執…

順序表增刪改查(c語言)

main函數&#xff1a; #include <stdio.h>#include "./seq.h"int main(int argc, const char *argv[]){SeqList* list create_seqList();insert_seqList(list,10);insert_seqList(list,100);insert_seqList(list,12);insert_seqList(list,23);show_seqList(l…

SpringBoot集成Mqtt發送消息

1. MQTT簡介 MQTT是一種物聯網消息協議&#xff0c;為Message Queuing Telemetry Transport的縮寫&#xff0c;即消息隊列傳輸探測&#xff0c;協議基于發布訂閱模式進行通信&#xff0c;有開銷低、帶寬小、輕量的特點&#xff0c;通常應用在物聯網數據采集、移動應用、智能硬…

H5獲取手機相機或相冊圖片兩種方式-Android通過webview傳遞多張照片給H5

需求目的&#xff1a; 手機機通過webView展示H5網頁&#xff0c;在特殊場景下&#xff0c;需要使用相機拍照或者從相冊獲取照片&#xff0c;上傳后臺。 完整流程效果&#xff1a; 如下圖 一、H5界面樣例代碼 使用html文件格式&#xff0c;文件直接打開就可以展示布局&#…

BGP-OSPF防環機制

一、BGP 防環機制 1、AS內部防環&#xff1a;通過IBGP水平分割&#xff0c;IBGP水平分割的基本思想是 不把從IBGP鄰居學到的路由信息發送給其他IBGP鄰居&#xff1b; 2、AS間的防環&#xff1a;通過屬性AS-PATH來實現&#xff0c; 基本思想是&#xff1a;記錄經過的路徑&…

【每日一題】2583. 二叉樹中的第 K 大層和-2024.2.23

題目: 2583. 二叉樹中的第 K 大層和 給你一棵二叉樹的根節點 root 和一個正整數 k 。 樹中的 層和 是指 同一層 上節點值的總和。 返回樹中第 k 大的層和(不一定不同)。如果樹少于 k 層,則返回 -1 。 注意,如果兩個節點與根節點的距離相同,則認為它們在同一層。 示…

canvas水波紋效果,jquery鼠標水波紋插件

canvas水波紋效果&#xff0c;jquery鼠標水波紋插件 效果展示 jQuery水波紋效果&#xff0c;canvas水波紋插件 HTML代碼片段 <div class"scroll04wrap"><h3>發展歷程</h3><div class"scroll04"><p>不要回頭&#xff0c;一…

前端工程Bem架構及其封裝

文章目錄 簡介語法在vue3項目中引用sass創建bem.scss文件修改vite.config.tsvue文件中使用結果 這是我學習記錄的筆記&#xff0c;如有不正&#xff0c;歡迎補充 簡介 首先認識一下什么是bem架構&#xff1f;BEM的意思就是塊&#xff08;block&#xff09;、元素&#xff08;e…

【DDD】學習筆記-發布者—訂閱者模式

在領域設計模型中引入了領域事件&#xff0c;并不意味著就采用了領域事件建模范式&#xff0c;此時的領域事件僅僅作為一種架構或設計模式而已&#xff0c;屬于領域設計模型的設計要素。在領域設計建模階段&#xff0c;如何選擇和設計領域事件&#xff0c;存在不同的模式&#…

nginx-ingress-controller組件中Nginx的版本升級

參考鏈接&#xff1a;https://blog.csdn.net/qq_22824481/article/details/133761302 https://blog.csdn.net/mengfanshaoxia/article/details/127155020 https://blog.csdn.net/weixin_39961559/article/details/87935873 概要 業務區k…

JAVAEE初階 JVM(一)

JVM的熱門話題 一. JVM中的內存區域劃分1.經典筆試題. 二. JVM的類加載機制 一. JVM中的內存區域劃分 1.經典筆試題. 二. JVM的類加載機制