vertx+redis实现查找附近的人
1.Redis GEO简介
Redis GEO实现主要包含了以下两项技术:
1、使用geohash保存地理位置的坐标。
geohash的思想是将二维的经纬度转换成一维的字符串,geohash有以下三个特点:
1.字符串越长,表示的范围越精确。编码长度为8时,精度在19米左右,而当编码长度为9时,精度在2米左右。
2.字符串相似的表示距离相近,利用字符串的前缀匹配,可以查询附近的地理位置。这样就实现了快速查询某个坐标附近的地理位置。
2、使用有序集合(zset)保存地理位置的集合。
主要方法:
geoadd:添加地理位置的坐标。
geopos:获取地理位置的坐标。
geodist:计算两个位置之间的距离。
georadius:根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
georadiusbymember:根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合。
geohash:返回一个或多个位置对象的 geohash 值。
2.后台搭建
后台使用Vert.x,底层使用netty,比springboot性能更好,更轻量,当然也更难用。
1.新建普通maven项目,并修改pom文件加入依赖
<!--使用vertx-core就足够,不必使用vertx-web,据闻vertx-core性能更好-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>3.9.4</version>
</dependency>
<!--redis依赖,版本最好跟vertx一致-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-redis-client</artifactId>
<version>3.9.4</version>
</dependency>
2.新建普通类,写一个main方法运行,以开启http服务并监听8080端口,实现保存用户位置,和返回2km内的其他用户。
package hm.com.app;
import io.vertx.core.Vertx;
import io.vertx.redis.client.*;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class App {
public static void main(String[] args) {
String GEO_KEY="location";
Vertx vertx = Vertx.vertx();
//创建http服务,并接收请求。这里监听所有请求方法和路径。
vertx.createHttpServer().requestHandler(request -> {
String longitude = request.getParam("longitude");
String latitude = request.getParam("latitude");
String nickname = request.getParam("nickname");
//获取redis连接,异步
Redis.createClient(vertx, new RedisOptions())
.connect(onConnect -> {
if (onConnect.succeeded()) {
RedisConnection client = onConnect.result();
RedisAPI redis = RedisAPI.api(client);
//保存用户位置
//GEOADD key longitude latitude member
redis.geoadd(Arrays.asList(new String[] {GEO_KEY,longitude,latitude,nickname}), res -> {
if (res.succeeded()) {
System.out.println("添加或更新成功..." + res.result().toInteger());
}
});
//获取附近的人
//GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]
redis.georadius(Arrays.asList(new String[] {GEO_KEY,longitude,latitude,"2","km"}), res -> {
if (res.succeeded()) {
List<Response> list1=res.result().stream().filter(s2-> !s2.toString().equals(nickname)).collect(Collectors.toList());
request.response().end(list1.toString());
}
});
}
});
}).listen(8080);//监听8080端口
}
}
3.调用接口
redis用zset保存