亿级 GPS 数据处理用 NoSQL、MySQL 还是 HBase?数据库选型看这里

在车联网场景下,GPS 产生的时序数据量级通常都达到了亿级,高效写入、存储和快速查询是最基本的数据处理要求,但在具体实践上这却不是一件容易实现的事情。最近某企业就遇到了这样一个问题:服务端接收存储 GPS 相关数据,按 1 次/30 秒的上传频率,一天的数据条数估计在 1.2 亿条,其想要实现后台的实时监控和历史轨迹查询,一般用什么样的数据库进行存储?NoSQL(Redis、MongoDB)?MySQL?还是 HBase?

相信上述企业的数据库选型问题并不是个例,选择到一款合适的数据库,对于打造一个适合业务发展的数据架构至关重要。为了找到该问题的最优解,涛思数据解决方案架构师从数据本质出发进行分析,结合具体实践输出本文,给到大家参考。

先谈 NoSQL 数据库

不管是 Redis/MongoDB/ElasticSearch 当中的哪一个,在面对上述场景时都会面临同一个问题:压缩率。在车联网当中,按照国标 30s 的采样间隔可以计算得到单台车的采集量为 2880 rows/day,在 10W 车辆规模下,就是 2.88 亿/天。假设单台车辆采集 250 个信号,每个信号 8 Bytes(相当于 Double),即每行 2000 Bytes,那么 1 天就会有 562.5 GB 的数据量,1 年会有约 200TB 的数据。

在这样的数据规模下,压缩率即使是 50%,也需要 100TB 的空间。而这样的空间规模,通常都需要 10 个节点以上的 NoSQL 集群(用 Redis 的话就更可怕了,需要内存 100TB 的集群)。这个结论的底层原理,就在于 NoSQL 是使用非结构化的方式来存储结构化数据的,这种模式导致了压缩效果差、存储成本高、节点规模大的劣势。

再谈 MySQL/PostgreSQL

本来这两款数据库作为 SQL 类数据库,存储结构化数据是很合适的。但是,我们看一下每秒的写入量:平均 10W/30 = 3333 rows/s,最大值 10W rows/s,由于车联网本身会出现“车机在一段时间内断网补传数据”、“车机上传按时钟定时”等特点,会有一定概率触发最大值写入量,甚至超过最大值。因此选用的数据库必须具备高吞吐能力,而且还得留有余力供后续扩容。用过 MySQL 的开发者都会有体验,在没调优的情况下,这种 2KB 的行写入,1k tps 基本把单个节点打满了。

另外一方面,我们一般都会建立索引,至少建立时间戳的索引用于按时间段查找数据。而当我们用 B+ 树存储索引,在单表数据量达到 2000W 行时,索引的维护会导致写入速度的下降,单从这一点看就很难运维,更不要说在建立更多索引的情况下。

再者,MySQL 的横向扩展只能靠中间件来实现,没有更好的方式了,这种分布式的横向扩展能力也为其打了个折扣。正是基于此,PostgreSQL 才会单独出了一个分支来存储时序数据。

接下来谈 HBase

HBase 单从诞生的背景看,就不是为了时序数据而设计的。很多程序员通过设计 rowkey 的方式,变相实现了 HBase 对时序数据的存储,其中 OpenTSDB 就是一种开源的实现方式。在 5、6 年前,分布式存储还是 Hadoop 一枝独秀的时代,大家也就自然而然地用上了 HBase/OpenTSDB 这一类数据库。但是从产品设计上看,其设计目标是为了服务爬虫存储这样的场景——支持几千亿行的表(超大表),并且支持随时添加新的列(列族)。从这样的设计里面,我们可以推导出来下面几个问题:

  • 存储率不高:因为 HBase 里用了 Byte 的类型,以 Column Family 为单位做列存,因此压缩率也上不去。但是比 NoSQL 好一些。
  • 运维复杂:用 HBase 就得先上 HDFS/ZooKeeper/MR 这一系列组件,安装运维就是个问题。本来只是为了存储数据,结果倒腾起大数据的组件来了。
  • 计算慢:哪怕是 OpenTSDB 这个基于 HBase 做的时序数据库(Time Series Database),在做一些常见的降采样、排序计算、时间段检索上,都不是特别快。其背后的问题还是在于 HBase 节点本身不提供时序的计算函数,因此查询时都得汇聚到 1 个OpenTSDB 节点来进行,并发度很有限并且会消耗大量的网络 IO 成本。

综上所述,HBase 也并非很适应车联网场景。

最后谈 TDengine

时序数据库(Time Series Database,TSDB)TDengine 在设计的初期就定位要做物联网场景下的数据库,也就是时序数据库。至于上述场景的数据问题,TDengine 已经从实践层面就给出了回答。

狮桥集团的网货平台与金融 GPS 系统业务中,对于车辆轨迹收集与计算有着强需求。GPS 每日产生总量在 40 亿左右,需要为业务方提供实时末次位置查询,近 180 日行驶轨迹查询,类似车辆轨迹对比查询,以及一些风险逾期的智能分析等等。在狮桥的产品历史中,技术架构一共经历过四个版本的迭代——通过 MQ 接入厂商数据、Kudu+Impala 模式、Hbase + Clickhouse、TDengine。

第三阶段改版中,狮桥曾尝试使用 Hbase、Clickhouse 替换 Kudu,但从存储功能而言,狮桥希望能够读写兼顾、支持 SQL,同时还有合理的分区策略,这一点 HBase 肯定不能满足,Clickhouse 虽然表现还算不错,但也没有完全满足需求。从业务需求出发,狮桥开始进行时序数据库选型,最后选择了 TDengine,实现了他们“希望找到一个存储技术既可以兼并读写性能,又可以契合到自身业务场景,且还是 SQL 原生”的数据库选型诉求。

在应用 TDengine 后,狮桥的整体数据存储缩减超过 60% 以上,集群更是指数级的下线——末次位置查询的 Redis、轨迹查询的 Hbase 集群集体下掉、Clickhouse 也不再用作轨迹存储,把裸金属用在了更需要蛮力干活的地方,真正实现了降本增效。

有着同样场景的还有南京津驰。此前他们的 GPS 服务采用的存储技术方案是 Redis + MySQL + CSV,实时数据存储到 Redis 队列,经过服务消费后将原始数据存储到 MySQL,凌晨执行定时任务将前一天 MySQL 中的原始数据存储到 CSV 文件。随着业务的发展以及数据量的增长,各种问题也逐渐凸显,开始影响工作效率,出现查询效率低、数据安全性低、数据占用空间大、数据运用不够灵活等问题。在进行选型调研后,他们选择将 TDengine 搭建在 GPS 服务中,轻松抗住了业务中每秒接近 400MB 左右的写入量,并且压缩率喜人,存储空间降为原方案的 3%

同样的车联网落地案例还有蔚来汽车理想汽车零跑汽车等,感兴趣可以点击链接查看,本篇文章就不多做赘述了。

而 TDengine 之所以能达到上述效果,还要从 Jeff(TDengine 创始人& CEO 陶建辉)归纳的十条时序数据处理特点说起:

  1. 所有采集的数据都是时序的 —— 就只处理时序数据
  2. 数据都是结构化的 —— 结构化是所有优化的第一切入点
  3. 每个数据流的数据源是唯一的 —— 在写入过程中不用过分考虑随机写入
  4. 数据少有更新或单条删除操作 —— 选择数据结构的重要依据
  5. 数据一般是按到期日期来删除的 —— 自动淘汰数据是长久运维的必需品
  6. 数据要优先保证写入操作,读操作为辅 —— 写入吞吐量是第一指标
  7. 数据流量平稳,可以较为准确的计算 —— 不像 MySQL 的业务场景,压力基本可预测
  8. 数据一定是指定时间段和指定区域查找的 —— 查询优化的主要入手点
  9. 数据多有统计、聚合等实时计算操作 —— 提供时序独有的函数
  10. 数据量巨大,一天的数据量就超过100亿条 —— 针对性的压缩率、横向扩展架构

从上述时序数据特点出发,TDengine 打造了以下的创新技术点:

  1. 创建一个设备一张表、超级表,压缩率达到到 10% 的级别
  2. 行式存储 + 列式存储,进一步提升压缩率
  3. LSM Tree 结构的引擎,SkipList 的 MemTable
  4. Union all + tag 的超级表语法糖
  5. 降采样/状态窗口/会话窗口函数

作为时序数据库引擎,TDengine 不需要基于 Hadoop 生态搭建,也不需要拼装 Kafka、Redis、HBase 等诸多组件,它将数据处理中的缓存、消息队列、数据库、流式计算等功能都统一在了一起,这样轻量级的设计不仅让它的安装包很小、对集群资源消耗很少,同时也在一定程度上降低了研发、运维成本,因为需要集成的开源组件少,因而系统可以更加健壮,也更容易保证数据的一致性。

下面延伸一个话题,分享一下我总结的数据库选型原则,以此帮助大家更好地进行数据库选型。

讲讲数据库的选型原则

  1. 如果是事务的:
    1. 单机扛得住的,MySQL/PG 都可以选择
    2. 单机扛不住,但是好分片的,同上一条
    3. 不好分片,那可以考虑 TiDB 这种分布式事务的 HTAP
  2. 对于非事务,基本上就是各种 MPP 型的 OLAP:
    1. 多维分析为主,不知道自己什么已知维度的分析,就用 ClickHouse/Doris 这种通用的 OLAP
    2. 有场景特色的,就选场景通用的,例如 TDengine 做时序场景,Neo4j 做图计算
  3. 分布式数据库,看几点:
    1. Sharding + Partition 策略:这一点基本上决定了性能的上下限
    2. 分布式架构:这一点影响系统的容量上限/瓶颈模块
    3. 计算函数:这一点决定好不好用,能不能减轻业务开发的工作量。不然都只有读写没计算,啥计算都自己写肯定是不合适的。

结语

事实证明,专用的比通用的更能打,大家可以移步到 https://docs.taosdata.com/ 去了解 TDengine 的更多技术细节。如果你也面临时序数据处理难题,欢迎添加小T vx:tdengine1 申请加入 TDengine 用户交流群,和更多志同道合的开发者一起探讨解决。