前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >redis地理位置GEO的实现原理

redis地理位置GEO的实现原理

作者头像
程序员小饭
发布2022-03-03 11:27:49
1.4K0
发布2022-03-03 11:27:49
举报
文章被收录于专栏:golang+phpgolang+php

Geo的基本操作

redis地理位置信息geo的基本操作和使用咱们之前已经聊过,可以看看这篇文章 微信附近的人,用redis也能实现?

GEO的底层结构

和zset的相似之处

首先我们不妨大胆来猜一猜GEO的底层结构是什么样的?首先一个key里面得保存各个member和经纬度,而且经纬度还必须得能够排序,所以我们发现这个结构其实和redis的zset结构其实挺像的,唯一的区别可能在于zset只有一个score,而GEO有经度和纬度,所以我们只需要解决能用一个score来保存经度和纬度就可以解决问题了。其实redis的确也是这么做的,而且GEO的底层其实就是在zset的结果上做了一层封装,所以按照严格意义上讲GEO并不是redis的一种新的数据类型。

GEO的hash编码方式

为了能高效地对经纬度进行比较,Redis 采用了业界广泛使用的 GeoHash 编码方法,这 个方法的基本原理就是“二分区间,区间编码”。

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

首先,我们来看下经度和纬度的单独编码过程。我们以经纬度 116.37,39.86为例 首先看经度 116.37

  • 第一次二分区操作,把经度区间[-180,180]分成了左分区[-180,0) 和右分区 [0,180],此时,经度值 116.37 是属于右分区[0,180],所以,我们用 1 表示第一次二分区 后的编码值。
  • 把经度值 116.37 所属的[0,180]区间,分成[0,90) 和[90, 180]。此时,经度值 116.37 还是属于右分区[90,180],所以,第二次分区后的编码值仍然 为 1。等到第三次对[90,180]进行二分区,经度值 116.37 落在了分区后的左分区[90, 135) 中,所以,第三次分区后的编码值就是 0。
  • 按照这种方法,做完 5 次分区后,我们把经度值 116.37 定位在[112.5, 123.75]这个区 间,并且得到了经度值的 5 位编码值,即 11010。这个编码过程如下表所示:

对纬度的编码方式,和对经度的一样,只是纬度的范围是[-90,90],下面这张表显示了对 纬度值 39.86 的编码过程。

我们刚刚计算的经纬度(116.37,39.86)的各自编码值是 11010 和 10111,组合之后, 第 0 位是经度的第 0 位 1,第 1 位是纬度的第 0 位 1,第 2 位是经度的第 1 位 1,第 3 位是纬度的第 1 位 0,以此类推,就能得到最终编码值 1110011101,如下图所示

用了 GeoHash 编码后,原来无法用一个权重分数表示的一组经纬度(116.37,39.86)就 可以用 1110011101 这一个值来表示,就可以保存为 Sorted Set 的权重分数了。最后根据上述得到的二进制值,以5位为一组,进行base32编码

最后获得的结果就是一组经纬度的geohash值。

地理位置二维转一维

上文讲了GeoHash的计算步骤,仅仅说明是什么而没有说明为什么?为什么分别给经度和维度编码?为什么需要将经纬度两串编码交叉组合成一串编码?本节试图回答这一问题。

如下图所示,我们将二进制编码的结果填写到空间中,当将空间划分为四块时候,编码的顺序分别是左下角00,左上角01,右下脚10,右上角11,也就是类似于Z的曲线,当我们递归的将各个块分解成更小的子块时,编码的顺序是自相似的(分形),每一个子块也形成Z曲线,这种类型的曲线被称为Peano空间填充曲线。

这种类型的空间填充曲线的优点是将二维空间转换成一维曲线(事实上是分形维),对大部分而言,编码相似的距离也相近, 但Peano空间填充曲线最大的缺点就是突变性,有些编码相邻但距离却相差很远,比如0111与1000,编码是相邻的,但距离相差很大。

所以,为了避免查询不准确问题,我们可以同时查询给定经纬度所在的方格周围的 4 个或 8 个方格。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-09-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员养成日记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Geo的基本操作
  • GEO的底层结构
    • 和zset的相似之处
      • GEO的hash编码方式
        • 地理位置二维转一维
        相关产品与服务
        云数据库 Redis
        腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档