Redis Geo 指令实现附近的人功能

前言

Redis 在 3.2 版本以后增加了地理位置 Geo 模块,意味着我们可以使用 Redis 来实现类似摩拜单车的“附近的共享单车”和微信“附近的人”这样的功能了。Redis 中 Geo 指令使用的是业界比较通用的地理位置距离排序算法 GeoHash 。

GeoHash 算法简介

GeoHash算法将二维的经纬度数据映射到一维的整数,这样所有的元素都将挂载到一条线上,距离靠近的二维坐标映射到一维后的点之间距离也会很接近。当我们想要计算“附近的人”时,首先将目标位置映射到这条线上,然后在这个一维的线上获取附近的点就行了。
它将整个地球看成一个二维平面,然后划分成了一系列正方形的方格,就好比围棋棋盘。所有的地图元素坐标都将被放置于唯一的方格中。方格越小,坐标越精确。然后对这些方格进行整数编码,越是靠近的方格编码越是接近。那如何编码呢? 个最简单的方案就是切蛋糕法。
在这里插入图片描述

如上图所示,设想一个正方形的蛋糕、摆在你面前,二刀下去均分分成四块小正方形,这四个小正方形可以分别标记为 00、 01、 10、 11 共四个二进制整数 。然后对每一个小正方形继续用二刀法切割,这时每个小小正方形就可以使用 4bit 的 二进制整数表示。然后继续切下去,正方形就会越来越小,二进 制整数也会越来越长,精确度就会越来越高。上面的例子中使用的是二刀法,真实算法中还会有很多其他刀法 ,最终编码出来的整数数字也都不一样。编码之后,每个地图元素的坐标都将变成一个整数,通过这个整数可以还原出元素的坐标,整数越长,还原出来的坐标值的损失程度就越小。对于“附近的人” 这个功能而言,损失的一点精确度可以忽略不计。
GeoHash算法会继续对这个整数做一次 base32编码(0~ 9, a~ z,去掉 a、 i、l、 o 四个字母)变成一个字符串。在 Redis 里面,经纬度使用 52 位的整数进行编码, 放进了 zset 里面, zset 的 value 是元素的 key, score 是 GeoHash 的 52 位整数值 。 zset 的 score 虽然是浮点数,但是对于 52 位的整数值,它可以无损存储。
在使用 Redis 进行 Geo 查询时,我们要时刻想到它的内部结构实际上只是一个 zset (skiplist)。通过 zset 的 score 排序就可以得到坐标附近的其他元素(实际情况要复杂一些,不过这样理解足够了),通过将 score 还原成坐标值就可以得到元素的原始坐标。

常用命令

  • geoadd
    在这里插入图片描述
  • geodist
    计算 2 个元素之间的距离
    在这里插入图片描述
  • geopos
    获取集合中任意元素的经纬度坐标。由于 GeoHash 对二维坐标进行的一维映射是有损的,所以此处获取的坐标和 geoadd 进去的有少许误差。
    在这里插入图片描述
  • geohash
    获取元素的经纬度编码字符串
    在这里插入图片描述
  • georadiusbymember
    查询指定元素附近的其他元素
    在这里插入图片描述
  • georadius
    根据坐标值查询附近的元素
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值