PostgreSQL 实时位置跟踪+轨迹分析系统实践 - 单机顶千亿轨迹/天

标签

PostgreSQL , PostGIS , 动态更新位置 , 轨迹跟踪 , 空间分析 , 时空分析


背景

随着移动设备的普及,越来越多的业务具备了时空属性,例如快递,试试跟踪包裹、快递员位置。例如实体,具备了空间属性。

例如餐饮配送,送货员位置属性。例如车辆,实时位置。等等。

其中两大需求包括:

1、对象位置实时跟踪,例如实时查询某个位点附近、或某个多边形区域内的送货员。

2、对象位置轨迹记录和分析。结合地图,分析轨迹,结合路由算法,预测、生成最佳路径等。

DEMO

以快递配送为例,GPS设备实时上报快递员轨迹,写入位置跟踪系统,同时将轨迹记录永久保存到轨迹分析系统。

由于快递员可能在配送过程中停留时间较长(比如在某个小区配送时),上报的多条位置可能变化并不大,同时考虑到数据库更新消耗,以及位置的时效性,可以避免一些点的更新(打个比方,上一次位置和当前位置变化量在50米时,不更新)。

动态更新可以减少数据库的更新量,提高整体吞吐能力。

设计

实时位置更新

1、建表

create table t_pos (
  uid int primary key,   -- 传感器、快递员、车辆、。。。对象ID
  pos point,             -- 位置
  mod_time timestamp     -- 最后修改时间
);  

create index idx_t_pos_1 on t_pos using gist (pos);

真实环境中,我们可以使用PostGIS空间数据库插件,使用geometry数据类型来存储经纬度点。

create extension postgis;  

create table t_pos (
  uid int primary key,   -- 传感器、快递员、车辆、。。。对象ID
  pos geometry,          -- 位置
  mod_time timestamp     -- 最后修改时间
);  

create index idx_t_pos_1 on t_pos using gist (pos);

2、上报位置,自动根据移动范围,更新位置。

例如,移动距离50米以内,不更新。

insert into t_pos values (?, st_setsrid(st_makepoint($lat, $lon), 4326), now())
on conflict (uid)
do update set pos=excluded.pos, mod_time=excluded.mod_time
where st_distancespheroid(t_pos.pos, excluded.pos, 'SPHEROID["WGS84",6378137,298.257223563]') > ?;  -- 超过多少米不更新

历史轨迹保存

通常终端会批量上报数据,例如每隔10秒上报10秒内采集的点,一次上报的数据可能包含多个点,在PostgreSQL中可以以数组存储。

create table t_pos_hist (
  uid int,                  -- 传感器、快递员、车辆、。。。对象ID
  pos point[],              -- 批量上报的位置
  crt_time timestamp[]      -- 批量上报的时间点
);   

create index idx_t_pos_hist_uid on t_pos_hist (uid);                 -- 对象ID
create index idx_t_pos_hist_crt_time on t_pos_hist ((crt_time[1]));    -- 对每批数据的起始时间创建索引

有必要的话,可以多存一个时间字段,用于分区。

历史轨迹分析

动态位置变更压测

写入并合并,同时判断当距离大于50时,才更新,否则不更新。

(测试)如果使用point类型,则使用如下SQL

insert into t_pos values (1, point(1,1), now())
on conflict (uid)
do update set pos=excluded.pos, mod_time=excluded.mod_time
where t_pos.pos <-> excluded.pos > 50;

(实际生产)如果使用PostGIS的geometry类型,则使用如下SQL

insert into t_pos values (1, st_setsrid(st_makepoint(120, 71), 4326), now())
on conflict (uid)
do update set pos=excluded.pos, mod_time=excluded.mod_time
where st_distancespheroid(t_pos.pos, excluded.pos, 'SPHEROID["WGS84",6378137,298.257223563]') > 50;

压测

首先生成1亿随机空间对象数据。

postgres=# insert into t_pos select generate_series(1,100000000), point(random()*10000, random()*10000), now();
INSERT 0 100000000
Time: 250039.193 ms (04:10.039)

压测脚本如下,1亿空间对象,测试动态更新性能(距离50以内,不更新)。

vi test.sql    

\set uid random(1,100000000)
insert into t_pos
select uid, point(pos[0]+random()*100-50, pos[1]+random()*100-50), now() from t_pos where uid=:uid
on conflict (uid)
do update set pos=excluded.pos, mod_time=excluded.mod_time
where t_pos.pos <-> excluded.pos > 50;

压测结果,动态更新 21.6万点/s,187亿点/天。

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 120   

number of transactions actually processed: 26014936
latency average = 0.295 ms
latency stddev = 0.163 ms
tps = 216767.645838 (including connections establishing)
tps = 216786.403543 (excluding connections establishing)

轨迹写入压测

每个UID,每批写入50条:写入速度约 467.5万点/s,4039亿点/天。

压测时,写多表,压测使用动态SQL。

do language plpgsql $$
declare
begin
  for i in 0..127 loop
    execute 'create table t_pos_hist'||i||' (like t_pos_hist including all)';
  end loop;
end;
$$;
create or replace function import_test(int) returns void as $$
declare
begin
  execute format('insert into t_pos_hist%s values (%s, %L, %L)', mod($1, 128), $1,
  array[point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1)] ,
  array['2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10']);
end;
$$ language plpgsql strict;
vi test1.sql  

\set uid random(1,100000000)
select import_test(:uid);
pgbench -M prepared -n -r -P 1 -f ./test1.sql -c 56 -j 56 -T 120   

number of transactions actually processed: 11220725
latency average = 0.599 ms
latency stddev = 5.452 ms
tps = 93504.532256 (including connections establishing)
tps = 93512.274135 (excluding connections establishing)

黑科技

1、块级索引(BRIN),在时序属性字段上,建立块级索引,既能达到高效检索目的,又能节约索引空间,还能加速写入。

《PostgreSQL BRIN索引的pages_per_range选项优化与内核代码优化思考》

《万亿级电商广告 - brin黑科技带你(最低成本)玩转毫秒级圈人(视觉挖掘姊妹篇) - 阿里云RDS PostgreSQL, HybridDB for PostgreSQL最佳实践》

《PostGIS空间索引(GiST、BRIN、R-Tree)选择、优化 - 阿里云RDS PostgreSQL最佳实践》

《自动选择正确索引访问接口(btree,hash,gin,gist,sp-gist,brin,bitmap...)的方法》

《PostgreSQL 并行写入堆表,如何保证时序线性存储 - BRIN索引优化》

《PostgreSQL 9种索引的原理和应用场景》

2、阿里云HDB PG特性:sort key , metascan

与BRIN类似,适合线性数据,自动建立块级元数据(取值范围、平均值、CNT、SUM等)进行过滤。

3、空间索引

GiST, SP-GiST空间索引,适合空间数据、以及其他异构数据。

4、动态合并写,根据位置变化量,自动判断是否需要合并更新。

insert on conflict语法,在do update里面,可以进行条件过滤,当位置变化超过N米时,才进行更新。

5、数组、JSON、KV等多值类型。

特别适合多值属性,例如批量上传的轨迹,通常GPS终端上报位置并不是实时的,可能存在一定的 延迟(例如批量上报)。使用数组、JSON都可以存储。

如果使用数组存储,将来分析轨迹时,依旧可以unnest解开,绘制轨迹。

性能

1、动态位置变更:1亿被跟踪对象,TPS:21.6万,动态更新21.6万点/s,187亿点/天。

2、轨迹写入:tps约10万,写入467.5万点/s,4039亿点/天。

参考

《PostGIS 空间数据学习建议》

《PostgreSQL + PostGIS + SFCGAL 优雅的处理3D数据》

《PostGIS 距离计算建议 - 投影 与 球 坐标系, geometry 与 geography 类型》

《PostgreSQL 10 + PostGIS + Sharding(pg_pathman) + MySQL(fdw外部表) on ECS 部署指南(适合新用户)》

《PostGIS 空间索引(GiST、BRIN、R-Tree)选择、优化 - 阿里云RDS PostgreSQL最佳实践》

《PostGIS 坐标转换(SRID)的边界问题引发的专业知识 - ST_Transform》

《无人驾驶背后的技术 - PostGIS点云(pointcloud)应用 - 2》

《无人驾驶背后的技术 - PostGIS点云(pointcloud)应用 - 1》

《geohash vs PostGIS》

《视觉挖掘与PostGIS空间数据库的完美邂逅 - 广告营销\圈人》

《PostGIS 点面叠加视觉判断输出》

《PostGIS 多点几何类型 空字符构造异常CASE》

《开放地图OpenStreetMap与PostGIS的三生三世十里桃花》

《PostGIS 地理信息、栅格数据 多核并行处理(st_memunion, st_union)》

《蜂巢的艺术与技术价值 - PostgreSQL PostGIS's hex-grid》

《如何建立GIS测试环境 - 将openstreetmap的样本数据导入PostgreSQL PostGIS库》

《GIS附近查找性能优化 - PostGIS long lat geometry distance search tuning using gist knn function》

时间: 2024-10-03 17:31:00

PostgreSQL 实时位置跟踪+轨迹分析系统实践 - 单机顶千亿轨迹/天的相关文章

百亿级全网舆情分析系统存储设计

前言 在时下互联网信息的浪潮下,信息的传播速度远超我们的想象.微博里一条大V的帖子,朋友圈的一个状态更新,热门论坛的一条新闻,购物平台的购物评价,可能会产生数以万计的转发,关注,点赞.如果是一些非理性负面的评论会激发人们的负面感,甚至影响到消费者对企业品牌的认同,如果不能及时的采取正确的应对措施,会造成难以估计的损失.所以我们需要一个高效的全网舆情分析系统,帮助我们实时的观测舆情. 这个全网舆情分析系统,可以实现百亿条网页数据的存储.实时新增网页的抓取和存储并能对新增网页做实时的元数据提取.有了

实时股票分析系统的架构与算法

[编者的话]如果能在一台服务器上应用人工智能和机器学习算法处理每天的股票交易,而自己则在夏威夷的海滩上享受生活,那将是多么惬意呀.虽然股票 价格的变化受多种因素的影响,世上也没有免费的午餐,但是有些公司依然能够借助于开源的机器学习算法和数据分析平台得到"更好.更健康.更便宜的午餐". 本文搜集并整理了一些如何实现实时股票分析系统的资料,从架构和算法两个层面给出了一种可行的方案. 虽然股票交易市场一直在持续地变化,经济力量.新产品.竞争.全球性的事件.法规.甚至是Tweet都 有可能引起

使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置)

原文:使用Socket通信实现Silverlight客户端实时数据的获取(模拟GPS数据,地图实时位置) 在上一篇中说到了Silverlight下的Socket通信,在最后的时候说到本篇将会结合地图.下面就来看看本文实现的功能: Silverlight 与服务器利用Socket通讯,实时从服务器获取数据(本文中的数据是地理坐标),由于没有GPS,所以本文在服务器写了一个构造新坐标的函数(本文是一个三角函数),然后利用Timer组件,实时调用,得到新的坐标,并将新的坐标发送给客户端,客户端接收到发

Hadoop连载系列之六:数据收集分析系统Chukwa

系列几篇文章中介绍了分布式存储和计算系统Hadoop以及Hadoop集群的搭建.Zookeeper集群搭建.HBase分布式部署等.当Hadoop集群的数量达到1000+时,集群自身的信息将会大量增加.Apache开发出一个开源的数据收集和分析系统-Chukwa来处理Hadoop集群的数据.Chukwa有几个非常吸引人的特点:它架构清晰,部署简单;收集的数据类型广泛,具有很强的扩展性;与 Hadoop 无缝集成,能完成海量数据的收集与整理. 1 Chukwa简介 ----------------

面向实时物流作业的板坯库管理系统

面向实时物流作业的板坯库管理系统        武钢2250mm热轧厂是国家"十五"重点建设工程,总投资40亿元人民币,计划年产350万吨优质钢卷.2250mm热轧厂板坯库是热轧工序与炼钢工序的生产缓冲环节,是武钢重要的生产物流中心,每日的进出库作业量和倒垛作业量高达3万吨.板坯库主要接收武钢第三炼钢厂的连铸板坯,实施板坯入库处理,然后按照轧制计划中的轧制顺序,实施板坯出库处理.板坯品种规格繁多,且板坯与用户定货合同相互对应,因此,必须按单个板坯进行管理,增加了板坯库管理的难度.图一是

学习笔记TF066:TensorFlow移动端应用,iOS、Android系统实践

TensorFlow对Android.iOS.树莓派都提供移动端支持. 移动端应用原理.移动端.嵌入式设备应用深度学习方式,一模型运行在云端服务器,向服务器发送请求,接收服务器响应:二在本地运行模型,PC训练模型,放到移动端预测.向服务端请求数据可行性差,移动端资源稀缺.本地运行实时性更好.加速计算,内存空间和速度优化.精简模型,节省内存空间,加快计算速度.加快框架执行速度,优化模型复杂度和每步计算速度. 精简模型,用更低权得精度,量化(quantization).权重剪枝(weight pru

清晰模糊图片 VICS专业视频图像处理分析系统

硅谷网讯 专业视频图像处理分析系统是国家要求公安系统必须配备的一种视频侦查装备,具有视频图像增强.比对.截取.转换.检索等视频图像处理分析功能,可以自动完成视频图像的去雾.去眩光.对比度提升和亮度调节等图像增强工作. 公安机关必须配备专业视频图像处理分析系统 随着视频监控技术的不断发展,视频监控在智慧城市.数字城市.平安园区等各类项目得以广泛应用,监控视频已经成为公安部门案件侦查的重要依据和线索,视频侦查已逐步成为继刑侦,技侦,网侦之后的第四大侦查手段.然而,由于缺乏有效的信息技术支撑,公安视频

自定义View系列教程04--Draw源码分析及其实践

探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Android多分辨率适配框架(3)- 使用指南 自定义View系列教程00–推翻自己和过往,重学自定义View 自定义View系列教程01–常用工具介绍 自定义View系列教程02–onMeasure源码详尽分析 自定义View

腾讯分析系统架构解析

TA(Tencent Analytics,腾讯分析)是一款面向第三方站长的免费网站分析系统,在数据稳定性.及时性方面广受站长好评,其秒级的实时数据更新频率也获得业界的认可.本文将从实时数据处理.数据存储等多个方面带你深入探寻TA的系统架构及实现原理. 网站分析(Web Analytics)主要指的是基于网站的用户浏览行为,对网站的点击流数据和运营数据进行分析,以监控网站的运营状况,为网站的优化提供决策依据.网站 分析系统已成为站长日常运营必不可少的工具,业界比较流行的网站分析系统主要有Googl