V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Allenxup
V2EX  ›  程序员

求友们帮助,大量 GPS 轨迹数据利用 MongoDB 数据库如何存储呢(SpringBoot+ MongoDB)

  •  1
     
  •   Allenxup · 2023-07-30 18:23:14 +08:00 · 3790 次点击
    这是一个创建于 484 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有大约 500 辆车 每辆车绑定 1 台 GPS 有线设备,每天大概运行 16 小时 运动状态下每 10 秒上报 1 条 gps 数据,静止状态下每 5 分钟上报 1 条。数据对接的是第三方 GPS 平台。

    需求 1:需要实时同步轨迹数据到自己 MongoDB 库中,目前第三方可进行推送数据,我方只需要提供 http 接收接口。 现在问题是只要数据接收接口挂了,就无法接收到数据了,要如何保证数据不丢失呢

    需求 2:在大量 GPS 数据情况下如何利用 MongoDB 如何存储呢,需要实现的功能:轨迹查询、区域查车、查询所有车辆当前位置。表结构改怎么设计比较合理呢?

    第 1 条附言  ·  2023-07-31 14:45:38 +08:00
    在查询轨迹时 WGS84 坐标使用百度 API 转百度坐标耗时比较长,导致查询轨迹耗时 6s 左右,有什么解决方案吗
    47 条回复    2023-08-01 16:37:51 +08:00
    opengps
        1
    opengps  
       2023-07-30 18:27:50 +08:00
    这也不多,我曾经在关系型里都能存到几十亿条,你这非关系型问题更不大了
    有一点需要调整:查询最新位置没必要进入历史表,用缓存或者单独一个表去更新存储最新即可。
    serafin
        2
    serafin  
       2023-07-30 18:41:39 +08:00
    最多平均每秒 50 条,极端情况每 10 秒同时来 500 条。用 .txt 都行吧。MongoDB 随便怎么都行吧。问题是 http 协议不适合干这个吧。这个体量 http 也不是不行。
    lzd123
        3
    lzd123  
       2023-07-30 18:42:10 +08:00 via iPhone
    针对需求 1 ,建议搞个网关服务用于专门对接数据,可高可用设计;
    数据流: http 接口-》网关服务:接收到轨迹数据简单处理-〉消息中间件(如 mq )-》相关服务再消费入库
    Allenxup
        4
    Allenxup  
    OP
       2023-07-30 18:45:50 +08:00
    @opengps 感谢您的解答。你的意思是 MongoDB 一个集合存所有的设备轨迹数据嘛?如果达到几十亿条查询轨迹速度咋样,
    最新位置存表里那不是要频繁更新吗
    dreasky
        5
    dreasky  
       2023-07-30 19:34:45 +08:00
    MongoDB 不是有专门存储地理空间数据的类型吗
    yoyoluck
        6
    yoyoluck  
       2023-07-30 19:44:04 +08:00   ❤️ 1
    这种数据时序数据库是不是更合适, 像 influxdb 这样的
    liprais
        7
    liprais  
       2023-07-30 19:47:36 +08:00
    api -> kafka -> mongodb 完事
    leloext
        8
    leloext  
       2023-07-30 21:04:44 +08:00
    同 6 楼,这种处理带时间标签的数据是时序数据库更合适。
    vincent7245
        9
    vincent7245  
       2023-07-30 21:52:14 +08:00
    1 直接用 nginx 收,打日志到本地,nginx 也可以做多台保证高可用,反正只要收到的数据都打到日志了,数据不可能丢。后面你怎么处理都随便了,日志传到 kafka ,还是直接读都行,看你们架构怎么设计了。

    2 暂时没什么建议,对 mongo 不熟
    xwayway
        10
    xwayway  
       2023-07-30 21:57:17 +08:00
    恰巧做过车辆网云平台,之前采取的是 gateway -> kafka ,存储用的是 hbase ,mongodb 只存最新的数据。
    hbase 用 vin+timestamp 做 rowkey 。
    其他更多的细节记不太清了,六七年前做的了。
    fishg
        11
    fishg  
       2023-07-30 21:58:37 +08:00
    其实有如果目标定了是 MongoDB ,可以在预期量级下模拟测试下
    xwayway
        12
    xwayway  
       2023-07-30 22:02:06 +08:00
    @xwayway 涉及到你说的区域查车和当前位置直接从 mongo 查询应该就能满足,轨迹查询应该也是单台车的吧,这个时候去 hbase 查就行了。
    opengps
        13
    opengps  
       2023-07-30 22:36:08 +08:00
    @Allenxup 历史轨迹单独存,这张表很大,但用途非常单一,仅仅用于需要使用历史数据的场景,结构也足够简单,仅仅支持单设备特定时间查询,仅仅支持写入效率,就已经足够了
    nosql 的我没写,参考下我之前关系型结构的博客: https://www.opengps.cn/Blog/View.aspx?id=284
    3kkkk
        14
    3kkkk  
       2023-07-30 22:48:13 +08:00
    需求 1:直接网关+分布式 api+mq+mongodb ;
    需求 2:建议分三个集合吧,最新车辆基本信息及最新位置信息、历史轨迹(可以把数据定期归档主要用来撕逼)、轨迹数据。至于三个需求:
    第一个看轨迹数据具体需求是否需要筛选你这么多数据加载到前端也不好处理,确认轨迹查询具体规则在 mq 处理的时侯可以直接筛选下重复数据生成一个车辆轨迹相关的文档。
    第二和第三个直接查询最新位置信息就可以,
    BurgerTown
        15
    BurgerTown  
       2023-07-30 23:18:26 +08:00
    1. 换 MQTT 感觉 IoT 场景用 MQTT 的挺多的吧
    2.这个的话 MongoDB 是有针对时序数据的 collection 做单独优化的 但是具体性能位置
    然后你要的那几个查询 MongoDB 都有原生的查询函数 起码你代码写起来很简单
    lsk569937453
        16
    lsk569937453  
       2023-07-31 09:14:50 +08:00
    1.现在问题是只要数据接收接口挂了,就无法接收到数据了,要如何保证数据不丢失呢?

    这个接口原来直接写 mongoDB 的话,改为写 kafka ,然后开异步线程从 kafka 消费写入 MongoDB 。

    2.我记得 MongoDB 在大数据量下性能不咋地。每天大概新增 500*16*36(每小时)=83W 数据。每月大概是 2000w 新增。这种数据量我也建议上 Hbase 。只不过 Hbase 的话查询有限制,不能像关系型数据一样查询。
    hopingtop
        17
    hopingtop  
       2023-07-31 09:49:41 +08:00   ❤️ 1
    我提供一个 Mongodb 写数据性能的实际体验吧。
    之前写了一个小的日志收集,提供的 gRPC 传输,2c4g 的 Mgo ,一天至少写 2-3 千万的数据,但是这个是多集合写。
    分担到单集合有些峰值差不多在 5-7 百万数据,CPU 使用波动幅度很小,是因为做了集合分片的。

    你的需求就用 mongo ,随便用,本身他也支持 GPS 的查询。 实在担心,自己 router 做一个集合分片即可。
    没必要使用 mongodb 自带的 Sharding ,运维成本又上去了。

    再回到你说的数据不丢失,这已经有很多成熟的解决方案了,匹配自己的技术栈和架构,找最简单的就行,如果发送端有最基本的重试,那么加一个 gateway 就是最实在的!
    hopingtop
        18
    hopingtop  
       2023-07-31 09:55:33 +08:00
    @hopingtop #17 再补一个查询体验,只要时间范围做好,命中索引 不长的复合索引,根据日志的查询感官来说,单集合 5000W 数据,可以做到 秒级返回。
    roundgis
        19
    roundgis  
       2023-07-31 10:52:51 +08:00 via Android
    存儲不用特別考慮 一條記錄一個軌跡點即可

    我以前用 mongodb 2.x 版本做過車隊管理 2000 台車一個實例 單表幾十億數據不成問題
    Desdemor
        20
    Desdemor  
       2023-07-31 11:16:27 +08:00   ❤️ 1
    用 ck 吧,查的快
    Allenxup
        21
    Allenxup  
    OP
       2023-07-31 13:39:03 +08:00
    @roundgis 十亿数据查询轨迹速度如何?
    Allenxup
        22
    Allenxup  
    OP
       2023-07-31 13:42:41 +08:00
    @Desdemor ck 是啥
    Desdemor
        23
    Desdemor  
       2023-07-31 13:58:12 +08:00
    @Allenxup ClickHouse 哇
    Allenxup
        24
    Allenxup  
    OP
       2023-07-31 13:58:55 +08:00
    @Desdemor 明白了,感谢
    Desdemor
        25
    Desdemor  
       2023-07-31 14:03:56 +08:00
    @Allenxup 我们也有类似的业务,查询那是相当的快了,你可以先存到 redis,然后批量写入
    Allenxup
        26
    Allenxup  
    OP
       2023-07-31 14:17:05 +08:00
    @opengps 有个问题请教,轨迹数据 WGS84 坐标转百度坐标,放前端转还是后端转比较好呢
    opengps
        27
    opengps  
       2023-07-31 14:33:45 +08:00
    @Allenxup 我建议是放在后端,这样可以用额外的 webapi 去进行处理,前端只管使用数据成果即可。
    我之前是同时存储 2 份数据,这样遇到比如计算里程的时候,直接使用原始坐标可以更高的理论准确度。实际用下来却发现意义不大,虽然两套标准并没有线性关系,但是在较多点的场景下,互相填补之后的里程计算结果基本就接近均匀坐标了
    Allenxup
        28
    Allenxup  
    OP
       2023-07-31 14:42:54 +08:00
    @opengps 我这边也是放后端处理,但是在轨迹坐标转换部分耗时比较长,导致查询轨迹耗时 6s 左右,有什么解决办法吗
    opengps
        29
    opengps  
       2023-07-31 14:48:49 +08:00
    @Allenxup 那你得自己验证下了,思路:
    1 ,硬盘速度跟上,看下磁盘队列有没有占满或者拉长
    2 ,sql 索引使用情况,比如我早期版本关系型数据库,天然就给查询只提供一种方式,一定会命中索引
    3 ,sql 一次读取量大小,sql 查询效率之外,那就是看你数据从硬盘到内存的总大小是不是满速传输依然需要 6 秒了,可以根据需要缩减需要返回的字段数量
    4 ,其他处理,有没有额外在程序里过滤或者排序,或者替换补充数据等等,能回归到原始的硬盘读写,就不要去费劲转换
    5 ,网络传输,服务器到客户端经过的网络带宽跟你序列化之后的结果集大小换算下耗时
    opengps
        30
    opengps  
       2023-07-31 15:04:07 +08:00
    @Allenxup 刚注意到附言,我都是入库时候先纠偏在入库,因为只查询一个点,所以单个流程里耗时很低

    另外,大家可能不知道,早期的方案多数人不是用联网查百度 webapi,而是自己采集的本地纠偏数据库,现在限制并发了总量了,采集不动了。
    Allenxup
        31
    Allenxup  
    OP
       2023-07-31 15:13:21 +08:00
    @opengps 感谢解答。你的意思是坐标转换后再入库吗
    opengps
        32
    opengps  
       2023-07-31 15:14:46 +08:00
    @Allenxup 是的。几乎所有核心功能全是在后端完成,包括围栏之类的
    Allenxup
        33
    Allenxup  
    OP
       2023-07-31 15:23:52 +08:00
    @opengps 但是考虑到以后如果换其他地图的话就麻烦了,不太灵活
    malaohu
        34
    malaohu  
       2023-07-31 15:29:26 +08:00
    上一个消息队列,分别用消费者处理业务。包括你得坐标转化。
    opengps
        35
    opengps  
       2023-07-31 15:29:35 +08:00
    @Allenxup 所以需要存原始坐标,毕竟有些地图标准只支持单向转化,你可以自己决定备用转化字段的存储结果是什么标准的。在所有的资源中,存储换效率是最低成本的
    QWE321ASD
        36
    QWE321ASD  
       2023-07-31 17:19:45 +08:00
    之前用过 clickhouse 存轨迹,存了 6000w 吧,用 10 个左右条件去查结果 30w 量级的数据,秒出,就是要自己想想怎么合并请求入库,官方推荐每秒最多 100 次 insert 操作
    bk201
        37
    bk201  
       2023-07-31 17:31:58 +08:00
    1.本地存储临时文件,定时上传,失败重试
    2.服务端异步消息,或者直接 mongodb 都行
    只要本地不丢失,都没问题。
    guxin0123
        38
    guxin0123  
       2023-07-31 17:36:40 +08:00
    @Allenxup 尽量保存原始记录,不要跟百度绑死了,api 计费规则修改为按次计费也不是不可能。

    而且不管是 Android iOS 还是浏览器端都支持 WGS84 坐标绘制的,保存 BD09LL 或 GCJ02 完全没有意义
    Elilili
        39
    Elilili  
       2023-07-31 17:37:48 +08:00
    geomesa
    victorc
        40
    victorc  
       2023-07-31 17:45:09 +08:00
    当然用 mysql 存:用 kafka 收数据,用 mysql 落盘

    你们这个公司规模很小吧,要尽可能的降低技术维护成本, 统一存储。
    Anivial
        41
    Anivial  
       2023-07-31 18:09:38 +08:00
    WGS84 坐标使用百度 API 转百度坐标耗时比较长:
    建议直接谷歌搜索“WGS84 坐标转换百度坐标 JS 方法”,已经有精确度蛮高的民间转换方法了
    Allenxup
        42
    Allenxup  
    OP
       2023-07-31 18:47:54 +08:00
    @guxin0123 那我如果使用百度地图,每次查询轨迹都需要转换坐标了,比较耗时,有什么办法解决吗
    roundgis
        43
    roundgis  
       2023-07-31 19:16:05 +08:00 via Android
    @Allenxup 三天內的數據秒級響應
    jackroyal
        44
    jackroyal  
       2023-07-31 20:17:43 +08:00
    直接用百度地图鹰眼轨迹就行吧, https://lbsyun.baidu.com/products/yingyan 定位点数据灌进去, 有网页或接口可以查询轨迹, 还可以纠偏和抽稀
    guxin0123
        45
    guxin0123  
       2023-08-01 10:02:41 +08:00
    @Allenxup 不需要转换 api 里面有使用 wgs84 坐标格式的选项
    Allenxup
        46
    Allenxup  
    OP
       2023-08-01 14:18:06 +08:00
    @guxin0123 百度地图可以直接使用 wgs84 坐标?
    guxin0123
        47
    guxin0123  
       2023-08-01 16:37:51 +08:00
    @Allenxup 😂 看错了 Android sdk 可以使用 GCJ02 其他的要自己转

    wgs84->gcj02 gcj02->bd09

    有相关 Java 代码 是 csdn 上的

    aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZlaW5pZmkvYXJ0aWNsZS9kZXRhaWxzLzEyMDU0NzEyNw==
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1650 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 16:50 · PVG 00:50 · LAX 08:50 · JFK 11:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.