摘要: 基于 TableStore 轻松实现亿量级轨迹管理与地理围栏
一, 方案背景
轨迹管理系统日常生活中使用非常普遍, 如外卖派送轨迹, 快递物流流转, 车辆定位轨迹等. 该场景与地理位置管理类似, 核心点与瓶颈都在数据库的存储性能与查询能力, 同时需要时间字段正序排列, 保证轨迹点顺序; 一方面, 存储服务需要应对海量数据的低延迟存, 读, 另一方面, 存储服务也要提供高效的多维度数据检索与排序. 表格存储 (TableStore) 对于轨迹管理场景, 依然可以胜任, 完全具备实现轨迹管理系统的能力.
不妨来体验一下基于 TableStore 打造的[亿量级摩托车管理系统] 样例;
需求场景
某城市市区出于安全考虑, 限制摩托车进入一定的区域范围. 某摩托车租赁公司, 为了更好管理所辖摩托车的违章问题, 对自己所辖摩托车安装定位系统, 定时采集摩托车位置. 摩托车租赁公司, 可以通过轨迹管理平台, 查询统计违章情况, 也可作为依据, 提醒违章的租赁用户, 过多违章拉入黑名单;
查询场景:[2018 年 11 月 01 日] 编号[id00001] 的摩托车行驶轨迹与违章情况查询;
样例如下:
注: 该样例提供了[亿量级] 轨迹数据. 官网控制台地址: 项目样例
样例内嵌在表格存储控制台中, 用户可登录控制台体验系统(若为表格存储的新用户, 需要点击开通服务后体验, 开通免费, 订单数据存储在公共实例中, 体验不消耗用户存储, 流量, Cu).
表格存储 (TableStore) 方案
采用表格存储 (TableStore) 轻松搭建一套: 亿量级摩托车管理系统. 多元索引功能提供 GEO 检索, 多维查询的能力, 通过对时间的排序获取追踪设备的轨迹. 同时, 用户可随时创建索引然后完成自动同步, 不用担心存量数据问题.
TableStore 作为阿里云提供的一款全托管, 零运维的分布式 NoSql 型数据存储服务, 具有[海量数据存储] ,[热点数据自动分片] ,[海量数据多维检索] 等功能, 有效的地解决了 GEO 数据量大膨胀这一挑战;
SearchIndex 功能在保证用户数据高可用的基础上, 提供了数据多维度搜索, 排序等能力. 针对多种场景创建多种索引, 实现多种模式的检索. 用户可以仅在需要的时候创建, 开通索引. 由 TableStore 来保证数据同步的一致性, 这极大的降低了用户的方案设计, 服务运维, 代码开发等工作量.
二, 搭建准备
若您对于基于 TableStore 实现的[亿量级摩托车管理系统] 体验不错, 并希望开始自己系统的搭建之旅, 只需按照如下步骤便可以着手搭建了:
1, 开通表格存储
通过控制台开通表格存储服务, 表格存储即开即用(后付费), 采用按量付费方式, 已为用户提供足够功能测试的免费额度. 表格存储官网控制台 https://ots.console.aliyun.com/ , 免费额度说明 https://help.aliyun.com/document_detail/52733.html .
2, 创建实例
通过控制台创建表格存储实例, 选择支持多元索引的 Region.(当前阶段 SearchIndex 功能尚未商业化, 暂时开放北京, 上海, 杭州和深圳四地, 其余地区将逐渐开放)
创建实例后, 提交工单申请多元索引功能邀测(商业化后默认打开, 不使用不收费).
邀测地址: 提工单, 选择[表格存储]>[产品功能, 特性咨询]>[创建工单] , 申请内容如下:
问题描述: 请填写[申请 SearchIndex 邀测]
机密信息: 请填写[地域 + 实例名] , 例: 上海 + myInstanceName
3,SDK 下载
使用具有多元索引 (SearchIndex) 的 SDK, 官网地址 https://help.aliyun.com/document_detail/86528.html , 暂时 java,go,node.JS 三种 SDK 增加了新功能
- java-SDK
- <dependency>
- <groupId>com.aliyun.openservices</groupId>
- <artifactId>tablestore</artifactId>
- <version>4.7.4</version>
- </dependency>
- go-SDK
- $ go get GitHub.com/aliyun/aliyun-tablestore-go-sdk
4, 表设计
店铺检索系统样例, 仅简易使用一张店铺表, 主要包含字段: 店铺类型, 店铺名称, 店铺地理位置, 店铺平均评分, 人均消费消等. 表设计如下:
表名: geo_track
列名 | 数据类型 | 索引类型 | 字段说明 |
---|---|---|---|
_id(主键列) | String | MD5(mId + timestamp) 避免热点 | |
mId | Stirng | 摩托车编号 | |
timestamp | long | LONG | 时间点(毫秒时间戳) |
pos | String | GEO_POINT | 车辆位置:"30.132,120.082"(纬度, 精度) |
... | ... | ... | ... |
三, 开始搭建(核心代码)
1, 创建数据表
用户仅需在完成邀测的实例下创建 "摩托车轨迹表": 通过控制台创建, 管理数据表(用户也可以通过 SDK 直接创建): 其他表如租赁用户表, 摩托车信息表等, 根据需求创建: 这里仅展示轨迹表, 表名: geo_track
2, 创建数据表索引
TableStore 自动做全量, 增量的索引数据同步: 用户可以通过控制台创建索引, 管理索引(也可以通过 SDK 创建索引)
3, 数据导入
插入部分测试数据 (控制台样例中插入了 1.08 亿条(1 万辆摩托 70 天 24 小时 * 6 个 "10 分钟点") 数据, 用户自己可以通过控制台插入少量测试数据);
表名: geo_track
摩托车编号 | 轨迹点 md5(mId + timestamp)(主键) | 时间 | 店铺位置 |
---|---|---|---|
id00001 | f50d55bec347253c24dc9144dff3e3b7 | 1541103600000 | 30.30094,120.01278 |
表名: moto_user
摩托车编号(主键) | 摩托车颜色 | 摩托车品牌 | 摩托车租赁用户 |
---|---|---|---|
id00001 | 银灰色 | H 牌摩托车 | 杨六 |
4, 数据读取
数据读取分为两类:
主键读取(摩托车信息查询)
基于原生表格存储的主键列获取: getRow, getRange, batchGetRow 等. 主键读取用于索引 (自动) 反查, 用户也可以提供主键 (摩托车编号) 单条查询的页面, 查询速度极快. 单主键查询方式不支持多维度检索;
索引读取(轨迹信息查询)
基于新 SearchIndex 功能 Query:search 接口. 用户可以自由设计索引字段的多维度条件组合查询. 通过设置选择不同的查询参数, 构建不同的查询条件, 不同排序方式; 目前支持: 精确查询, 范围查询, 前缀查询, 匹配查询, 通配符查询, 短语匹配查询, 分词字符串查询, 并通过布尔与, 或组合.
如[2018 年 11 月 01 日, id00001 号摩托车, 行驶轨迹及违章查询] Query 条件如下:
- List<Query> mustQueries = new ArrayList<Query>();
- List<String> polygonList = Arrays.asList(// 地理围栏, 禁摩区域
- "30.262348,120.092127",
- "30.311668,120.079761",
- "30.332413,120.129371",
- ...
- );
- String mId = "id00001";
Long timeStart = [2018-11-01 时间戳];
Long timeEnd = [2018-11-02 时间戳];
- GeoPolygonQuery geoPolygonQuery = new GeoPolygonQuery();
- geoPolygonQuery.setPoints(polygonList);
- geoPolygonQuery.setFieldName("pos");
- mustQueries.add(geoPolygonQuery);
- TermQuery termQuery = new TermQuery();
- termQuery.setFieldName("mId");
- termQuery.setTerm(ColumnValue.fromString(request.getmId()));
- mustQueries.add(termQuery);
- RangeQuery rangeQuery = new RangeQuery();
- rangeQuery.setFieldName("timestamp");
- rangeQuery.setFrom(ColumnValue.fromDouble(timeStart, true);
- rangeQuery.setTo(ColumnValue.fromDouble(timeEnd, false);
- mustQueries.add(rangeQuery);
- BoolQuery boolQuery = new BoolQuery();
- boolQuery.setMustQueries(mustQueries);
这样, 系统的核心代码已经完成, 基于表格存储搭亿量级 "摩托车管理系统", 是不是很简单?
来源: https://segmentfault.com/a/1190000017022749