近水楼台——GeoHash
Redis在3.2版本后增加了地理位置Geo模块,意味着我们可以使用Redis来实现类似摩拜单车的"附近的Mobile"类似功能
GeoHash算法
将二维的经纬度数据映射到一维的整数,地图元素的左边编码,通过这个整数可以还原出元素的坐标,整数越长,还原出来的坐标值的损失程度就越小。GeoHash算法会对这个整数做一次base32编码,变成一个字符串。经纬度使用52位的整数进行编码,放进了zset里面。zset的value是元素的key,score是GeoHash的52位整数值
内部是一个zset的数据结构,通过zset的score排序得到坐标附近的其他元素,通过score还原成坐标值就得到元素的原始坐标。
Geo指令的基本用法
增加
geoadd company 116.48105 39.996794 juejin
geoadd company 116.48105 39.996794 juejin 116.334255 40。027400 xiaomi
距离
geodist用来计算两个元素之间的距离,携带集合名词、两个名词和距离单位
距离单位可以是m、km、ml、ft(米,千米,英里、尺)
geodist company juejin xiaomi km
获取元素位置
geopos指令可以获取集合中任意元素的经纬度坐标,可以一次获取多个
获取出来的元素与geoadd进去的坐标有少许误差,因为二维坐标进行一维映射是有损的,会出现较小的误差
geoops company juejin xiaomi
获取元素的hash值
GeoHash可以获取元素的经纬度编码字符串,它是base32编码。
geohash company juejin
附近的公司
georadiusbymember指令是最关键的指令之一,可以用来查询指定元素附近的其他元素
# 范围20公里以内最多3个元素按距离正排,它不会排除自身
georadiusbymember company juejin 20 km count 3 asc
# 范围20公里以内最多3个元素距离倒排
georadiusbymember company juejin 20 km count 3 desc
# 三个可选参数withcoord withdist withhash,withdist 可以用来显示距离
georadiusbymember company juejin 20 km withcoord withdist withhash count 3 asc
geradius 根据坐标值来查询附近的元素的指令,和georadiusbymember基本一致,唯一的差别是将目标元素改成经纬度坐标值
georadiusbymember company 116.514202 39.905409 20 km withcoord withdist withhash count 3 asc
注意事项
一个地图的数据量是很庞大的,将它们放入在一个zset集合中,会对节点数据迁移产生影响。所以Geo数据使用单独的Redis实例部署,不适用集群环境。如果数据量过亿,甚至更多,需要对Geo数据进行拆分,按国家拆分,按省或者按区