如何在Redis中快速推算两地之间的距离?——Geo篇

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: Redis 3.2 引入Geo类型,支持地理位置数据存储和计算,如距离和范围查询。使用`GEOADD`将城市经纬度添加至`zset`中,通过`GEOPOS`获取坐标,`GEODIST`计算距离,`GEORADIUS`查找指定范围内的城市。Redis的Geo功能适用于快速的地理位置服务,如附近搜索和配送范围分析。利用`ZSET`操作可增删位置数据,简化地理空间应用开发。

处理地理位置数据已成为许多应用程序的核心需求。无论是推送附近的餐馆还是对全国范围内的服务点进行分析,快速而准确地处理和检索地理位置信息都至关重要。Redis,作为一种高性能的内存数据库,为我们提供了这样的解决方案。

Redis 在 3.2 推出 Geo 类型,该功能可以推算出地理位置信息,两地之间的距离。有效的经度从 -180 度到 180 度。有效的纬度从 -85.05112878 度到 85.05112878 度,如果超过此范围,redis 会直接报错。

通过本文,我们将一步步探索 Redis 如何帮助我们处理地理位置数据,不仅适合初学者,也能让有经验的开发者有所收获。

添加地理位置数据

首先,我们需要向 Redis 中添加一些中国城市的地理位置数据:

你可以通过这个网站 http://www.jsons.cn/lngcode/ 来查询一下一些城市的经纬度。

127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shengzhen
(integer) 2
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian
(integer) 2

这里,geoadd 命令用于向指定的 key(这里是 china:city)中添加地理空间位置信息。每条记录包括经度、纬度以及位置的名称。

你是否会好奇 geo 是通过什么类型在 Redis 中存储的?那我们不妨可以使用 type 命令来进行查看一下:

127.0.0.1:6379> type china:city
zset

我们可以看到,其实 geo 底层实现原理就是 zset ,这表明 Redis 内部使用了有序集合存储地理空间信息,每个地点的名称是有序集合的成员,而其经纬度则用于计算分数,以确保成员的有序性。

查询地理空间信息

当信息存入数据库后,我们可以执行各种查询:

查询单个城市位置

127.0.0.1:6379> geopos china:city shanghai
1) 1) "121.47000163793563843"
   2) "31.22999903975783553"

geopos 命令用于获取一个或多个成员的地理位置信息(经度和纬度),这个命令返回上海的经纬度。

计算两城市间距离

单位:

  • m 表示单位为米,也是默认单位。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。
127.0.0.1:6379> geodist china:city shanghai chongqing
"1447673.6920"

geodist 命令用于计算两个位置之间的距离,默认单位是米。上面返回的是上海到重庆的距离。

查询指定范围内的城市

127.0.0.1:6379> georadius china:city 100 20 1000 km
(empty array)
127.0.0.1:6379> georadius china:city 110 30 1000 km
1) "chongqing"
2) "xian"
3) "shengzhen"
4) "hangzhou"

查看以(110,30)为中心,半径 1000 公里的范围内,有哪些城市。

带有选项的地理位置查询

Redis 地理空间查询还支持多种选项,例如,返回搜索结果的坐标和距离,或者限制返回结果的数量:

查询并返回坐标

127.0.0.1:6379> georadius china:city 110 30 1000 km withcoord
1) 1) "chongqing"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"

通过添加 withcoord 选项,georadius 命令可以返回位置元素的名称和它们的地理位置信息。

查询并返回距离

127.0.0.1:6379> georadius china:city 110 30 1000 km withdist
1) 1) "chongqing"
   2) "341.9374"
2) 1) "xian"
   2) "483.8340"
3) 1) "shengzhen"
   2) "924.6408"
4) 1) "hangzhou"
   2) "977.5143"

返回每个城市到查询中心的距离。

查询并限制结果数量

127.0.0.1:6379> georadius china:city 110 30 1000 km withdist withcoord count 2
1) 1) "chongqing"
   2) "341.9374"
   3) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) "483.8340"
   3) 1) "108.96000176668167114"
      2) "34.25999964418929977"

仅返回两个最近的城市及其坐标和距离。

查询某个距离范围内的元素

127.0.0.1:6379> georadiusbymember china:city chongqing 1000000 m
1) "chongqing"
2) "xian"

georadiusbymember 命令根据指定成员的位置和给定的距离,返回范围内的位置元素。

上文中,我们已经知道 geo 的底层是通过 zset 来实现的,那么也就意味着我们也可以通过 zset 命令来操作 geo。

127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "xian"
3) "shengzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city xian
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqing"
2) "shengzhen"
3) "hangzhou"
4) "shanghai"
5) "beijing"

实践意义

在实际开发中,你可以使用 Redis 的地理空间功能来实现各种基于位置的服务,如商家定位、配送范围估算、最近服务点查询等。通过上述例子,我们可以看到,Redis 提供的地理空间功能既强大又易于使用,能够帮助开发者在构建地理空间数据相关应用时,提高开发效率和应用性能。

结语

Redis 的地理空间数据处理模块为处理和查询地理信息提供了强大而高效的方法。无论你是在处理简单的位置数据查询还是构建复杂的地理信息系统(GIS),Redis 都能为你提供必要的支持。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
7月前
|
存储 NoSQL 定位技术
Redis Geo:掌握地理空间数据的艺术
Redis Geo:掌握地理空间数据的艺术
515 0
|
存储 NoSQL Java
|
2月前
|
存储 NoSQL 定位技术
Redis GEO
10月更文挑战第19天
40 1
|
7月前
|
SQL NoSQL Java
Redis数据类型 Hash Set Zset Bitmap HyperLogLog GEO
Redis数据类型 Hash Set Zset Bitmap HyperLogLog GEO
62 0
|
7月前
|
存储 NoSQL API
Redis入门到通关之GEO实现附近的人功能
Redis入门到通关之GEO实现附近的人功能
67 0
|
7月前
|
存储 NoSQL 定位技术
Redis Geo:解锁地理位置数据的新可能性
Redis Geo:解锁地理位置数据的新可能性
228 0
|
7月前
|
NoSQL Java Redis
Spring Boot和Redis Geo实现附近的人【redis实战 三】
Spring Boot和Redis Geo实现附近的人【redis实战 三】
240 0
|
7月前
|
存储 NoSQL Redis
【Redis】Redis 高级数据类型Bitmaps、HyperLogLog、GEO
【Redis】Redis 高级数据类型Bitmaps、HyperLogLog、GEO
78 0
【Redis】Redis 高级数据类型Bitmaps、HyperLogLog、GEO
|
7月前
|
存储 NoSQL 关系型数据库
Redis系列-8.Redis案例实战之Bitmap、Hyperloglog、GEO(下)
Redis系列-8.Redis案例实战之Bitmap、Hyperloglog、GEO
75 0
|
7月前
|
存储 NoSQL 算法
Redis系列-8.Redis案例实战之Bitmap、Hyperloglog、GEO(上)
Redis系列-8.Redis案例实战之Bitmap、Hyperloglog、GEO
103 0