GEO
介绍
Redis GEO 是Redis3.2版本新增的数据类型,主要用于存储地理位置信息,并对存储的信息进行操作。
在日常生活中,我们越来越依赖搜索“附件的餐馆”、在打车软件上叫车,这些都离不开基于位置信息服务(Location-Based Service,LBS)的应用。LBS应用访问的数据时和人或物关联的一组经纬度信息,而且要能查询相邻的经纬度范围,GEO就非常适合应用在LBS服务的场景中。
内部实现
GEO 本身并没有新的底层数据结构,而是直接使用了Sorted Set集合类型。
GEO类型使用GeoHash编码方法实现了经纬度到Sorted Set中元素权重分数的转换,这其中两个关键机制就是[对二维地图做区间划分]和[对区间进行编码]。一组经纬度落在某个区间后,就用区间的编码值来表示,并把编码值作为Sorted Set元素的权重分数。
这样一来,我们就可以把经纬度保存到Sorted Set中,利用Sorted Set提供的“按权重进行有序范围查找”的特性,实现LBS服务中频繁使用的“搜索附近”的需求
常用命令
# 存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的key中
GEOADD key longitude latiude member [longitude latitude member ...]
# 从给定的key里返回所有指定名称(member)的位置(经度和纬度),不存在返回nil
GEOPOS key member [member ...]
# 返回两个定位置之间的距离
GEODIST key member1 member2 [m|km|ft|mi]
# 根据用户给定的经纬度坐标来获取指定范围内的地理位置集合。
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count] [ASC|DESC] [STOREDIST key]
应用场景
滴滴叫车
这里以滴滴叫车的场景为例,介绍下具体如何使用GEO命令:GEOADD和GEORADIUS这两命令。
假设车辆ID是33,经纬度位置是(116.034579,39.0304052),我们可以用一个GEO集合保存所有车辆的经纬度,集合key是cars:locations.
执行下面这个命令,就可以把ID号为33的车辆的当前经纬度位置存入GEO集合中:
GEOADD cars:locations 116.034579 39.0304052 33
当用户想寻找自己附近的车是,LBS应用就可以使用GEORADIUS命令
例如,LBS应用执行下面的命令时,Redis会根据输入的用户的经纬度信息(116.034579,39.0304052),查找这个经纬度为中心的5公里内车辆信息,并返回个LBS应用
GEORADIUS cars:locations 116.034579 39.0304052 5 km ASC COUNT 10