#Redis
意味着可以使用 Redis 的能力实现比如”附近的人“、”附近的饭店“等等如此的功能。
使用 MySQL 等关系型数据库方案
- 求 A 和 B 两点距离时,把地址的经纬度存入数据库,然后根据勾股定理即可算出直线距离;
- 需要注意的是,经纬度的密度不一样(地球是椭球形),计算时需要按一定系数加权后再求和;
- 实现附近的人功能就比较复杂了,因为数据表存储着每个人的信息,不可能把所有数据全部遍历计算和当前坐标的距离。这时可以使用矩形区域进行一个筛选,比如限定当前坐标点经纬度偏差 0.01 的区域内的人进行遍历计算排序;
- 为了加快查询效率,可以在经纬度 x、y 上增加复合索引;
以上办法都是基于 MySQL 等关系型数据库来做的,但是此类数据库都有性能瓶颈,在实际场景中性能不足,所以不是很推荐。
使用 Redis-GeoHash 方案
[[GeoHash 算法]]是当前业界比较通用的算法,它将二维的经纬度数据映射到一维的整数上,这样所有的元素都在一条线上,求附近的人只需要将坐标映射后获取附近的点即可。
需要注意的是,此算法会有一定误差,因为二位经纬度映射到一维整数是有损的,通过整数再映射回来坐标会有一定偏差。 具体的 [[GeoHash 算法]]可以参考[[GeoHash 算法]]
在 Redis 中,[[GeoHash 算法]]将经纬度使用 52 位的整数进行编码,然后放进 zset 中,value 是元素的 key,score 是这 52 位整数。此时计算附近的人只需要通过 zset 的排序功能即可获得。
Geo 指令
geoadd增加geodist计算两个元素之间的距离geopos获取集合任意元素的经纬度坐标,可以一次获取多个geohash获取元素的经纬度编码,然后去 http://geohash.org/${hash} 上去定位georadiusbymember查询指定元素附近的其他元素,参数很复杂georadius查询指定坐标值附近的元素
需要说明的是,在一个地图应用中,位置数据可能有几百万条,而在集群环境中单个 key 对应的数据量不宜超过 1MB,否则会导致集群迁移时出现卡顿现象。所以建议 Geo 数据使用单独的 Redis 实例,不和基础业务放在一起,不放入集群中。
另外当数据量过大的时候,需要考虑对 Geo 数据进行拆分,通过国家、省、市等区域进行处理。