如果说移动互联网时代区别与主机互联网时代最大的革命是什么?大部分人都会认为是lbs服务,众所周知的我们一款社交应用,当年就是靠着摇一摇跟查看附近的人,一发不可收,彻底掀起了移动互联网的革命。今天我们介绍一下如何实现一个简单的位置服务功能的架构是什么样子呢?
我们先从业务场景入手吧,之前我们团队是做共享充电宝的,我们经常会遇到这样的场景,寻找最近的共享充电宝在哪里。一开始,我们这个东西是这么实现的,对于每个共享充电宝站,都会存经纬度坐标在数据库里面。每次用户过来查询身边的充电宝,前端会把用户的经纬度坐标带上来,然后后台从数据库里面捞出所有的坐标,通过经纬度计算距离,然后找出最小距离的共享充电宝仓库出来。
慢慢的随着业务的扩展,充电宝仓库越来越多,性能问题就显现了,毕竟每次拿出全国门店的充电宝来比较,的确性能很差。即便我们把数据都缓存了,但依然改变不了很多无所谓的计算。
一个简单的优化是我们按照城市或者区域去分区,然后每次只检查同个区域的数据,按照城市分区是一个比较简单的方案,因为网上有很多api可以根据经纬度而获取到对应的区号。这一个看似行之有效的优化,却引来了不少投诉。举个例子,假如我们以城市分区,那么有些在城市交界的服务点,就会搜索不到。例如在广州佛山的交接有个门店,却在分区上归属与佛山,这个时候在广州的边界就会搜索不到,即便距离很短。
这便引出了我们今天的主角,geohash,将经纬度编码成字符串,可以起到一个降维的作用。如下图,一般来说,两个编码前面相同的子字符串越多,说明他们越接近。具体的算法大家感兴趣可以深入学习。
还好开源世界已经帮我们提供了一个很好用的geohash库了,那便是使用redis。redis将位置的数据存放在zset里面。并对我们提供了一些api,下面我们简单的介绍一下。
1.我们从业务场景出发,我们每新增一个共享充电宝的服务站,就需要插入这个服务站的坐标信息,我们使用redis命令geoadd。
2.用户查询以自己为中心,附近的充电宝,我们可以使用redis命令georadius
3.后台可能要拉去所有的门店列表,可以使用redis命令geodist