GEO类型的使用
一、应用场景
基础信息服务(Location- Based Service,LBS)
LBS应用访问的数据是和人或物关联的一组经纬度信息,而且要能查询相邻的经纬度范围。
例如:搜索“附近的餐馆”、在打车软件上叫车。
二、GEO的底层结构
GEO 类型的底层数据结构是用 Sorted Set 来实现的。
2.1 GeoHash编码方法
基本原理:“二分区间,区间编码”
比如:当我们要对一组经纬度进行GeoHash编码时,我们要先对经度和纬度分别编码,然后再把经纬度各自的编码组合成一个最终编码。
比如:我们要对 经度116.37 ,纬度39.86进行编码
对于一个地理位置来说,它的经度范围是 [-180,180]。GeoHash 编码会把一个经度值编码成一个 N 位的二进制值,我们来对经度范围[-180,180]做 N 次的二分区操作,其中 N 可以自定义。
我们将 116.37 做5次分区,如图所示
纬度的范围是[-90,90],我们将 39.86 做5次分区,如下图所示:
将经纬度各自的编码进行组合,如下图所示:
使用 GeoHash 编码后,我们相当于把整个地理空间分成了一个个方格,每个方格对应了 GeoHash 的一个分区。
比如:我们分别对经度和纬度做一次二分区,如下图所示:
这 4 个分区对应了 4 个方格,每个方格覆盖了一定范围内的经纬度值,分区越多,每个方格能覆盖到的地理空间就越小,也就越精准。我们把所有方格的编码值映射到一维空间时,相邻方格的 GeoHash 编码值基本也是接近的。
所以,我们使用 Sorted Set 范围查询得到的相近编码值,在实际的地理空间上,也是相邻的方格,这就可以实现 LBS 应用“搜索附近的人或物”的功能了。
2.2 如何操作 GEO 类型
- GEOADD 命令:用于把一组经纬度信息和相对应的一个 ID 记录到 GEO 类型集合中;
- GEORADIUS 命令:会根据输入的经纬度位置,查找以这个经纬度为中心的一定范围内的其他元素。当然,我们可以自己定义这个范围。
三、小结
GEO类型可以记录经纬度形式的地理位置信息,被广泛地应用在LBS服务中。GEO本身并没有设计新的底层数据结构,而是直接使用了 Sorted Set 集合类型。
GEO 类型使用 GeoHash 编码方法实现了经纬度到 Sorted Set 中元素权重分数的转换,这其中的两个关键机制就是对二维地图做区间划分,以及对区间进行编码。一组经纬度落在某个区间后,就用区间的编码值来表示,并把编码值作为 Sorted Set 元素的权重分数。这样一来,我们就可以把经纬度保存到 Sorted Set 中,利用 Sorted Set 提供的“按权重进行有序范围查找”的特性,实现 LBS 服务中频繁使用的“搜索附近”的需求。
GEO 属于 Redis 提供的扩展数据类型。扩展数据类型有两种实现途径:一种是基于现有的数据类型,通过数据编码或是实现新的操作的方式,来实现扩展数据类型,例如基于 Sorted Set 和 GeoHash 编码实现 GEO,以及基于 String 和位操作实现 Bitmap;另一种就是开发自定义的数据类型,具体的操作是增加新数据类型的定义,实现创建和释放函数,实现新数据类型支持的命令操作。