一灰灰blog 一灰灰blog
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)

一灰灰blog

资深搬运工
首页
  • InfluxDB
  • MongoDB
  • MySql
  • 基础系列
  • DB系列
  • 搜索系列
  • MQ系列
  • WEB系列
  • 中间件
  • 运维
  • SpringSecurity
  • SpringCloud
  • QuickAlarm
  • QuickCrawer
  • QuickFix
  • QuickMedia
  • QuickSpi
  • QuickTask
  • 高可用
  • 分类
  • 标签
  • 归档
  • 收藏
  • 关于
GitHub (opens new window)
  • 基础系列

  • DB系列

    • H2Database

    • JPA

    • JdbcTemplate

    • Jooq

    • Mybatis

    • 事务

    • MongoDB

    • Redis

      • 【DB系列】Redis之基本配置
      • 【DB系列】Redis之Jedis配置
      • 【DB系列】Redis之String数据结构的读写
      • 【DB系列】Redis之List数据结构使用姿势
      • 【DB系列】Redis之Hash数据结构使用姿势
      • 【DB系列】Redis之Set数据结构使用姿势
      • 【DB系列】Redis之ZSet数据结构使用姿势
      • 【DB系列】借助Redis实现排行榜功能(应用篇)
      • 【DB系列】借助Redis搭建一个简单站点统计服务(应用篇)
      • 【DB系列】Redis集群环境配置
      • 【DB系列】Redis之管道Pipelined使用姿势
      • 【DB系列】Redis高级特性之Bitmap使用姿势及应用场景介绍
      • 【DB系列】Redis高级特性之发布订阅
      • 【DB系列】Redis高级特性之HyperLoglog
      • 【DB系列】Redis高级特性之GEO
        • I. 基本使用
          • 1. 配置
          • 2. 使用姿势
          • 3. 小结
        • II. 其他
          • 0. 项目
          • 1. 一灰灰Blog
      • 【DB系列】redisson分布式锁使用及注意事项
      • 【DB系列】缓存注解@Cacheable @CacheEvit @CachePut使用姿势介绍
      • 【DB系列】SpringBoot缓存注解@Cacheable之自定义key策略及缓存失效时间指定
      • 【DB系列】借助redis来实现延时队列(应用篇)
      • 【DB系列】Redis实现分布式锁(应用篇)
    • 实例

  • 搜索系列

  • MQ系列

  • WEB系列

  • 中间件

  • 运维

  • SpringSecurity

  • SpringCloud

  • Spring系列
  • DB系列
  • Redis
一灰灰
2020-10-27

【DB系列】Redis高级特性之GEO

GEO用于存储地理信息,最直观的就是我们日常使用的地图app中,如果我想查询我所在地的周边餐饮,就可以利用geo中的以(x,y)为圆心,以n为半径,扫描坐标在这个圈内的所有餐饮店,这个case借助redis的geo可以很方便的实现

# I. 基本使用

# 1. 配置

我们使用SpringBoot 2.2.1.RELEASE来搭建项目环境,直接在pom.xml中添加redis依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1
2
3
4

如果我们的redis是默认配置,则可以不额外添加任何配置;也可以直接在application.yml配置中,如下

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password:
1
2
3
4
5

# 2. 使用姿势

geo有6个常见的命令,下面逐一进行解释说明

# a. geoadd 添加

存储指定的地理空间位置,一般需要三个基本的参数,经度 + 维度 + 位置名

private final StringRedisTemplate redisTemplate;

public GeoBean(StringRedisTemplate stringRedisTemplate) {
    this.redisTemplate = stringRedisTemplate;
}

/**
 * 添加geo信息
 *
 * @param key       缓存key
 * @param longitude 经度
 * @param latitude  纬度
 * @param member    位置名
 */
public void add(String key, double longitude, double latitude, String member) {
    // geoadd xhh_pos 114.31 30.52 武汉 116.46 39.92 北京
    redisTemplate.opsForGeo().add(key, new Point(longitude, latitude), member);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# b. geopos 获取坐标

上面添加一组坐标 + 地理位置到redis中,如果我们想知道某个位置的坐标,则可以借助geopos来获取

/**
 * 获取某个地方的坐标
 *
 * @param key
 * @param member
 * @return
 */
public List<Point> get(String key, String... member) {
    // geopos xhh_pos 武汉
    List<Point> list = redisTemplate.opsForGeo().position(key, member);
    return list;
}
1
2
3
4
5
6
7
8
9
10
11
12

# c. geodist 获取距离

计算两个位置之间的距离,比如我已经写入了武汉、北京的经纬度,这个时候希望知道他们两的距离,直接geodist即可

/**
 * 判断两个地点的距离
 *
 * @param key
 * @param source
 * @param dest
 * @return
 */
public Distance distance(String key, String source, String dest) {
    // 可以指定距离单位,默认是米, ft->英尺, mi->英里
    // geodist xhh_pos 武汉 北京 km
    return redisTemplate.opsForGeo().distance(key, source, dest);
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# d. georadius 获取临近元素

georadius 以给定的经纬度为中心, 返回与中心的距离不超过给定最大距离的所有位置元素。

 public void near(String key, double longitude, double latitude) {
    // georadius xhh_pos 114.31 30.52 5km
    Circle circle = new Circle(longitude, latitude, 5 * Metrics.KILOMETERS.getMultiplier());
    RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
            .includeDistance()
            .includeCoordinates()
            .sortAscending().limit(5);
    GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo()
            .radius(key, circle, args);
    System.out.println(results);
}
1
2
3
4
5
6
7
8
9
10
11

# e. georadiusbymember 获取临近元素

和上面的作用差不多,区别在于上面参数是经纬度,这里是位置

public void nearByPlace(String key, String member) {
    // georadiusbymember xhh_pos 武汉 1100 km
    Distance distance = new Distance(5, Metrics.KILOMETERS);
    RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
            .includeDistance()
            .includeCoordinates()
            .sortAscending()
            .limit(5);
    GeoResults<RedisGeoCommands.GeoLocation<String>> results = redisTemplate.opsForGeo()
            .radius(key, member, distance, args);
    System.out.println(results);
}
1
2
3
4
5
6
7
8
9
10
11
12

# f. geohash

GeoHash将二维的经纬度转换成字符串,将二维的经纬度转换为一维的字符串,可以方便业务优化;geohash有自己的一套算法,这里不详细展开,有兴趣的小伙伴可以搜索一下

public void geoHash(String key) {
    // geohash xhh_pos 武汉
    List<String> results = redisTemplate.opsForGeo()
            .hash(key, "北京", "上海", "深圳");
    System.out.println(results);
}
1
2
3
4
5
6

# 3. 小结

geo更适用于地图这种业务场景中,关于这块的业务没怎么接触过,也不太好确定诸如百度地图、高德地图这种是否有在真实业务中采用;如果我们把目标缩小一点,改成一个地下车库的导航,统计所在位置周边的空余车位,位置导航,停车位记录,感觉有点靠谱

注意上面的六个操作命令,没有删除,但如果我们错误的写入了一个数据,难道没法删除么?

  • 使用 zrem key member 执行删除操作,如上面的case中,删除北京的坐标,可以: zrem xhh_pos 北京

为什么可以这么操作?

  • geo的底层存储借助ZSET来实现的,因此zset的操作符都是支持的,geo添加的元素,会通过算法得出一个score,如上面case中的北京,武汉添加之后,zset值为

# II. 其他

# 0. 项目

系列博文

  • 【DB系列】Redis高级特性之HyperLoglog (opens new window)
  • 【DB系列】Redis高级特性之发布订阅 (opens new window)
  • 【DB系列】Redis高级特性之Bitmap使用姿势及应用场景介绍 (opens new window)
  • 【DB系列】Redis之管道Pipelined使用姿势 (opens new window)
  • 【DB系列】Redis集群环境配置 (opens new window)
  • 【DB系列】借助Redis搭建一个简单站点统计服务(应用篇) (opens new window)
  • 【DB系列】借助Redis实现排行榜功能(应用篇) (opens new window)
  • 【DB系列】Redis之ZSet数据结构使用姿势 (opens new window)
  • 【DB系列】Redis之Set数据结构使用姿势 (opens new window)
  • 【DB系列】Redis之Hash数据结构使用姿势 (opens new window)
  • 【DB系列】Redis之List数据结构使用姿势 (opens new window)
  • 【DB系列】Redis之String数据结构的读写 (opens new window)
  • 【DB系列】Redis之Jedis配置 (opens new window)
  • 【DB系列】Redis之基本配置 (opens new window)

工程源码

  • 工程:https://github.com/liuyueyi/spring-boot-demo (opens new window)
  • 项目源码: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/122-redis-template (opens new window)

# 1. 一灰灰Blog

尽信书则不如,以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

下面一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

  • 一灰灰Blog个人博客 https://blog.hhui.top (opens new window)
  • 一灰灰Blog-Spring专题博客 http://spring.hhui.top (opens new window)

一灰灰blog

编辑 (opens new window)
#Redis
上次更新: 2021/10/15, 19:56:22
【DB系列】Redis高级特性之HyperLoglog
【DB系列】redisson分布式锁使用及注意事项

← 【DB系列】Redis高级特性之HyperLoglog 【DB系列】redisson分布式锁使用及注意事项→

最近更新
01
【基础系列】基于maven多环境配置
04-25
02
【WEB系列】内嵌Tomcat配置Accesslog日志文件生成位置源码探索
04-24
03
【搜索系列】ES查询常用实例演示
04-18
更多文章>
Theme by Vdoing | Copyright © 2017-2022 一灰灰Blog
MIT License | 鄂ICP备18017282号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×