Redis高级数据结构(geohash)——Redis深度历险笔记6

geohash是关于划分经纬度的,它跟R树是挺不一样的。
R树是分散的,多维的,由底下的点聚集成树索引,geohash是把经纬度这两维度压缩到一个维度上。

那是如何将2维压缩到1维的呢?

例如,一个点(x,y)在一个象限内,x轴上正为1,负为0。y轴也是,正为1,负为0。这样,就将一个平面划分成4个方位,可以用11,10,00,01这样的二进制一维数来表示点所处的二维方位。

那这个算法是如何进行的呢。
众所周知,经度是-180到180,维度是-90到90,我们设定0为负,1为正。

假如一个点的值为(-100,30)

我们需要对经度跟维度分别计算其方位的2进制。

(-180,0)为0,(0,180)为1
因为值为-100,所以第一个值为0。
接下去继续分
(-180,-90)为0,(-90,0)为1,因为值为-100,则第二个值还是为0。
这样可以无限二分法下去。
具体几位,由需要的精度确定。

维度也同理,计算出一串二进制串。

这两条串长度相同。需要将它们合并起来,那该如何合并呢。

经度跟维度相间轮流合并,经度占偶数位(起始0位),维度占奇数位。

这样就得到了一个新的二进制。

会对这二进制做一次base32的编码(就是5位为一组)

redis里的geohash呢?

在redis里,geohash是用52位整数进行编码,放进一个zset的结构里,排序集合。

但是实际上不是这么简单,不是说在一个格子里,两个点就是最近的,如果A点在边界,B在一个格子里的对面的边界,那AB两个点的距离还不如另外的格子里的点近呢。

而且geohash算法还会有曲线跃迁,比如第二象限跟第四象限,虽然差1,但是他们距离还是挺远的。

这两点都需要考量。

使用

不过我们使用的话,就不用想那么多了。

geoadd company 116.48105 39.996794 juejin
//命令 名称 经度 维度 内部名称

因为内部本身就是一个zset,则其他的命令跟zset的命令差不多。这边就不赘述了。

geodis company juejin meituan km
//查询两个元素直接的距离 

最重要的

还是查询一个点附近的点,这个功能。

georadius company 116.514202 39.905409 20 km withdist count 3 asc

查找company集合内,(116.514202 ,39.905409)20km内的,正序排名前3的元素

最后的提示

因为geohash是存在zset结构内的,其实不太会被频繁的变动,一个地图的各种数据,可能有几千万条,就不太合适布置在集群里,因为迁移会很慢。

建议是使用redis单独的实例部署。

上一篇:GeoHash原理以及代码实现


下一篇:GeoHash