面試問題
Redis 如何實現查詢附近的人?
涉及知識點
- Redis 中如何操作位置信息?
- GEO 底層是如何實現的?
- 如何在程序實現查詢附近的人?
- 在實際使用中需要注意哪些問題?
視頻答案
視頻地址:https://www.bilibili.com/video/av89369236/
圖文答案
Redis 中要實現查詢附近的人,需要使用 Redis 3.2 版本中提供的 GEO 數據類型,它包含以下幾個重要的方法:
- GEOADD 添加元素位置信息;
- GEOPOS 查詢元素經緯度信息;
- GEODIST 查詢兩個元素的直線距離;
- GEORADIUS 查詢附近一定距離內的元素信息。
首先我們可以使用百度提供的經緯度查詢工具來確定位置信息,地址:我們先用百度地圖提供的經緯度查詢工具,地址:http://api.map.baidu.com/lbsapi/getpoint/index.html
命令使用詳見視頻部分。
代碼實戰
下面我們用 Java 代碼,來實現查詢附近的人,完整代碼如下:
import redis.clients.jedis.GeoCoordinate;
import redis.clients.jedis.GeoRadiusResponse;
import redis.clients.jedis.GeoUnit;
import redis.clients.jedis.Jedis;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class GeoHashExample {
public static void main(String[] args) {
Jedis jedis = new Jedis("127.0.0.1", 6379);
Map<String, GeoCoordinate> map = new HashMap<>();
// 添加小明的位置
map.put("xiaoming", new GeoCoordinate(116.404269, 39.913164));
// 添加小紅的位置
map.put("xiaohong", new GeoCoordinate(116.36, 39.922461));
// 添加小美的位置
map.put("xiaomei", new GeoCoordinate(116.499705, 39.874635));
// 添加小二
map.put("xiaoer", new GeoCoordinate(116.193275, 39.996348));
jedis.geoadd("person", map);
// 查詢小明和小紅的直線距離
System.out.println("小明和小紅相距:" + jedis.geodist("person", "xiaoming",
"xiaohong", GeoUnit.KM) + " KM");
// 查詢小明附近 5 公里的人
List<GeoRadiusResponse> res = jedis.georadiusByMemberReadonly("person", "xiaoming",
5, GeoUnit.KM);
for (int i = 1; i < res.size(); i++) {
System.out.println("小明附近的人:" + res.get(i).getMemberByString());
}
}
}
以上程序執行的結果如下:
小明和小紅相距:3.9153 KM
小明附近的人:xiaohong
總結
GEO 是 Redis 3.2 版本中新增的功能,只有升級到 3.2+ 才能使用,GEO 本質上是基於 ZSet 實現的,這點在 Redis 源碼找到相關信息,我們可以 GEO 使用實現查找附近的人或者附近的地點,還可以用它來計算兩個位置相隔的直線距離。