为了查一个南极用户,我把整个位置系统重构了

0 阅读3分钟

事情起源于一个特别离谱的Bug。

后台用户分布地图上。

国内密密麻麻一大片。

然后南极洲孤零零一个点。

特别显眼。

运营截图发群里:

这位用户是在南极科考站下单的吗?

大家笑了半天。

最后定位到原因:

经纬度写反了。

本来以为改一行代码就结束了。

结果越查越发现事情没那么简单。


第一个问题:到底有多少脏数据?

我写了个脚本扫数据库。

结果比想象中夸张。

除了南极。

还有:

  • 太平洋
  • 非洲撒哈拉
  • 印度洋

甚至还有经纬度是:

{
  "lat": 999,
  "lng": 999
}

的数据。

那一刻我意识到:

问题不是一条数据错了。

而是整个位置系统没有边界。


第二个问题:每个接口返回格式都不一样

项目这些年接过不少位置服务。

有些返回:

{
  "lat": 30.57,
  "lng": 104.06
}

有些返回:

{
  "latitude": 30.57,
  "longitude": 104.06
}

还有:

{
  "x": 104.06,
  "y": 30.57
}

每个开发写接口的时候。

都在自己转换。

没人统一。


第三个问题:没人知道坐标系是什么

最开始我以为:

经纬度不就是经纬度吗?

后来才发现。

国内位置服务至少有:

  • WGS84
  • GCJ02
  • BD09

三套。

有的接口返回GCJ02。

有的返回WGS84。

有人直接存库。

有人转换之后再存。

几年下来。

数据库已经没人能说清楚:

到底存的是什么。


我们干脆做了一层 Location Gateway

后来索性重构。

所有位置数据必须经过一个统一入口。

LocationGateway

负责:

  • 坐标系统一
  • 格式统一
  • 数据校验
  • Provider切换

业务层禁止直接调用第三方API。


数据进库前先过四道关

第一关:

经纬度范围校验

lat ∈ [-90,90]
lng ∈ [-180,180]

第二关:

坐标系转换

统一转GCJ02。

第三关:

可信度检查

{
  "confidence": 92
}

低于阈值直接丢弃。

第四关:

来源记录

{
  "provider": "lts"
}

以后出问题能追溯。


为什么最后选了统一Provider

重构过程中发现。

业务真正需要的能力其实不多:

  • 地理编码
  • 逆地理编码
  • 坐标转换
  • IP定位
  • 行政区划

以前不同能力接不同服务。

出了问题根本不知道找谁。

后来统一收敛到了:

迈云位置服务(LTS)

主要原因很简单:

接口比较全。

不用维护一堆适配层。


重构后的一个意外收获

以前每次排查定位问题:

查接口
查日志
查数据库

半小时起步。

现在看到一条位置数据。

直接知道:

{
  "provider": "lts",
  "coordsType": "GCJ02",
  "confidence": 95
}

来源、坐标系、可信度一眼看完。

排查效率高了很多。


最后

那个南极用户后来找到了。

其实就在成都高新区。

但那次事故让我意识到:

位置服务最难的不是定位。

而是数据治理。

很多团队觉得:

save(lat, lng)

就算完成了位置功能。

实际上真正的工作。

从这里才刚刚开始。