水煮Redisson(二二)-GEO功能介绍

前言

Redis提供了GEO地理索引的实现,其存储结构本质上来说是一个ZSET,这一点可以从Redisson中的GEO接口看出来【public interface RGeoAsync extends RScoredSortedSetAsync

Redis 命令描述

  • GEOHASH 返回一个或多个位置元素的 Geohash 表示,Redis 使用 Geohash 技术的变体来表示元素的位置
  • GEOPOS 从 key 里返回所有给定位置元素的位置(经度和纬度)
  • GEODIST 返回两个给定位置之间的距离
  • GEORADIUS 以给定的经纬度为中心, 找出某一半径内的元素
  • GEOADD 将指定的地理空间位置(纬度、经度、名称)添加到指定的 key 中
  • GEORADIUSBYMEMBER 找出位于指定范围内的元素,中心点是由给定的位置元素决定

注意:没有 GEODEL 命令,因为可以使用 ZREM 来删除元素,地理索引结构只是一个有序集合【zset】。
注意:如果数据量过亿甚至更大,可能造成redis节点卡顿,这时就需要对 Geo 数据进行拆分,按国家拆分、按省拆分,按市拆分,在人口特大城市甚至可以按区拆分。这样就可以显著降低单个 zset 集合的大小。(注意:zset集合大小,进行合适地切分)

新增地理元素

csharp 复制代码
        RGeo<String> geo = client.getGeo("GEO_TEST");
        geo.add(new GeoEntry(121.472641,31.231707,"上海"));
		// 新增返回1,更新返回0
        long 添加数量 = geo.add(new GeoEntry(116.405289,39.904987,"北京"));
		System.out.println("添加数量:"+添加数量);

经纬度越界

  • 有效经度从-180到180度。
  • 有效纬度从 -85.05112878 到 85.05112878 度。
    当用户尝试索引超出指定范围的坐标时,该命令将报告错误。
csharp 复制代码
        // 异常:RedisException: ERR invalid longitude,latitude pair xxx,xxx
        geo.add(new GeoEntry(183.549130,22.198750,"经度越界"));
        geo.add(new GeoEntry(113.549130,92.198750,"纬度越界"));

计算两个元素之间的距离

ini 复制代码
        Double distance = geo.dist("北京", "上海", GeoUnit.KILOMETERS);
        System.out.println("北京和上海的距离:" + distance + " 千米");

输出信息
北京和上海的距离:1067.597 千米

元素的经纬度信息

ini 复制代码
        Map<String, GeoPosition> pos = geo.pos("北京", "上海");
        System.out.println("两个元素的经纬度信息\n" + pos);

输出信息
两个元素的经纬度信息
{上海=GeoPosition [longitude=121.47264093160629, latitude=31.231707441819232], 北京=GeoPosition [longitude=116.40528827905655, latitude=39.90498588819134]}

附近的元素

ini 复制代码
        // 返回10个在上海附近200米的元素名称和距离
        Map<String, Double> radiusWithDistance = geo.radiusWithDistance(
                "上海", 500, GeoUnit.KILOMETERS, GeoOrder.ASC, 10);
        System.out.println("上海附近500千米的元素名称和距离[千米]\n" + radiusWithDistance);
        // 经度 120,纬度30,半径500千米,这个范围内的元素
        List<String> cities = geo.radius(120, 30, 500, GeoUnit.KILOMETERS);
        System.out.println("经度120,纬度30,半径500千米,这个范围内的元素\n" + cities);
        // 返回10个在经度15,纬度37附近200米内的元素名称和距离,方便在列表中显示
        Map<String, Double> radiusWithDistance2 = geo.radiusWithDistance(
                120, 30, 500, GeoUnit.KILOMETERS, GeoOrder.ASC, 10);
        System.out.println("经度120,纬度30附近500千米内的元素名称和距离[千米]\n" + radiusWithDistance2);

输出信息
上海附近500千米的元素名称和距离[千米]
{上海=0.0, 杭州=164.0861, 南京=271.5419, 合肥=403.2241}
经度120,纬度30,半径500千米,这个范围内的元素
[南昌, 合肥, 杭州, 上海, 南京, 福州]
经度120,纬度30附近500千米内的元素名称和距离[千米]
{杭州=35.2204, 上海=196.5638, 南京=255.6618, 合肥=331.7151, 南昌=424.5977, 福州=441.8072}

redisson实现

RGeo的实现类是【RedissonGeo】,其中基本都是直接调用redis的指令来完成计算,没有特别的自定义逻辑,所以不进行详细介绍。例如:

scss 复制代码
    public RFuture<Map<V, Double>> radiusWithDistanceAsync(double longitude, double latitude, double radius,
            GeoUnit geoUnit, GeoOrder geoOrder, int count) {
        return commandExecutor.readAsync(getName(), codec, GEORADIUS_RO_DISTANCE, getName(), convert(longitude),
                convert(latitude), radius, geoUnit, "WITHDIST", "COUNT", count, geoOrder);
    }
相关推荐
dr李四维43 分钟前
Java在小米SU7 Ultra汽车中的技术赋能
java·人工智能·安卓·智能驾驶·互联·小米su7ultra·hdfs架构
RainbowSea1 小时前
130道基础OJ编程题之: 78~88
java
松树戈1 小时前
IDEA Commit 模态提交界面关闭VS开启对比
java·ide·intellij-idea
谦行1 小时前
前端视角 Java Web 入门手册 4.4:Web 开发基础—— Listener
java·后端
jk_1012 小时前
MATLAB中strip函数用法
java·服务器·数据库
一弓虽2 小时前
maven学习
java·学习·github·maven
24k小善2 小时前
Flink Forward Asia 2024 大会 内容整理
java·大数据·flink
xiaozaq2 小时前
在Eclipse中安装Lombok插件
java·python·eclipse
P7进阶路3 小时前
nginx 代理 redis
运维·redis·nginx
是姜姜啊!3 小时前
服务熔断组件sentinel,监控服务-springboot-admin-ui
java·服务器