水煮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);
    }
相关推荐
customer082 小时前
【开源免费】基于SpringBoot+Vue.JS体育馆管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
Miketutu3 小时前
Spring MVC消息转换器
java·spring
乔冠宇3 小时前
Java手写简单Merkle树
java·区块链·merkle树
LUCIAZZZ4 小时前
简单的SQL语句的快速复习
java·数据库·sql
komo莫莫da4 小时前
寒假刷题Day19
java·开发语言
S-X-S5 小时前
算法总结-数组/字符串
java·数据结构·算法
linwq85 小时前
设计模式学习(二)
java·学习·设计模式
桦说编程6 小时前
CompletableFuture 超时功能有大坑!使用不当直接生产事故!
java·性能优化·函数式编程·并发编程
@_@哆啦A梦6 小时前
Redis 基础命令
java·数据库·redis
字节全栈_rJF7 小时前
性能测试 —— Tomcat监控与调优:status页监控_tomcat 自带监控
java·tomcat