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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LBS解决方案

發(fā)布時間:2023/12/4 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LBS解决方案 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
LBS解決方案
  • LBS(基于地理位置的服務)服務是現(xiàn)在移動互聯(lián)網(wǎng)中比較常用的功能,例如外賣中我附近的店鋪,通常是以客戶位置坐標為中心,查詢一定范圍內的店鋪信息,按照距離由近及原進行倒敘排序
方案一,直接mysql
  • 經(jīng)緯度范圍計算就是弧度的計算,只要數(shù)學夠好,算出來分分鐘的事情,直接上mysql一個語句搞定:
CREATE TABLE `places` (`id` INT (11) NOT NULL AUTO_INCREMENT,`lat` DOUBLE NOT NULL DEFAULT '0',`lng` DOUBLE NOT NULL DEFAULT '0',PRIMARY KEY (`Id`),KEY `lat` (`lat`),KEY `lng` (`lng`) ) ENGINE = INNODB AUTO_INCREMENT = 9 DEFAULT CHARSET = utf8;-- 測試經(jīng)緯度 INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 23.123123, 123.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 21.123123, 121.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 22.123123, 122.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 24.123123, 124.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 25.123123, 125.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 26.123123, 126.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 27.123123, 127.123); INSERT INTO `zhenai_yewu`.`places` (`lat`, `lng`) VALUES ( 28.123123, 128.123);-- 為了查詢效果,將范圍設置為255555 單位是KM SELECT id, ( 6371 * acos( cos( radians(24.123123) ) * cos( radians( lat ) ) * cos( radians ( lng ) - radians(124.123) ) + sin( radians(24.123123) ) * sin( radians( lat ) ) ) ) AS distanceFROM places HAVING distance < 255555 ORDER BY distance LIMIT 0 , 100; -- 結果信息 id: distance 12 0 13 150.27231636470339 9 150.80702908932616 14 299.9866451782974 11 302.12576883654754 15 449.11942176001054 10 453.93347262147796 16 597.6467747050862
  • sql 查詢的是lat,lng對應的坐標信息,中心點的信息是[124.123, 24.123123],明顯這個是通過弧度計算來算出適合范圍內的經(jīng)緯度范圍,然后搜索對應的id,如下sql語句分析
  • 即使加上了索引這種查詢也必須掃全表信息,效率低下
  • 優(yōu)化一下:
    • 另外一種算法,可以根據(jù)圓心坐標計算正方形四個點的坐標,然后查詢正方形內的點。
SELECT * FROM places WHERE ((lat BETWEEN 20 AND 29) AND (lng BETWEEN 90 AND 170)); //獲取如下結果: 9 23.123123 123.123 10 21.123123 121.123 11 22.123123 122.123 12 24.123123 124.123 13 25.123123 125.123 14 26.123123 126.123 15 27.123123 127.123 16 28.123123 128.123
  • 這樣優(yōu)化后,雖然數(shù)據(jù)不完全精確(圓形變正方形),但性能提升很明顯,并且可以通過給lat lng字段做索引的方式進一步加快這條SQL的查詢速度。對精度有要求的應用也可以在這個結果上再進行計算,排除那些在方塊范圍內但不在圓形范圍內的數(shù)據(jù),已達到對精度的要求。 但是沒有排序,沒有距離,除非做其他運算。
方案二,Redis
  • Redis3.2.0后開始支持LBS相關的命令,要實現(xiàn)以上功能,主要用到Redis geo相關的兩個命令 GEOADD, GETRADIOUS
  • 命令描述,案例:
GEOADD key longitude latitude member [longitude latitude member ...] //命令將指定地理空間位置(金緯度信息,名稱)添加到指定key中
  • 有效經(jīng)度值域[-180,180], 有效緯度值域[-85.05112878 , 85.05112878 ],單坐標超過上述指定范圍時候,會返回錯誤信息,可以一次添加多個位置地點,如下案例:
新docker-redis:0>GEOADD location 117 20 beijing "1" 新docker-redis:0>GEOADD location 120 30 shenzheng "1" 新docker-redis:0>GEOADD location 121 31 guangzhou, 122 32 nanjing "2"
  • 添加后通過GEORADIOUS查詢如下:
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
  • 命令以給定的經(jīng)緯度為中心,返回鍵值key包含的位置元素中,與中心距離不超過給定最大距離的所有位置的元素,并且可以指定單位,順序返回單位信息如下:
m:米 km:千米 mi:英里 ft:英尺
  • 給定一下選項時候,命令會額外返回信息:
  • WITHDIST:返回位置元素的同時,將位置元素與中心之間的距離也一并返回。距離的單位和用戶給定的范圍單位保持一致 如下:
新docker-redis:0>GEORADIUS location 120.987 30.1234 500 km WITHDIST1) 1) "shenzheng"2) "95.9992"2) 1) "guangzhou,"2) "97.5090"3) 1) "nanjing"2) "229.9580"
  • WITHCOORD :將位置元素的進度和緯度也一起返回。
新docker-redis:0>GEORADIUS location 120.987 30.1234 500 km WITHCOORD1) 1) "shenzheng"2) 1) "120.00000089406967163"2) "30.00000024997701331"2) 1) "guangzhou,"2) 1) "120.99999815225601196"2) "31.00000097648057817"3) 1) "nanjing"2) 1) "122.00000077486038208"2) "31.99999916826298119"
  • WITHHASH 以52位有符號整形,返回位置元素經(jīng)過原始geohash編碼的有序集合分值
新docker-redis:0>GEORADIUS location 120.987 30.1234 500 km WITHHASH1) 1) "shenzheng"2) "4054115787372083"2) 1) "guangzhou,"2) "4054742425916764"3) 1) "nanjing"2) "4066587848444692"
  • asc:更具中心位置按從近到遠的方式返回位置元素
  • desc:根據(jù)中心位置,從遠到近的方式返回位置元素
  • 默認情況GEORADIUS命令會返回所有匹配的位置元素,用戶可以使用count 獲取前面N個
新docker-redis:0>GEORADIUS location 120.987 30.1234 500 km WITHHASH asc1) 1) "shenzheng"2) "4054115787372083"2) 1) "guangzhou,"2) "4054742425916764"3) 1) "nanjing"2) "4066587848444692"新docker-redis:0>GEORADIUS location 120.987 30.1234 500 km WITHHASH desc1) 1) "nanjing"2) "4066587848444692"2) 1) "guangzhou,"2) "4054742425916764"3) 1) "shenzheng"2) "4054115787372083"新docker-redis:0>GEORADIUS location 120.987 30.1234 500 km WITHHASH desc count 11) 1) "nanjing"2) "4066587848444692"
方案三
  • mongodb 原生支持地理位置索引2dSpace,可以直接用于位置距離計算和查詢。 而且我們用的也比較多,能夠支持地理位置查詢的同事也有免息集合存儲,數(shù)據(jù)格式自由,查詢性能高等特點,對應我們需求只需要一個mongodb查詢語句:
db。moment.find( { location : { $geoWithin :{ $centerSphere :[ [121.492183, 31.247610 ] , 1000 / 3963.2 ]} } } )
  • 查詢結果默認由近及遠,并且geoWithin是mongodb支持的查詢函數(shù),已經(jīng)在性能上做了高度的優(yōu)化,完全可以生產用,現(xiàn)在moment的地理位置推薦用的這個
方案四
  • GeoHash是一種地址編碼,通過切分地圖區(qū)域變成小的方塊,只有切分的足夠小,精度就越高。

上一篇:Redis分布式鎖奧義
下一篇:Redis遍歷方式思考–字典擴容方式

總結

以上是生活随笔為你收集整理的LBS解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

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