日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

【Redis】数据结构的应用——GEO 【搜索“附近的餐馆”、在打车软件上叫车】

發布時間:2024/3/13 数据库 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Redis】数据结构的应用——GEO 【搜索“附近的餐馆”、在打车软件上叫车】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

搜索“附近的餐館”、在打車軟件上叫車,這些都離不開基于位置信息服務(Location-Based Service,LBS)的應用。LBS 應用訪問的數據是和人或物關聯的一組經緯度信息,而且要能查詢相鄰的經緯度范圍

  • 以叫車服務為例,來分析下 LBS 應用中經緯度的存取特點。
  • 每一輛網約車都有一個編號(例如 33),網約車需要將自己的經度信息(例如 116.034579)和緯度信息(例如 39.000452 )發給叫車應用。
  • 用戶在叫車的時候,叫車應用會根據用戶的經緯度位置(例如經度 116.054579,緯度 39.030452),查找用戶的附近車輛,并進行匹配。
  • 等把位置相近的用戶和車輛匹配上以后,叫車應用就會根據車輛的編號,獲取車輛的信息,并返回給用戶。
  • 可以看到,一輛車(或一個用戶)對應一組經緯度,并且隨著車(或用戶)的位置移動,相應的經緯度也會變化。

    使用hash進行key:車輛ID,value:車輛經緯度

    這種數據記錄模式屬于一個 key(例如車 ID)對應一個 value(一組經緯度)。當有很多車輛信息要保存時,就需要有一個集合來保存一系列的 key 和 value。Hash 集合類型可以快速存取一系列的 key 和 value,正好可以用來記錄一系列車輛 ID 和經緯度的對應關系,所以,我們可以把不同車輛的 ID 和它們對應的經緯度信息存在 Hash 集合中,如下圖所示:

    Hash 類型的 HSET 操作命令,會根據 key 來設置相應的 value 值,所以,我們可以用它來快速地更新車輛變化的經緯度信息。

    問題:

    對于一個 LBS 應用來說,除了記錄經緯度信息,還需要根據用戶的經緯度信息在車輛的 Hash 集合中進行范圍查詢。一旦涉及到范圍查詢,就意味著集合中的元素需要有序,但 Hash 類型的元素是無序的,顯然不能滿足我們的要求。

    Sorted Set類型進行記錄

    GEO 類型的底層數據結構就是用 Sorted Set 來實現的

    Sorted Set 類型也支持一個 key 對應一個 value 的記錄模式,其中,key 就是 Sorted Set 中的元素,而 value 則是元素的權重分數。更重要的是,Sorted Set 可以根據元素的權重分數排序,支持范圍查詢。這就能滿足 LBS 服務中查找相鄰位置的需求了。

    用 Sorted Set 來保存車輛的經緯度信息時,Sorted Set 的元素是車輛 ID,元素的權重分數是經緯度信息,如下圖所示:


    Sorted Set 元素的權重分數是一個浮點數(float 類型),而一組經緯度包含的是經度和緯度兩個值,是沒法直接保存為一個浮點數的,那具體該怎么進行保存呢?

    • GEO 類型中的 GeoHash 編碼

    Redis 采用了業界廣泛使用的 GeoHash 編碼方法,這個方法的基本原理就是“二分區間,區間編碼”

    對于一個地理位置信息來說,它的經度范圍是[-180,180]。GeoHash 編碼會把一個經度值編碼成一個 N 位的二進制值,我們來對經度范圍[-180,180]做 N 次的二分區操作,其中 N 可以自定義。

    在進行第一次二分區時,經度范圍[-180,180]會被分成兩個子區間:[-180,0) 和[0,180](我稱之為左、右分區)。此時,我們可以查看一下要編碼的經度值落在了左分區還是右分區。如果是落在左分區,我們就用 0 表示;如果落在右分區,就用 1 表示。這樣一來,每做完一次二分區,我們就可以得到 1 位編碼值。

    然后,我們再對經度值所屬的分區再做一次二分區,同時再次查看經度值落在了二分區后的左分區還是右分區,按照剛才的規則再做 1 位編碼。當做完 N 次的二分區后,經度值就可以用一個 N bit 的數來表示了。

    舉個例子,假設我們要編碼的經度值是 116.37,我們用 5 位編碼值(也就是 N=5,做 5 次分區)。

    我們先做第一次二分區操作,把經度區間[-180,180]分成了左分區[-180,0) 和右分區[0,180],此時,經度值 116.37 是屬于右分區[0,180],所以,我們用 1 表示第一次二分區后的編碼值。

    接下來,我們做第二次二分區:把經度值 116.37 所屬的[0,180]區間,分成[0,90) 和[90, 180]。此時,經度值 116.37 還是屬于右分區[90,180],所以,第二次分區后的編碼值仍然為 1。等到第三次對[90,180]進行二分區,經度值 116.37 落在了分區后的左分區[90, 135) 中,所以,第三次分區后的編碼值就是 0。

    按照這種方法,做完 5 次分區后,我們把經度值 116.37 定位在[112.5, 123.75]這個區間,并且得到了經度值的 5 位編碼值,即 11010。這個編碼過程如下表所示:

    對緯度的編碼方式,和對經度的一樣,只是緯度的范圍是[-90,90],下面這張表顯示了對緯度值 39.86 的編碼過程。

    當一組經緯度值都編完碼后,我們再把它們的各自編碼值組合在一起,組合的規則是:最終編碼值的偶數位上依次是經度的編碼值,奇數位上依次是緯度的編碼值,其中,偶數位從 0 開始,奇數位從 1 開始。

    我們剛剛計算的經緯度(116.37,39.86)的各自編碼值是 11010 和 10111,組合之后,第 0 位是經度的第 0 位 1,第 1 位是緯度的第 0 位 1,第 2 位是經度的第 1 位 1,第 3 位是緯度的第 1 位 0,以此類推,就能得到最終編碼值 1110011101,如下圖所示:

    當然,使用 GeoHash 編碼后,我們相當于把整個地理空間劃分成了一個個方格,每個方格對應了 GeoHash 中的一個分區。

    總結

    以上是生活随笔為你收集整理的【Redis】数据结构的应用——GEO 【搜索“附近的餐馆”、在打车软件上叫车】的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。