Redis之Geospatial:你不知道的,附近人

2023-11-04 10:10
文章标签 redis 知道 附近 geospatial

本文主要是介绍Redis之Geospatial:你不知道的,附近人,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • J3 - 白起
  • Redis数据类型 # Geospatial
  • Redis的基本数据类型停更有一段时间了,是时候重新拾起它了。那么今天我来介绍一下这个Redis的Geospatial相关命令,不知道你们怎么觉得反正我感觉挺实用的这个数据类型,因为我实习入职的时候接到的第一个项目好像就用的了这个数据类型(可惜那个功能不是我写的😂)。

一、Geospatial概述

Redis 在 3.2 版本以后增加了地理位置 GEO 模块。

生活中我们常常见到的功能如:附近的人查找共享单车美团找附近的餐馆等用来指定两地之间的距离基本上都可以用这个来实现!

并且Geospatial本质是使用Sorted Set存储的,当然计算两者之间的距离Redis用的底层技术则是GeoHash(不了解的,可以看我下面贴出来的资料一)。

Redis对GEO模块添加地理位置的形式是:

key 经度 纬度 名称
  • key:这个好理解我就不解释了
  • 经度:从本初子午线0度开始,向左和向右分别分出180度,跨度是(-180,180),其中本初子午线向左称为西经,本初子午线向右称为东经。
  • 纬度:以赤道0度开始,向上和向下分别分出90度,南极和北极分别为南纬90度和北纬90度,南极到北极的跨度是(-90,90),其中赤道到南极称为南纬,赤道到北极称为北纬。
  • 名称:经度与纬度对应的地理名称

注意的点:

  1. 两级无法直接添加。
  2. 经纬度一定不能超出范围,有效的纬度从-85.05112878度到85.05112878度、有效的经度从-180度到180度。
  3. 地球是圆的,这两个数字的单位不是距离,而是角度。

学下面六个GEO命令之前,我们先来准备一下数据(城市经纬度)

获取城市经纬度:https://jingweidu.bmcx.com/

查看两地距离:http://www.24timemap.com/distance

  1. 北京:116.23128,40.22077
  2. 上海:121.48941,31.40527
  3. 重庆:106.54041,29.40268
  4. 广州:113.27324,23.15792
  5. 天津:117.30983,39.71755
  6. 深圳:113.88308,22.55329

有了以上的这些数据,我们就可以开始学习下面的六个命令了。

二、六大命令解析

2.1 GEOADD(geoadd)

**时间复杂度:**每一个元素添加是O(log(N)) ,N是sorted set的元素数量。

添加地理位置

案例:

127.0.0.1:6379> geoadd myMap 116.23128 40.22077 beijing #添加一个城市的地理坐标
(integer) 1
127.0.0.1:6379> geoadd myMap 121.48941 31.40527 shanghai 106.54041 29.40268 chongqing 113.27324 23.15792 guangzhou #添加多个
(integer) 3
127.0.0.1:6379> geoadd myMap 117.30983 39.71755 tianjing 113.88308 22.55329 shenzhen #添加多个
(integer) 2
127.0.0.1:6379> 

2.2 GEOPOS(geopos)

时间复杂度:O(log(N))对于请求的每个成员,其中N是排序集中的元素数量。

获得对应位置的经纬度

返回值:

GEOPOS 命令返回一个数组, 数组中的每个项都由两个元素组成: 第一个元素为给定位置元素的经度, 而第二个元素则为给定位置元素的纬度。

当给定的位置元素不存在时, 对应的数组项为空值。

案例

127.0.0.1:6379> geopos myMap beijing #获取指定位置的下标
1) 1) "116.23128265142440796"2) "40.22076905438526495"
127.0.0.1:6379> geopos myMap shanghai
1) 1) "121.48941010236740112"2) "31.40526993848380499"
127.0.0.1:6379> geopos myMap shanghai tianjing #一次性获取多个地理坐标
1) 1) "121.48941010236740112"2) "31.40526993848380499"
2) 1) "117.30983108282089233"2) "39.71755086262169954"
127.0.0.1:6379> 

2.3 GEODIST(geodist)

时间复杂度:O(log(N))

返回两地之间的距离,如果两个位置之间的其中一个不存在, 那么命令返回空值。

指定单位的参数 unit 必须是以下单位的其中一个:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

如果用户没有显式地指定单位参数, 那么 GEODIST 默认使用米作为单位。

GEODIST 命令在计算距离时会假设地球为完美的球形, 在极限情况下, 这一假设最大会造成 0.5% 的误差。

案例:

127.0.0.1:6379> geodist myMap beijing tianjing km #北京与天津之间的直线距离,km
"107.6344"
127.0.0.1:6379> 

用上面我贴的工具验证一下:

在这里插入图片描述

我们注意到,这计算的还是很精准的。

2.4 GEORADIUS(georadius)

时间复杂度:O(N+log(M))其中,N为以圆心和半径划定的圆形区域的边框内的元素数量,M为索引内的项目数量。

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

范围可以使用以下其中一个单位:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。

在给定以下可选项时, 命令会返回额外的信息:

  • WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。 距离的单位和用户给定的范围单位保持一致。
  • WITHCOORD: 将位置元素的经度和维度也一并返回。
  • WITHHASH: 以 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。

命令默认返回未排序的位置元素。 通过以下两个参数, 用户可以指定被返回位置元素的排序方式:

  • ASC: 根据中心的位置, 按照从近到远的方式返回位置元素。
  • DESC: 根据中心的位置, 按照从远到近的方式返回位置元素。

案例:

127.0.0.1:6379> georadius myMap 112.89262 22.90026 100 km	#返回指定经纬度为中心的100km范围内的城市
1) "guangzhou"
127.0.0.1:6379> georadius myMap 112.89262 22.90026 200 km withdist	#返回指定经纬度为中心的200km范围内的城市和城市离中心的距离
1) 1) "shenzhen"2) "108.6930"
2) 1) "guangzhou"
127.0.0.1:6379> georadius myMap 112.89262 22.90026 200 km withcoord #获取指定中心范围内的城市和经纬度
1) 1) "shenzhen"2) 1) "113.88307839632034302"2) "22.55329111565713873"
2) 1) "guangzhou"2) 1) "113.27324062585830688"2) "23.1579209662846921"
127.0.0.1:6379> georadius myMap 112.89262 22.90026 200 km withdist desc #带排序,远到近
1) 1) "shenzhen"2) "108.6930"
2) 1) "guangzhou"2) "48.3662"
127.0.0.1:6379> georadius myMap 112.89262 22.90026 200 km withdist asc #带排序,近到远
1) 1) "guangzhou"2) "48.3662"
2) 1) "shenzhen"2) "108.6930"
127.0.0.1:6379> georadius myMap 112.89262 22.90026 200 km withdist count 1 #只获取一个
1) 1) "guangzhou"2) "48.3662"

2.5 GEORADIUSBYMEMBER(georadiusbymember)

时间复杂度:O(N+log(M))其中,N为以圆心和半径划定的圆形区域的边框内的元素数量,M为索引内的项目数量。

这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS那样, 使用输入的经度和纬度来决定中心点。

案例:

127.0.0.1:6379> georadiusbymember myMap shenzhen 200 km # 获取深圳为中心200km范围内的城市
1) "shenzhen"
2) "guangzhou"
127.0.0.1:6379> georadiusbymember myMap beijing 200 km #和上面同理
1) "beijing"
2) "tianjing"
127.0.0.1:6379> 

2.6 GEOHASH(geohash)

这个基本用不到,知道有这么回事就行

时间复杂度:O(log(N))对于请求的每个成员,其中N是排序集中的元素数量。

返回一个或多个位置元素的 Geohash 表示。

案例:

127.0.0.1:6379> geohash myMap chongqing tianjing # 获取指定位置的 geohash字符串
1) "wm5z22s7520"
2) "wx53vqq7t00"
127.0.0.1:6379> 

三、Geospatial存储原理案例

前面我说过,Geospatial是使用Sorted Set存储的,那么我们现在回头想想,上面介绍的六种操作命令有将城市的数据移除的命令吗?

显然没有,那么我现在就用Sorted Set中相关的命令来操作一下

案例:

127.0.0.1:6379> zrange myMap 0 -1				#获取myMap的所有值
1) "chongqing"
2) "shenzhen"
3) "guangzhou"
4) "shanghai"
5) "tianjing"
6) "beijing"
127.0.0.1:6379> zrange myMap 0 -1 withscores	#获取myMap的所有值及对应的分数1) "chongqing"2) "4026046519194590"3) "shenzhen"4) "4046340107163728"5) "guangzhou"6) "4046534010880445"7) "shanghai"8) "4054807796443227"9) "tianjing"
10) "4069256193403282"
11) "beijing"
12) "4069896088584598"
127.0.0.1:6379> zrem myMap shenzhen	#移除指定的值
(integer) 1
127.0.0.1:6379> zrange myMap 0 -1 withscores1) "chongqing"2) "4026046519194590"3) "guangzhou"4) "4046534010880445"5) "shanghai"6) "4054807796443227"7) "tianjing"8) "4069256193403282"9) "beijing"
10) "4069896088584598"
127.0.0.1:6379> 

通过上面这案例也说明了Geospatial的存储结构就是Sorted Set。


参考资料

资料一:《redis系列之——数据类型geospatial:你隔壁有没有老王?》

资料二:Redis中文网

  • 由于博主才疏学浅,难免会有纰漏,假如你发现了错误或偏见的地方,还望留言给我指出来,我会对其加以修正。
  • 如果你觉得文章还不错,你的转发、分享、点赞、留言就是对我最大的鼓励。
  • 感谢您的阅读,十分欢迎并感谢您的关注。

好了,今天的内容到这里就结束了,关注我,我们下期见

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

CSDN:J3 - 白起

这是一个技术一般,但热衷于分享;经验尚浅,但脸皮够厚;明明年轻有颜值,但非要靠才华吃饭的程序员。

长按下图二维码关注,来一场博友之交吧!

在这里插入图片描述

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

这篇关于Redis之Geospatial:你不知道的,附近人的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/345054

相关文章

redis群集简单部署过程

《redis群集简单部署过程》文章介绍了Redis,一个高性能的键值存储系统,其支持多种数据结构和命令,它还讨论了Redis的服务器端架构、数据存储和获取、协议和命令、高可用性方案、缓存机制以及监控和... 目录Redis介绍1. 基本概念2. 服务器端3. 存储和获取数据4. 协议和命令5. 高可用性6.

Redis的数据过期策略和数据淘汰策略

《Redis的数据过期策略和数据淘汰策略》本文主要介绍了Redis的数据过期策略和数据淘汰策略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录一、数据过期策略1、惰性删除2、定期删除二、数据淘汰策略1、数据淘汰策略概念2、8种数据淘汰策略

Redis存储的列表分页和检索的实现方法

《Redis存储的列表分页和检索的实现方法》在Redis中,列表(List)是一种有序的数据结构,通常用于存储一系列元素,由于列表是有序的,可以通过索引来访问元素,因此可以很方便地实现分页和检索功能,... 目录一、Redis 列表的基本操作二、分页实现三、检索实现3.1 方法 1:客户端过滤3.2 方法

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增

redis防止短信恶意调用的实现

《redis防止短信恶意调用的实现》本文主要介绍了在场景登录或注册接口中使用短信验证码时遇到的恶意调用问题,并通过使用Redis分布式锁来解决,具有一定的参考价值,感兴趣的可以了解一下... 目录1.场景2.排查3.解决方案3.1 Redis锁实现3.2 方法调用1.场景登录或注册接口中,使用短信验证码场

Redis 多规则限流和防重复提交方案实现小结

《Redis多规则限流和防重复提交方案实现小结》本文主要介绍了Redis多规则限流和防重复提交方案实现小结,包括使用String结构和Zset结构来记录用户IP的访问次数,具有一定的参考价值,感兴趣... 目录一:使用 String 结构记录固定时间段内某用户 IP 访问某接口的次数二:使用 Zset 进行

解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)

《解读Redis秒杀优化方案(阻塞队列+基于Stream流的消息队列)》该文章介绍了使用Redis的阻塞队列和Stream流的消息队列来优化秒杀系统的方案,通过将秒杀流程拆分为两条流水线,使用Redi... 目录Redis秒杀优化方案(阻塞队列+Stream流的消息队列)什么是消息队列?消费者组的工作方式每

Redis如何使用zset处理排行榜和计数问题

《Redis如何使用zset处理排行榜和计数问题》Redis的ZSET数据结构非常适合处理排行榜和计数问题,它可以在高并发的点赞业务中高效地管理点赞的排名,并且由于ZSET的排序特性,可以轻松实现根据... 目录Redis使用zset处理排行榜和计数业务逻辑ZSET 数据结构优化高并发的点赞操作ZSET 结

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ

Redis多种内存淘汰策略及配置技巧分享

《Redis多种内存淘汰策略及配置技巧分享》本文介绍了Redis内存满时的淘汰机制,包括内存淘汰机制的概念,Redis提供的8种淘汰策略(如noeviction、volatile-lru等)及其适用场... 目录前言一、什么是 Redis 的内存淘汰机制?二、Redis 内存淘汰策略1. pythonnoe