Redis-GEO地理位置

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis-GEO地理位置

 Redis 3.2版本一个重大的更新是新增了GEO地理位置相关的命令。

目前Redis对地理位置支持提供了一下6个命令:

    1. 1. geoadd:增加地理位置的坐标。
    2. 2. geodist:获取两个地理位置的距离。
    3. 3. geohash:获取地理位置的GeoHash值。
    4. 4. geopos:获取地理位置的坐标。
    5. 5. georadius:根据给定经纬度坐标获取指定范围内的地理位置集合。
    6. 6. georadiusbymember:根据给定地理位置获取指定范围内的地理位置集合。

    GeoHash基本原理

      1. GeoHash是一种地址编码,通过切分地图区域为小方块(切分次数越多,精度越高),它能把二维的经纬度编码成一维的字符串。
      2. 也就是说,理论上geohash字符串表示的并不是一个点,而是一个矩形区域,只要矩形区域足够小,达到所需精度即可

      编码过程

        1. 以经纬度(116.390639.92324)为例:

        2. 1.对于维度39.9232439.92324属于(0,90),所以取编码为1
        3. 然后再将(0,90)分成(0,45),(45,90)两个区间,而39.92324位于(0,45),所以编码为0
        4. 以此类推,直到精度符合要求为止,得到纬度编码为10111000110001111001

        5. 2.经度也用同样的算法,对(-180,180)依次细分,得到116.3906的编码为11010010110001000100

        6. 3.接下来将经度和纬度的编码合并,奇数位是纬度,偶数位是经度,得到编码1110011101001000111100000011010101100001

        7. 4.最后,用0-9b-z(去掉a, i, l, o)这32个字母进行base32编码,得到(39.92324,116.3906)的编码为wx4g0ec1

        8. 116.390639.92324)对应的地图位置就是http://geohash.org/wx4g0ec1,
        9. 降低一些精度,就会是http://geohash.org/wx4g0ec,
        10. 再降低一些精度,就会是http://geohash.org/wx4g0

        编码特性

          1. 不难看出这样的编码方式仅用一个字符串保存经纬度信息,并且精度由字符串从头到尾的长度决定,编码长度越长,精度越高。
          2. GeoHash值的前缀相同的位数越多,代表的位置越接近,可以方便索引。(反之不成立,位置接近的GeoHash值不一定相似).

          3. 但这种方案的缺点是:从geohash的编码算法中可以看出,靠近每个方块边界两侧的点虽然十分接近,但所属的编码会完全不同
          4. 实际应用中,需要通过去搜索环绕当前方块周围的8个方块来解决该问题。
          5. 除此之外,这个方案也无法直接得到距离,需要程序协助进行后续的排序计算

          Redis Geo命令实现

            1. Redis将地理位置的52GeoHash值作为有序集合的score,将地理位置存放在有序集合中进行保存。

            2. 后续按位置搜索时,依据GeoHash的特性搜索当前方块与环绕当前方块的8个方块来搜索目标位置集合。

            1.GEOADD

              1. 命令:GEOADD key longitude latitude member [longitude latitude member ...]
              2. 命令描述:将指定的地理空间位置(纬度、经度、名称)添加到指定的key
              3. 返回值:添加到sorted set元素的数目,但不包括已更新score的元素。
                1. Redis中接受的有效的精度范围为-180180度,有效维度范围为-85.0511287885.05112878(靠近南北极的一小块地方是无法生成索引的)。
                  • GEOADD  实现方式
                    1. Redis内部使用有序集合来保存key,每一个memberscore大小为一个52位的Geohash值(double类型精度为52位)。
                    2. 实际上Redis内部实现的时候就是将GEOADD命令转换成ZADD命令来实现的
                    3. (这也解释了为什么没有专门的georem命令,地理位置信息是通过使用ZREM命令来删除成员。)

                    2.GEODIST 

                      1. 命令:GEODIST key member1 member2 [unit]
                      2. 命令描述:
                      3. 返回两个给定位置之间的距离。如果两个位置之间的其中一个不存在,那么命令返回空值。指定单位的参数 unit 必须是以下单位的其中一个:
                        • m 表示单位为米。
                        • km 表示单位为千米。
                        • mi 表示单位为英里。
                        • ft 表示单位为英尺。
                            • GEODIST 实现方式
                              1. 使用WGS84坐标系统,计算距离时使用Haversine公式。由于地球并不是严格标准的,计算出来的距离有最大约0.5%的误差。

                              3.GEOPOS 

                                1. 命令:GEOPOS key member [member ...]
                                2. 命令描述:key里返回所有给定位置元素的位置(经度和纬度)
                                3. 返回值:GEOPOS 命令返回一个数组,数组中的每个项都由两个元素组成: 
                                4. 第一个元素为给定位置元素的经度,而第二个元素则为给定位置元素的纬度。当给定的位置元素不存在时,对应的数组项为空值。

                                4.GEOHASH 

                                  1. 命令:GEOHASH key member [member ...]
                                  2. 命令描述:返回一个或多个位置元素的Geohash表示。通常使用表示位置的元素使用不同的技术,使用Geohash位置52点整数编码。
                                  3. 由于编码和解码过程中所使用的初始最小和最大坐标不同,编码的编码也不同于标准。此命令返回一个标准的Geohash
                                  4. 返回值:一个数组,数组的每个项都是一个 geohash 命令返回的 geohash 的位置与用户给定的位置元素的位置一一对应。
                                    • GEOHASH 实现方式
                                      1. Redis在内部生成有序集合成员score时的geohash值与标准的算法略有差异(Redis内部使用-85,85作为维度范围,标准使用-90,90)。

                                      2. 这个命令返回的是标准值,与https://en.wikipedia.org/wiki/Geohash中标准算法和geohash.org网站的结果一致。

                                      5.GEORADIUS

                                        1. 命令:GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD][WITHDIST][WITHHASH][COUNT count]
                                        2. 命令描述:
                                        3. 以给定的经纬度为中心,返回键包含的位置元素当中,与中心的距离不超过给定最大距离的所有位置元素。

                                        4. 范围可以使用以下其中一个单位:
                                          1. m 表示单位为米。
                                          2. km 表示单位为千米。
                                          3. mi 表示单位为英里。
                                          4. ft 表示单位为英尺。
                                            1. 在给定以下可选项时,命令会返回额外的信息:
                                              1. WITHDIST:在返回位置元素的同时,将位置元素与中心之间的距离也一并返回。距离的单位和用户给定的范围单位保持一致。
                                              2. WITHCOORD:将位置元素的经度和维度也一并返回。
                                              3. WITHHASH:52位有符号整数的形式,返回位置元素经过原始 geohash 编码的有序集合分值。这个选项主要用于底层应用或者调试,实际中的作用并不大。
                                                1. 命令默认返回未排序的位置元素。通过以下两个参数,用户可以指定被返回位置元素的排序方式:
                                                  1. ASC:根据中心的位置,按照从近到远的方式返回位置元素。
                                                  2. DESC:根据中心的位置,按照从远到近的方式返回位置元素。
                                                    1. 在默认情况下, GEORADIUS 命令会返回所有匹配的位置元素。虽然用户可以使用 COUNT <count>选项去获取前 N 个匹配元素,但是因为命令在内部可能会需要对所有被匹配的元素进行处理,所以在对一个非常大的区域进行搜索时,即使只使用 COUNT 选项去获取少量元素,命令的执行速度也可能会非常慢。但是从另一方面来说,使用 COUNT 选项去减少需要返回的元素数量,对于减少带宽来说仍然是非常有用的。

                                                    2. 返回值:
                                                      1. 在没有给定任何 WITH 选项的情况下,命令只会返回一个像[“NewYork”,”Milan”,”Paris”]这样的线性(linear)列表。
                                                      2. 在指定了 WITHCOORD WITHDIST WITHHASH 等选项的情况下,命令返回一个二层嵌套数组,内层的每个子数组就表示一个元素。
                                                        1. 在返回嵌套数组时,子数组的第一个元素总是位置元素的名字。至于额外的信息,则会作为子数组的后续元素,按照以下顺序被返回:
                                                          1. 以浮点数格式返回的中心与位置元素之间的距离,单位与用户指定范围时的单位一致。
                                                          2. geohash 整数。
                                                          3. 由两个元素组成的坐标,分别为经度和纬度。
                                                                  • GEORADIUS实现方式
                                                                    1. GeoHash值的前缀相同的位数越多,代表的位置越接近,可以方便索引。但反之不成立,位置接近的GeoHash值不一定相似。

                                                                    2. 靠近每个方块边界两侧的点虽然十分接近,但所属的编码会完全不同。实际应用中,需要通过去搜索环绕当前方块周围的8个方块来解决该问题。

                                                                    3. 搜索的时候会检查挡墙方块+8个覆盖整个搜索半径的区域,不断的去除geohash的低位,直到这9个方块能覆盖搜索半径位置。再一次搜索计算每个位置的距离。

                                                                    6.GEORADIUSBYMEMBER 

                                                                      1. 命令:GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD][WITHDIST][WITHHASH][COUNT count]
                                                                      2. 命令描述:这个命令和 GEORADIUS 命令一样,都可以找出位于指定范围内的元素,但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的。



                                                                      相关实践学习
                                                                      基于Redis实现在线游戏积分排行榜
                                                                      本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
                                                                      云数据库 Redis 版使用教程
                                                                      云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
                                                                      目录
                                                                      相关文章
                                                                      |
                                                                      6月前
                                                                      |
                                                                      存储 NoSQL 定位技术
                                                                      Redis Geo:掌握地理空间数据的艺术
                                                                      Redis Geo:掌握地理空间数据的艺术
                                                                      492 0
                                                                      |
                                                                      存储 NoSQL Java
                                                                      |
                                                                      29天前
                                                                      |
                                                                      存储 NoSQL 定位技术
                                                                      Redis GEO
                                                                      10月更文挑战第19天
                                                                      32 1
                                                                      |
                                                                      4月前
                                                                      |
                                                                      存储 NoSQL 定位技术
                                                                      如何在Redis中快速推算两地之间的距离?——Geo篇
                                                                      Redis 3.2 引入Geo类型,支持地理位置数据存储和计算,如距离和范围查询。使用`GEOADD`将城市经纬度添加至`zset`中,通过`GEOPOS`获取坐标,`GEODIST`计算距离,`GEORADIUS`查找指定范围内的城市。Redis的Geo功能适用于快速的地理位置服务,如附近搜索和配送范围分析。利用`ZSET`操作可增删位置数据,简化地理空间应用开发。
                                                                      86 0
                                                                      |
                                                                      6月前
                                                                      |
                                                                      SQL NoSQL Java
                                                                      Redis数据类型 Hash Set Zset Bitmap HyperLogLog GEO
                                                                      Redis数据类型 Hash Set Zset Bitmap HyperLogLog GEO
                                                                      60 0
                                                                      |
                                                                      6月前
                                                                      |
                                                                      存储 NoSQL API
                                                                      Redis入门到通关之GEO实现附近的人功能
                                                                      Redis入门到通关之GEO实现附近的人功能
                                                                      62 0
                                                                      |
                                                                      6月前
                                                                      |
                                                                      存储 NoSQL 定位技术
                                                                      Redis Geo:解锁地理位置数据的新可能性
                                                                      Redis Geo:解锁地理位置数据的新可能性
                                                                      207 0
                                                                      |
                                                                      存储 NoSQL 搜索推荐
                                                                      Redis地理位置和搜索:实现位置服务和简单搜索引擎
                                                                      本篇深入研究了Redis的地理位置数据类型及其应用,以及如何基于Redis构建一个简单的搜索引擎。我们首先介绍了地理位置数据类型(Geo),展示了如何使用它来存储位置信息,并进行位置查询、距离计算以及附近位置搜索。通过代码示例,读者可以了解如何利用地理位置数据类型实现位置服务。
                                                                      526 0
                                                                      |
                                                                      6月前
                                                                      |
                                                                      NoSQL Java Redis
                                                                      Spring Boot和Redis Geo实现附近的人【redis实战 三】
                                                                      Spring Boot和Redis Geo实现附近的人【redis实战 三】
                                                                      230 0
                                                                      |
                                                                      6月前
                                                                      |
                                                                      存储 NoSQL Redis
                                                                      【Redis】Redis 高级数据类型Bitmaps、HyperLogLog、GEO
                                                                      【Redis】Redis 高级数据类型Bitmaps、HyperLogLog、GEO
                                                                      75 0
                                                                      【Redis】Redis 高级数据类型Bitmaps、HyperLogLog、GEO