使用Redis來實現LBS的應用

2021-07-03 23:30:34 字數 2718 閱讀 8678

目標

查詢附近的某某某,由近到遠返回結果,且結果中有與目標點的距離。

針對查詢附近的某某某,提出兩個方案,如下:

方案a:

本方案前,請先閱讀:基於lbs功能應用的geohash方案,看過該文章便可簡單知道;

1、僅需每分鐘將使用者的經緯度,上報到資料庫;

2、然後每次使用者查詢附近好友時,通過 like 『wm3yr3%』,即可獲取

缺點:稍有一定資料量,對資料庫的鴨梨可想而知

方案b:使用redis

策略假象把中國分成,若干個一平方公里的單元格

1)、使用者位置的變更,理解為乙個單元格移動到另外乙個單元格(或者不移動)

2)、使用者查詢附近,理解為查詢,自己所在方塊的的所有人

資料結構

1)、使用者基本資訊 緯度、經度、geohash值(經緯度,僅用於後期距離計算)

2)、單元格 集合(使用者1,使用者2,…)

儲存工具

1)、redis string(key->value) 結構,儲存使用者基本資訊

2)、redis set(集合) 結構,以geohash值,前6位作為key(約表示一平方千公尺),儲存單元格的使用者群

演算法流程

1)、更新使用者資訊,先刪除使用者原所在集合,再更新當前使用者資訊,最後更新當前使用者所在集合

2)、查詢附近,直接查詢,所在單元格集合所有使用者id

具體實現

<?php

include_once('geohash.class.php');

class lbs

/*** 更新使用者資訊

* @param mixed $latitude 緯度

* @param mixed $longitude 經度

*/public function upinfo($user_id,$latitude,$longitude)

//新資料處理

//緯度

$this

->redis->hset($user_id,'la',$latitude);

//經度

$this

->redis->hset($user_id,'lo',$longitude);

//geohash

$hashdata

=$this

->geohash->encode($latitude,$longitude);

$this

->redis->hset($user_id,'geo',$hashdata);

//索引

$index_key

= substr($hashdata, 0, $this

->index_len);

//存入

$this

->redis->sadd($index_key,$user_id);

return

true;

}/**

* 獲取附近使用者

* @param mixed $latitude 緯度

* @param mixed $longitude 經度

*/public function serach($latitude,$longitude)

}?>

效能測試

1)模擬資料上報

<?php

include_once('lbs.class.php');

$b_time = microtime(true);

$n = 0;

while(1)

}function

mylog

($content)

?>

2)模擬附近查詢

<?php

include_once('lbs.class.php');

$b_time = microtime(true);

$n = 0;

while(1)

}function

mylog

($content)

?>

測試環境

vmware虛擬機器,記憶體256m,主頻2.93ghz

效能結果

模擬了100w活躍使用者行為,不斷更新,不斷查詢附近好友

//60 seconds insert

88544

//60 seconds search

117660

//成都 100w人,資料占用記憶體

11.97m

總結

尚可改進之處:

1、geohash,可寫成php c擴充套件;或者其他geohash實現方式

2、redis,記憶體消耗較大,可考慮redis集群方案

3、本文僅查出本單元格使用者,提高精度,可查出周圍八個單元個,求交集

問題1)假設我現在設定的hash長度為7 ,那乙個個hash值對應乙個塊,如何得到這個塊的座標區間呢?

例如,成都永豐立交的geohash值為:wm3yr31d2524;如取7位,則為,wm3yr31;

根據geohash的演算法,那麼區間就會是 wm3yr3100000 ~ wm3yr31zzzzz;

根據如上兩值,通過「geohash->經緯度」算出經緯度,可大致確定區間。

2)如果使用者上報的位置資訊有時效性(比如:15秒內有效)如何處理?

可以在redis儲存的時候,設定有效時間

使用Redis來實現LBS的應用

1 僅需每分鐘將使用者的經緯度,上報到資料庫 2 然後每次使用者查詢附近好友時,通過 like wm3yr3 即可獲取 缺點 稍有一定資料量,對資料庫的鴨梨可想而知 假象把中國分成,若干個一平方公里的單元格 1 使用者位置的變更,理解為乙個單元格移動到另外乙個單元格 或者不移動 2 使用者查詢附近,...

使用thin neverblock來部署應用

neverblock出了之後就想試一試,但是跟mongrel配合有點問題,所以還是選擇thin,感覺不錯。url 下完後解壓,打包成gem,然後安裝。thin可以用gem直接安裝 sudo gem install thin thin來啟動rails非常簡單,切換到應用程式目錄,直接用 thin st...

使用 Redis 來實現定時任務

在 redis 的2.8.0版本之後,其推出了乙個新的特性 鍵空間訊息 redis keyspace notifications 它配合 2.0.0 版本之後的 subscribe 就能完成這個定時任務的操作了,不過定時的單位是秒。redis 在 2.0.0 之後推出了 pub sub 的指令,大致...