欢迎光临
我们一直在努力

从零搭一套骑手实时追踪系统,我踩过的那些位置服务的坑

年初我们接了一个同城配送平台的改造需求。

需求看起来很简单:

用户下单之后,能够实时看到骑手的位置、距离还有预计到达时间。

产品经理当时觉得这就是个地图功能,无非是在地图上放个小图标动一动。

结果真正落地的时候才发现,整个链路里面最复杂的反而是位置服务。

上线前后,我们陆续踩了地址解析、GPS失效、坐标系混乱、逆地址解析成本失控等几个大坑。

这篇文章把整个过程记录下来,希望能给正在做类似系统的同学一些参考。

系统整体架构

先看看最终的整体架构。

商家录入地址


地址解析(获取坐标)


订单创建

骑手接单


GPS定位

├─成功


坐标转换


逆地址解析


轨迹存储


推送用户

GPS失败


融合定位(WiFi+基站)


逆地址解析


轨迹存储


推送用户

刚开始我们以为位置服务无非就是经纬度。

后来发现真正需要解决的问题其实有四类:

  • 商家地址如何转坐标
  • GPS失效怎么办
  • 多种坐标系如何统一
  • 如何降低逆地址解析成本

而且这几个问题往往是一起出现的。

第一个坑:商家地址解析成功率远比想象中低

刚开始做的时候,我们认为地址解析是一件非常简单的事情。

用户填地址。

系统调一下接口。

返回经纬度。

结束。

结果上线一周之后,运营同事反馈:

有部分订单骑手接单后无法直接导航。

排查日志发现,大量商家填写的地址根本不是标准地址。

例如:

万达负一楼

停车场出口旁边

工商银行背后

xx路88号旁边

老地方

这种地址对于人类来说很好理解。

对于机器来说基本属于谜语。

我们统计了接近3万条商家地址数据。

发现:

  • 标准地址解析成功率接近98%
  • 非标准地址解析成功率不足80%

别小看这十几个百分点。

对于骑手来说就是:

接单后无法一键导航。

只能手动搜索。

配送效率直接下降。

后来我们把流程改成:

原始地址

地址标准化

地址解析

坐标入库

这样做之后解析成功率明显提升。

目前我们的位置服务层直接接入了LTS的Geocoding能力。

除了返回坐标之外,还会返回标准化后的地址和行政区划信息。

例如:

{
"lat": 30.658,
"lng": 104.065,
"address": {
"name": "四川省成都市锦江区东大街88号"
}
}

这样后续做区域统计、运营分析时也方便很多。

最大的经验就是:

不要相信商家录入的数据质量。

地址解析失败一定要记录日志。

定期人工修正。

否则脏数据会越来越多。


第二个坑:骑手进商场以后位置不动了

这个问题是用户投诉最多的。

用户反馈:

骑手明明已经到商场了

地图上的位置还停留在500米外

刚开始我们以为是App卡死。

后来排查发现:

根本原因是GPS失效。

例如:

  • 商场内部
  • 地下停车场
  • 写字楼电梯间
  • 地铁口附近

这些场景GPS信号非常差。

很多时候根本拿不到有效坐标。

最初我们的逻辑是:

GPS失败

不上报

结果用户看到的就是:

位置长时间不更新。

后来改成三级降级链路:

GPS

融合定位

定位失败状态

流程变成:

优先GPS

GPS精度低于阈值

自动切换WiFi+基站定位

仍然失败

上报定位失败状态

这里有个有意思的数据。

我们统计了一周线上数据:

用户投诉的位置异常订单中:

  • 87%发生在室内场景
  • 9%发生在地下停车场
  • 4%其它情况

真正发生在室外GPS漂移的反而很少。

后来增加融合定位之后:

位置中断时间从平均3分钟下降到30秒以内。

用户投诉量下降非常明显。

这里我们没有自己维护WiFi和基站数据库。

直接通过LTS的位置融合接口获取结果。

对于业务团队来说省了很多基础设施建设成本。

第三个坑:坐标系不统一,轨迹回放直接崩了

这是整个项目里最痛的一次事故。

当时系统已经上线。

客服突然反馈:

有些骑手轨迹非常诡异。

打开轨迹回放之后发现:

骑手在马路上

瞬移到小区里面

又跳回主干道

再穿过一栋楼

看起来像开了瞬移外挂。

排查两天后终于找到原因。

系统里混进了三种坐标:

GPS
WGS84

融合定位
GCJ02

历史系统
GCJ02 + BD09

全部存在同一张表。

而且没有记录坐标系字段。

导致回放时直接混用。

地图渲染自然乱套。

后来我们花了接近两周时间做数据迁移。

把历史数据全部重新转换。

从那以后团队立下一个铁规矩:

任何位置数据

必须带坐标系字段

数据库设计也改成:

coord_system TINYINT NOT NULL

并且在服务层强制校验。

最终统一规范:

所有数据入库前

全部转换GCJ02

数据库只存GCJ02

前端不做任何转换

事实证明:

提前统一规范的成本远远小于事后迁移。


第四个坑:逆地址解析把配额打爆了

刚开始我们做得非常直接。

用户每次刷新位置:

获取坐标

调用逆地址解析

返回地址

看起来没问题。

直到运营突然发现:

位置服务费用开始异常增长。

统计后发现:

骑手上报频率:15秒

用户刷新频率:5秒

在线骑手:100+

意味着同一个位置可能被反复解析几十次。

大量请求完全重复。

后来我们把逻辑改成:

写路径解析

读路径直接读取

即:

骑手上报位置

逆地址解析

位置+地址一起存库

用户读取:

直接查库

不再实时解析。

改造之后调用量下降超过60%。

后来又增加了一层GeoHash缓存:

GeoHash(7)

Redis

逆地址缓存

同一个区域直接复用解析结果。

最终逆地址解析调用量再次下降接近40%。

这类优化看起来不起眼。

但对于高频位置业务来说非常关键。

最终的位置能力架构

经过几轮重构之后。

整套位置能力最终变成:

商家录入

地址解析

标准化地址+坐标

骑手接单

GPS定位

坐标统一转换GCJ02

逆地址解析

轨迹存储

消息推送

GPS失败

融合定位

GCJ02坐标

逆地址解析

轨迹存储

消息推送

用户查看

读取轨迹表

直接返回坐标+地址

整个过程中我们实际上没有自己维护:

  • 地址解析库
  • 基站数据库
  • WiFi指纹库
  • 坐标转换服务

这些能力最终都沉淀到统一的位置服务层。

目前正地址解析、逆地址解析、坐标转换、融合定位几块能力都统一接在LTS上。

最大的收益其实不是省钱。

而是避免不同服务商之间的数据格式和坐标体系差异。

维护起来简单很多。

总结

做骑手实时追踪系统最大的坑。

其实从来不是地图展示。

真正容易出问题的是:

  • 地址脏数据
  • GPS失效
  • 坐标系混乱
  • 逆解析成本失控

这些问题单独出现都不严重。

但同时出现的时候。

用户感知会非常明显。

我们这套系统上线半年之后。

日均处理数万次位置更新。

回头看最重要的几个经验其实只有四条:

第一,坐标系从第一天统一。

不要让多种坐标系混进数据库。

第二,设计完整降级链路。

GPS → 融合定位 → 失败状态。

每一步都要有明确处理逻辑。

第三,逆解析走写路径。

不要把成本放到读请求上。

第四,地址解析失败必须记录。

脏数据不会自己消失。

只会越积越多。

赞(0)
未经允许不得转载:171主机测评 » 从零搭一套骑手实时追踪系统,我踩过的那些位置服务的坑
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址