Redis:GEO 类型


这篇文章主要介绍 Redis 中 GEO 类型的相关知识

GEO 的底层结构

GEO 类型的底层数据结构是用 Sorted Set 来实现的。

Sorted Set 类型支持一个 key 对应一个 value 的记录模式,其中,key 就是 Sorted Set 中的元素,而 value 则是元素的权重分数。更重要的是,Sorted Set 可以根据元素的权重分数排序,支持范围查询。

问题:Sorted Set 元素的权重分数是一个浮点数(float 类型),而一组经纬度包含的是经度和纬度两个值,是没法直接保存为一个浮点数的,那具体该怎么进行保存呢?

GeoHash 的编码方法

这个方法的基本原理就是“二分区间,区间编码”。

当对一组经纬度进行 GeoHash 编码时,要先对经度和纬度分别编码,然后再把经纬度各自的编码组合成一个最终编码。

来看下经度和纬度的单独编码过程。

对于一个地理位置信息来说,它的经度范围是[-180,180]。GeoHash 编码会把一个经度值编码成一个 N 位的二进制值,对经度范围[-180,180]做 N 次的二分区操作,其中 N 可以自定义。在进行第一次二分区时,经度范围[-180,180]会被分成两个子区间:[-180,0) 和(0,180] (称之为左、右分区)。此时可以查看一下要编码的经度值落在了左分区还是右分区。如果是落在左分区,就用 0 表示;如果落在右分区,就用 1 表示。这样一来, 每做完一次二分区,我们就可以得到 1 位编码值。 然后再对经度值所属的分区再做一次二分区,同时再次查看经度值落在了二分区后的左分区还是右分区,按照刚才的规则再做 1 位编码。当做完 N 次的二分区后,经度值就可以用一个 N bit 的数来表示了。

对纬度的编码方式,和对经度的一样,只是纬度的范围是[-90,90]。

当一组经纬度值都编完码后,再把它们的各自编码值组合在一起,组合的规则是:最终编码值的偶数位上依次是经度的编码值,奇数位上依次是纬度的编码值,其中,偶数位 从 0 开始,奇数位从 1 开始。

用了 GeoHash 编码后,原来无法用一个权重分数表示的一组经纬度(116.37,39.86)就可以用 1110011101 这一个值来表示,就可以保存为 Sorted Set 的权重分数了。

使用 GeoHash 编码后,相当于把整个地理空间划分成了一个个方格,每个方格对应了 GeoHash 中的一个分区。

举个例子。把经度区间[-180,180]做一次二分区,把纬度区间[-90,90]做一次二分区, 就会得到 4 个分区。来看下它们的经度和纬度范围以及对应的 GeoHash 组合编码。

  • 分区一:[-180,0) 和[-90,0),编码 00;
  • 分区二:[-180,0) 和[0,90],编码 01;
  • 分区三:[0,180]和[-90,0),编码 10;
  • 分区四:[0,180]和[0,90],编码 11。

这 4 个分区对应了 4 个方格,每个方格覆盖了一定范围内的经纬度值,分区越多,每个方 格能覆盖到的地理空间就越小,也就越精准。我们把所有方格的编码值映射到一维空间 时,相邻方格的 GeoHash 编码值基本也是接近的。

所以,使用 Sorted Set 范围查询得到的相近编码值,在实际的地理空间上,也是相邻的方格,这就可以实现 LBS 应用“搜索附近的人或物”的功能了。

不过,我要提醒你一句,有的编码值虽然在大小上接近,但实际对应的方格却距离比较远。所以,为了避免查询不准确问题,可以同时查询给定经纬度所在的方格周围的 4 个或 8 个方格。

如何操作 GEO 类型

  • GEOADD 命令:用于把一组经纬度信息和相对应的一个 ID 记录到 GEO 类型集合中;
  • GEORADIUS 命令:会根据输入的经纬度位置,查找以这个经纬度为中心的一定范围内的其他元素。当然,我们可以自己定义这个范围。

参考资料

《Redis 45讲》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值