Redis三种特殊数据类型——Geospatial地理空间

Redis三种特殊数据类型:bitmaps位图、hyperloglog基数统计 和 geospatial 地理空间

 一、介绍

Redis GEO 用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。主要应用于:附近的人、定位

二、数据结构

底层是使用zset进行实现的,zset的命令也可以直接使用。Redis GEO 使用 geohash 来保存地理位置的坐标。

三、操作命令

命令功能描述
geoadd添加地理位置往key中添加地理位置的坐标(经度、纬度、位置名称)
geopos查询经纬度返回指定成员的经纬度参数
geodist查询距离返回指定2个成员之间的直线距离(默认单位:米)
georadius附近的人指定经纬度为中心,返回该中心指定半径内的成员
georadiusbymember附近的人等同georadius,上述是指定经纬度,这个是指定成员附近的人
geohash地理位置坐标返回Redis GEO 的地理位置的坐标

1、geoadd   向key中添加指定的地理位置:经度、纬度、位置名称    (添加位置)

语法:geoadd key longitude1 latitude1 member1  [longitude2 ...]

# 添加北京(经纬度)、上海(经纬度)的位置到名为mycity的key中
127.0.0.1:6379> geoadd mycity 116.40 39.9 beijing 121.47 31.23 shanghai
(integer) 2

# 底层是zset存储方式,可以直接用zrange查询索引区间的所有成员
127.0.0.1:6379> zrange mycity 0 -1
1) "guangzhou"
2) "nanchang"
3) "hangzhou"
4) "shanghai"
5) "nanjing"
6) "shijiazhuang"
7) "beijing"

注意:

  • longitude经度:从-180度到180度
  • latitude纬度:从-85.05112878度到85.05112878度。

2、geopos   返回指定成员的经纬度参数    (查询位置)

语法:geopos key member1 member2...

# 底层是zset存储方式,可以直接用zrange查询索引区间的所有成员
127.0.0.1:6379> zrange mycity 0 -1
1) "guangzhou"
2) "nanchang"
3) "hangzhou"
4) "shanghai"
5) "nanjing"
6) "shijiazhuang"
7) "beijing"

# 查询上海、北京、成都的经度纬度
127.0.0.1:6379> geopos mycity shanghai beijing chengdu
1) 1) "121.47000163793563843"
   2) "31.22999903975783553"
2) 1) "116.39999896287918091"
   2) "39.90000009167092543"
3) (nil)  # 不存在mycity中的城市位置,则返回nil

3、geodist   返回指定2个成员之间的距离   (查询位置)

语法:geodist key member1 member2... [m|km|ft|mi 单位可选]

# 返回上海到北京的直线距离,单位为:km千米
127.0.0.1:6379> geodist mycity shanghai beijing km
"1067.3788" 

# 返回上海到成都的直线距离,成都在mycity中不存在,返回nil
127.0.0.1:6379> geodist mycity shanghai chengdu
(nil)

注意1:指定单位的参数 unit 必须是以下单位的其中一个

  • m 表示单位为米(默认值)
  • km 表示单位为千米
  • mi 表示单位为英里
  • ft 表示单位为英尺

注意2:通过搜索得知,空中距离为1069千米,上述返回的是1067,根据航空路线,飞机场所在的位置,得出的距离都会产生差异,其次区域的位置也是不同的,例如上海静安区、黄浦区

4、georadius   以给定的经纬度为中心,返回指定半径内的成员   (查询附近的人)

语法:georadius key longitude latitude radius [m|km|ft|mi 单位可选]

# 返回经度120,纬度30 的周边500千米内的成员
127.0.0.1:6379> georadius mycity 120 30 500 km
1) "nanchang"
2) "hangzhou"
3) "shanghai"
4) "nanjing"

# 100千米内的成员
127.0.0.1:6379> georadius mycity 120 30 100 km
1) "hangzhou"

# 200千米内的成员
127.0.0.1:6379> georadius mycity 120 30 200 km
1) "hangzhou"
2) "shanghai"

# 200千米内的成员名称、120,30与该成员位置的直线距离数、经纬度参数
127.0.0.1:6379> georadius mycity 120 30 200 km withdist withcoord
1) 1) "hangzhou"
   2) "30.8146"  # 直线距离
   3) 1) "120.1600000262260437"  
      2) "30.2400003229490224"
2) 1) "shanghai"
   2) "196.2512"
   3) 1) "121.47000163793563843"
      2) "31.22999903975783553"

# 返回1个 200千米内的成员名称 (count num 指定显示num个)
127.0.0.1:6379> georadius mycity 120 30 200 km count 1
1) "hangzhou"

5、georadiusbymember   指定某成员为中心,返回指定半径内的成员   (查询附近的人)

语法:georadiusbymember key longitude latitude radius [m|km|ft|mi]

# 返回上海的周边300千米内的成员名称
127.0.0.1:6379> georadiusbymember mycity shanghai 300 km
1) "hangzhou"
2) "shanghai"
3) "nanjing"

# 200千米内的成员名称
127.0.0.1:6379> georadiusbymember mycity shanghai 200 km
1) "hangzhou"
2) "shanghai"

# 返回上海的周边200千米内的成员名称、经纬度参数
127.0.0.1:6379> georadiusbymember mycity shanghai 200 km withcoord
1) 1) "hangzhou"
   2) 1) "120.1600000262260437"
      2) "30.2400003229490224"
2) 1) "shanghai"
   2) 1) "121.47000163793563843"
      2) "31.22999903975783553"

6、geohash   获取一个或多个地理位置的hash值   (返回坐标hash值)

语法:geohash key member1 member2...

# 返回上海、北京、杭州的坐标hash
127.0.0.1:6379> geohash mycity shanghai beijing hangzhou
1) "wtw3sj5zbj0"
2) "wx4fbxxfke0"
3) "wtmkn31bfb0"

—————将二维的经纬度转换为一维的字符串,字符串越相似,表示距离位置越近

注意:该命令返回11位字符的 Geohash字符串!

四、geohash原理分析

  • 如何唯一表示地球上的一块空间?
  • 如何将地球切分成大小近似的区块,并支持不同粒度的表示?

为了解决上述两个问题,我们需要三个步骤。

  1. 第一步,将三维地球变成二维;
  2. 第二步,将二维再转成一维;
  3. 最后一步,将一维表示成二进制码存储。

1、如何将三维变二维?

地球纬度区间是[-90,90],经度区间是[-180,180]。 将它展开想象长一个矩形为

三维变二维

2、如何将二维变一维?

通过上述方法,将地球的表面转换成二维空间的平面。二维空间可以切割出很多正方形。

如何表示这个正方形呢?最简单的方法是在平面上进行遍历。每遍历到一个点,就给它标注一个值,比如00、01、10、11,随着二进制数字增加,相当于遍历面上不同的位置。

二维变一维


图一:当将空间划分为四块时候,编码的顺序分别是左下角00,左上角01,右下脚10,右上角11,也就是类似于Z的曲线。

图二:继续将各个块分解成更小的子块时可标识更小的空间范围,如从0000开始到1111,编码的顺序是自相似的(分形),每个子快也形成Z曲线,这种类型的曲线被称为Peano空间填充曲线。

2、如何将一维表示成二进制码存储?

Geohash 也有几种编码形式,常见的有2种,base 32 和 base 36。 会将落到网格中的二进制数据编码成字符串

五、总结

Redis GEO的实现原理背后核心是geohash,使用geohash将二维的经纬度数据编码成一维数据,再使用B树索引快速查找出需要的数据。


 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值