Redis数据结构之GEO
未完待续
1.概述
移动互联网时代LBS应用越来越多,交友软件中附近的人、外卖软件中附近的美食店铺等,那这种附近各种形形色色的地址位置选择是如何实现的?
地球上的地理位置是使用二维的经纬度表示,经度范围(-180,180],纬度范围(-90,90],只要我们确定一个点的经纬度就可以取得它在地球上的位置。
例如滴滴打车,最直观的操作就是实时记录更新各个车的位置,然后当我们要找车时,在数据库中查找距离我们(x0, y0)附近r公里范围内部的车辆,使用如下SQL即可:
select taxi from position where x0 - r < x < x0 + r and y0 - r < y < y0 + r
但是这样会有查询性能问题,如果并发高数据量大,这种查询会影响数据库性能,而且这个查询到的是一个矩形范围,而不是以点为中心r公里为半径的圆形范围。
为了解决这一问题,Redis在3.2版本之后支持了GEO这一数据结构,GEO主要用于存储地理位置信息,并对存储的信息进行操作,包括:
- 添加地理位置的坐标
- 获取地理位置的坐标
- 计算两个位置之间的距离
- 根据用户给定的经纬度坐标来获取指定范围内的地理位置集合
2.常用命令
2.1 GEOADD
多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的key中
GEOADD key longitude latitude member [longitude latitude member ...]
经纬度可以通过百度地图坐标拾取获得:https://api.map.baidu.com/lbsapi/getpoint/index.html
例如:
127.0.0.1:6379> GEOADD city 116.515802 39.951893 "北京朝阳站" 116.385671 39.871141 "北京南站"
(integer) 1
GEO的本质是Set的子类型:
127.0.0.1:6379> type city
zset
127.0.0.1:6379> zrange city 0 -1
1) "\xe5\x8c\x97\xe4\xba\xac\xe5\x8d\x97\xe7\xab\x99"
2) "\xe5\x8c\x97\xe4\xba\xac\xe7\xab\x99"
3) "\xe5\x8c\x97\xe4\xba\xac\xe6\x9c\x9d\xe9\x98\xb3\xe7\xab\x99"
127.0.0.1:6379>
中文乱码的解决:修改客户端参数
127.0.0.1:6379> quit
[root@localhost bin]# ./redis-cli --raw
127.0.0.1:6379> auth lzj
OK
127.0.0.1:6379> zrange city 0 -1
北京南站
北京站
北京朝阳站
2.2 GEOPOS
用于从给定的key里返回所有指定名称(member)的位置(经度和纬度),不存在的返回nil
GEOPOS key member [member ...]
例
127.0.0.1:6379> GEOPOS city 北京站
116.43414348363876343
39.90890963654599233
127.0.0.1:6379> GEOPOS city 北京朝阳站
116.51580065488815308
39.95189343796607062
2.3 GEODIST
返回两个给定位置之间的距离
m
米km
千米ft
英尺mi
英里
GEODIST key memberl member2 [m|km|ft|mi]
例:高铁站之间的距离
127.0.0.1:6379> GEODIST city 北京站 北京朝阳站 km
8.4477
127.0.0.1:6379> GEODIST city 北京南站 北京朝阳站 km
14.2804
127.0.0.1:6379> GEOADD city 117.978057 40.893571 "承德南站"
1
127.0.0.1:6379> GEODIST city 承德南站 北京朝阳站 km
162.1702
2.4 GEORADIUS
以给定的经纬度为中心,返回与中心的距离不超过给定最大距离的所有位置元素,说白了就是根据半径检索附近的POI(兴趣点)
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STORE key] [STOREDIST key]
key
: 存储地理位置的有序集合键名longitude latitude
: 中心点的经度和纬度radius
: 半径距离m|km|ft|mi
: 距离单位(米、千米、英尺、英里)WITHCOORD
: 将位置元素的经度和维度也一并返回。WITHDIST
: 在返回位置元素的同时,将位置元素与中心之间的距离也一并返回, 距离的单位和用户给定的范围单位保持一致WITHHASH
: 以52位有符号整数的形式,返回位置元素经过原始geohash编码的有序集合分值,这个选项主要用于底层应用或者调试,实际中的作用并不大COUNT count
: 限制返回结果数量ASC|DESC
: 按距离排序(升序/降序)STORE key
: 将结果存储为有序集合(存储 geohash)STOREDIST key
: 将结果存储为有序集合(存储距离)
例:以朝阳公园(116.486817,39.953201)为圆心,10千米为半径,搜索city中满足条件的地点
127.0.0.1:6379> GEORADIUS city 116.486817 39.953201 10 km WITHCOORD WITHDIST
北京站
6.6672
116.43414348363876343
39.90890963654599233
北京朝阳站
2.4755
116.51580065488815308
39.95189343796607062
2.5 GEORADIUSBYMEMBER
跟GEORADIUS类似
2.6 GEOHASH
返回一个或多个位置元素的GEOHASH表示,比位数众多的小数更好处理
GEOHASH算法生成的base32编码值,主要分为三步:
1.将三维的地球变为二维的坐标
2.将二维的坐标转换为一维的点块
3.最后将一维的点块转换为二进制再通过base32编码
GEOHASH key member [member ...]
例
127.0.0.1:6379> GEOHASH city 北京站 北京南站 北京朝阳站
wx4g190y0p0
wx4fb6m6nx0
wx4g73h0wu0
"如果文章对您有帮助,可以请作者喝杯咖啡吗?"

微信支付

支付宝