场景需求
在移动对象轨迹监控与分析的项目中, 收集了数十万的车辆信息, 每个车辆会定时的上报当前位置, 事件, 状态等信息, 每天约数亿条轨迹点, 需要能够存储. 且前端用户在查询时, 要能快速返回目标船舶的信息.
入库需求:
轨迹数据, 每日新增 10 亿条左右, 包括时间点, 经纬度坐标, 对象当前的属性信息
基本不涉及到数据的修改(不断的追加数据)
查询需求:
区域回放: 根据时间和空间范围两个维度共同查询. 例如: 查询东经 110°~120°, 北纬 25°~35° 空间范围内, 2019.3.1~2019.3.10 时间范围内的所有轨迹点.
轨迹线查询: 根据某个移动对象的 id, 查出某段时间内的轨迹. 例如: 查询编号为 "205073000" 的船舶在 2019.3.1~2019.3.10 时间范围内的所有轨迹点.
要求:
要能支撑每日 10 亿量级的写入, 要能承载千亿轨迹规模的存储
时空查询 (区域回放) 要能在秒级响应, 轨迹线查询要能在百毫秒级响应
技术调研
关系型数据库
现有的关系型数据库如 Oracle,MySQL,PostgreSQL 都提供了 Spatial 的插件, 尤其是 PG 的空间引擎 PostGIS, 使用率较高, 具有丰富的空间处理算法, 适合做空间关系判断与分析等. 但众所周知, 关系型数据库的强项在于 OLTP, 即适合数据更新, 查询等, 但对于大规模数据的存储则需要分库分表等操作, 操作相对繁琐, 因此对于上述需求来说, 暂不考虑关系型数据库.(这里提一下, 除了阿里云 PG Ganos 外, 都没有时空处理)
NoSQL 数据库
NoSQL 适合处理海量数据的存储与查询, 如 Cassandra,HBase,MongoDB,Redis 等, 都支持海量数据的水平扩展. 但在时空方面都没有一个完善的方案, 比如 MongoDB,Redis 虽然都提供了空间处理的算法, 但总体来说只能实现 Within 等操作, 即空间范围查询操作.
阿里云已经发布了基于 HBase 的时空引擎 HBase Ganos(参考: https://help.aliyun.com/document_detail/87287.html?spm=a2c4g.11174283.6.619.3c693c2e29oyDM), 不仅可以处理空间查询, 还可以处理时空查询场景. 因此, 本文基于 HBase Ganos 时空引擎对上述场景进行测试.
实例规格
HBase Ganos 具有高吞吐特点, 本着节省的原则, 我们以最小规格配置为基础(约 2000 元 +/ 月, 成本与 HBase 相同), 来看看是否能够支撑上述需求. 具体配置如下:
master 节点: 2 核 4G
core 节点: 4 核 8G(数量可动态扩展)
磁盘: 高效磁盘(500G, 可动态扩展)
具体实施
访问接口
HBase Ganos 支持 RESTful 和 GeoTools 两种接口访问形式, 前者通过 HTTP 协议可以方便的使用任何一种编程语言访问; 而 GeoTools 接口基于 Java 语言, 较为通用. 本文采用该接口方式, 这里封装了一个 Ganos Client 工具, 可以直接下载使用(附案例代码连接)
数据模型表
通过 GanosSchemaUtil 工具类创建 SimpleFeature(Point 类型), 并添加了对象 id(为其建立索引), 速度, 事件, 状态, 时间 (默认建立索引) 等信息, 具体如下:
- GanosSchemaUtil ganosSchemaUtil = new GanosSchemaUtil();
- ganosSchemaUtil.addField("objId", "String", true);
- ganosSchemaUtil.addField("speed", "Double", false);
- ganosSchemaUtil.addField("event", "Integer", false);
- ganosSchemaUtil.addField("status", "Integer", false);
- ganosSchemaUtil.setGeometry("Point", null);
- ganosSchemaUtil.setDate("dtg");
- SimpleFeatureType sft = ganosClient.createSFT(schemaName, ganosSchemaUtil.toString(),"zstd");
- ganosClient.createSchema(sft);
数据构造
上述字段的值采用随机生成方式(按照真实数据规则模拟), 数据构造方法为:
时间窗口: 2019-02-25 00:00:00~2019-03-05 00:00:00
空间窗口: 经度范围 115.37465076~120.37465076, 纬度范围: 26.23923772~31.23923772
移动对象数量(可理解为车, 船的数量):100 万
其他属性数据: 速度, 状态, 事件等, 均采用随机生成方式
数据导入
启动 10 个线程并发写入
导入方法:
启动 10 个线程写入, 每次批量写入 1000 条.
这 1000 条数据中, 随机选取多个移动对象, 同时随机生成该移动对象的时间点, 空间位置以及其他属性信息. 比如这 1000 条轨迹点可属于 N 个对象, 每个对象的轨迹点个数也不相同.
代码参考:
数据查询
启动 10 个线程查询, 查询场景包含两种: a, 区域回放(时空查询);b, 单条轨迹查询(id + 时间)
每次从一百万个移动对象中随机选取一条, 同时随机选取查询的时间窗口, 考察系统吞吐, RT 等
代码: 参考
性能
写入性能: 存储层的 IO 可达 8 万 +/s, 在构建三张索引表的情况下, 可理解为每秒能支撑 3 万个轨迹点的导入, 完全能够满足一天 10 亿级的写入需求.
查询性能:
区域回放(时空查询): 每次查询返回数据量在几百条左右, 缓存为命中情况下, 耗时在 1 秒钟以内; 若缓存命中情况下, 在 100ms 左右.
轨迹线查询: 每次返回数据量在几百条左右, 耗时在 800ms 以内.
总结
HBase Ganos 不仅能够支持空间查询, 还能够支持 "时间 + 空间" 的查询, 以及轨迹线 (时序) 查询. 在 2 个 4 核 8G 的节点配置下, 能够支撑每日 10 亿量级的数据写入, 且性能维持在秒级以下, 适合海量轨迹的存储和查询场景.
来源: https://yq.aliyun.com/articles/694847