水煮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);
    }
相关推荐
码农郁郁久居人下2 小时前
Redis的配置与优化
数据库·redis·缓存
架构文摘JGWZ2 小时前
Java 23 的12 个新特性!!
java·开发语言·学习
拾光师3 小时前
spring获取当前request
java·后端·spring
aPurpleBerry3 小时前
neo4j安装启动教程+对应的jdk配置
java·neo4j
我是苏苏3 小时前
Web开发:ABP框架2——入门级别的增删改查Demo
java·开发语言
xujinwei_gingko4 小时前
Spring IOC容器Bean对象管理-Java Config方式
java·spring
2301_789985944 小时前
Java语言程序设计基础篇_编程练习题*18.29(某个目录下的文件数目)
java·开发语言·学习
IT学长编程4 小时前
计算机毕业设计 教师科研信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·毕业设计·springboot·毕业论文·计算机毕业设计选题·计算机毕业设计开题报告·教师科研管理系统
m0_571957584 小时前
Java | Leetcode Java题解之第406题根据身高重建队列
java·leetcode·题解
Hsu_kk4 小时前
Redis 主从复制配置教程
数据库·redis·缓存