背景介紹:廣(guang)州市(shi)雅(ya)恒信息科技有(you)限公司專注提供優質的互聯網(wang)整(zheng)體(ti)解決方案(an),在(zai)數(shu)字治(zhi)理(li)系統開(kai)發有(you)著(zhu)成(cheng)熟豐富的經驗(yan)。數(shu)字治(zhi)理(li)系統是基(ji)于城鄉(xiang)治(zhi)理(li)的概念(nian),對(dui)治(zhi)理(li)過程進行(xing)信息化的記錄(lu)和管理(li),并加(jia)以大數(shu)據(ju)分析、智能硬(ying)件(jian)監(jian)測和無人(ren)機巡查(cha)輔助(zhu)。城鄉(xiang)治(zhi)理(li)是指基(ji)層政(zheng)府對(dui)行(xing)政(zheng)區(qu)域(yu)內進行(xing)網(wang)絡的劃分,并將每(mei)個網(wang)格責任到網(wang)格員(yuan),網(wang)格員(yuan)通過開(kai)展巡查(cha)活動,對(dui)發現的問(wen)題(ti)進行(xing)上報、交辦、處理(li)、跟(gen)蹤的過程。
巧遇TDengine
2019年(nian)首次聽說(shuo)TDengine Database,真正接(jie)觸是從收到(dao)(dao)一(yi)個(ge)直播(bo)的(de)(de)鏈接(jie)轉發,陶建輝老(lao)師(shi)在(zai)極客(ke)時(shi)間(jian)直播(bo),標題這樣描述(shu):35年(nian)碼(ma)齡老(lao)程序員給您講述(shu)TDengine的(de)(de)超高性能是如何(he)實(shi)現(xian)(xian)的(de)(de)。直播(bo)現(xian)(xian)場(chang),陶老(lao)師(shi)大汗淋漓(li),大家都在(zai)說(shuo)沒(mei)開空調,主持人解釋(shi),陶老(lao)師(shi)現(xian)(xian)在(zai)高燒,堅(jian)持給大家講解。感性與(yu)理(li)性。之后(hou),深(shen)圳見面會,老(lao)板時(shi)間(jian)挺(ting)忙,趕在(zai)最后(hou)一(yi)天去的(de)(de),沒(mei)有見到(dao)(dao)陶老(lao)師(shi),見到(dao)(dao)了(le)我們的(de)(de)侯老(lao)師(shi)。一(yi)聊,相見恨(hen)晚(wan)。

場景介紹
雅恒做了接近兩年的“基層數字網格管理系統”。這個管理系統能夠對鎮街進行大小網格的劃分,以網格內建筑和核心部件為基本信息點,在網格內開展消防、禁毒、環衛、兩違等巡查活動,并形成規范上傳、下達工作流程規范。但我們這段時間其實也在琢磨這個系統的架構是不是已經老了,該如何優化呢?這時候正好通過TDengine了解到時序數據庫(Time-Series Database)的概念,應用后雖然不能一步到位把系統做一個(ge)很大的提升,但產品不是應該這樣一點(dian)點(dian)改進嗎?
在我(wo)們的應用場景(jing)中,網格員在使(shi)用app和(he)小程序進(jin)行(xing)巡(xun)查活動時(shi),每(mei)隔30秒會(hui)檢查一(yi)(yi)(yi)次(ci)移動距離(li),如果超過20米就(jiu)會(hui)上傳一(yi)(yi)(yi)個(ge)(ge)(ge)(ge)坐標(biao)到服務(wu)端。一(yi)(yi)(yi)個(ge)(ge)(ge)(ge)街道(dao)大(da)約有100名網格員,每(mei)月(yue)有效巡(xun)查距離(li)超過100公里,一(yi)(yi)(yi)年約1200000米;一(yi)(yi)(yi)個(ge)(ge)(ge)(ge)街道(dao)一(yi)(yi)(yi)年就(jiu)會(hui)產生約6000000條(tiao)坐標(biao)記錄(lu)(武漢大(da)約有一(yi)(yi)(yi)萬七千名網格員)。我(wo)們有可能隨(sui)時(shi)翻閱三年前某條(tiao)巡(xun)查線(xian)路。按原關(guan)系數(shu)據(ju)庫(ku)的結構設計,這就(jiu)需(xu)要(yao)(yao)從坐標(biao)記錄(lu)表里根據(ju)巡(xun)查線(xian)路id檢索出一(yi)(yi)(yi)個(ge)(ge)(ge)(ge)個(ge)(ge)(ge)(ge)的坐標(biao)點,然(ran)后重組成一(yi)(yi)(yi)條(tiao)巡(xun)查線(xian)路。三年的記錄(lu)總量接近2000萬條(tiao),此(ci)時(shi)關(guan)系型數(shu)據(ju)庫(ku)的查詢響應應急(ji)非常慢(man),必須要(yao)(yao)通過按照時(shi)間分庫(ku)分表來提高性能,但隨(sui)之(zhi)而來的問題就(jiu)是遇到跨庫(ku)跨表查詢時(shi)間段處(chu)理的麻(ma)煩(想(xiang)想(xiang)就(jiu)覺(jue)得累)。
我們基(ji)于TDengine Database的特性以及使用原則,把坐標(biao)記錄(lu)數據(ju)遷移到這上面來(lai):
- 一個網格賬號一張坐標記錄表,這個網格員巡查產生的坐標記錄全都按時間順序記錄到這個表上來;
- 巡查線路坐標點的檢索按線路的巡查時間范圍,時序數據庫對時間的處理是天生的優勢,這樣也降低了跨庫的耦合;
- 我們還借助了微服務低耦合易擴展的特性,獨立出坐標讀寫模塊,以下是完整的系統架構,供參考,歡迎批評指正。

用戶直接(jie)交(jiao)互(hu)(hu)的(de)(de)是應用層(ceng),包含:瀏覽器(qi)的(de)(de)Web應用、微信(xin)小程序或者Android平臺(tai)的(de)(de)App。其(qi)中Web應用還與GIS系(xi)統(tong)進行交(jiao)互(hu)(hu)獲取地圖瓦片和坐標(biao)載入顯示等(deng)信(xin)息。支(zhi)撐應用層(ceng)的(de)(de)是業務(wu)運(yun)算后(hou)臺(tai)服(fu)務(wu),包含用戶管理(li)、權限管理(li)、問(wen)題管理(li)等(deng)業務(wu)運(yun)算。底(di)層(ceng)存儲使用了MySQL+ TDengine的(de)(de)配合。業務(wu)運(yun)算后(hou)臺(tai)還會與其(qi)他(ta)門(men)戶數據中心的(de)(de)第三方服(fu)務(wu)進行交(jiao)互(hu)(hu),實(shi)現(xian)整(zheng)個數字治理(li)系(xi)統(tong)的(de)(de)各項(xiang)需(xu)求。
底(di)層數(shu)據(ju)(ju)存(cun)儲(chu)上的(de)思考(kao)是這樣的(de)。業務(wu)邏輯相關的(de)數(shu)據(ju)(ju)需要大(da)量(liang)賬號(hao)信(xin)息管理、關聯(lian)查詢(xun)、業務(wu)從屬處理,是典(dian)型關系數(shu)據(ju)(ju)庫(ku)應用場景(jing)(jing),因(yin)此這部分數(shu)據(ju)(ju)存(cun)入(ru)MySQL;巡查坐標數(shu)據(ju)(ju)是前文提到(dao)的(de)海量(liang)時(shi)序(xu)位置信(xin)息,涉(she)及更多的(de)是按時(shi)間讀取數(shu)據(ju)(ju),按照賬號(hao)計(ji)算(suan)(suan)軌跡等,是典(dian)型的(de)時(shi)序(xu)結構(gou)化(hua)數(shu)據(ju)(ju)儲(chu)存(cun)分析場景(jing)(jing),非常適合存(cun)入(ru)TDengine。這里(li)把(ba)位置數(shu)據(ju)(ju)從原來的(de)MySQL中摘出(chu)來后(hou),通過一(yi)個坐標計(ji)算(suan)(suan)微服務(wu)來轉存(cun)、計(ji)算(suan)(suan)巡查坐標數(shu)據(ju)(ju),實現(xian)了原有的(de)業務(wu)運算(suan)(suan)后(hou)臺與TDengine之間的(de)交互,且不對原來的(de)運算(suan)(suan)后(hou)臺產(chan)生(sheng)大(da)量(liang)代碼改動,非常方便。
數據模型
遵循一(yi)臺設(she)(she)(she)備一(yi)張表的設(she)(she)(she)計思(si)路。在我們系統中是一(yi)個(ge)用戶一(yi)張表,用于(yu)記錄該用戶的所有歷史軌跡信息。所有子表都(dou)基于(yu)一(yi)個(ge)名為“super”的超級表創建,將設(she)(she)(she)備ID定義成一(yi)個(ge)tag,用于(yu)對表進行區分(fen)。
快速開發
封裝(zhuang)好API,直接用Spring Boot調用JDBC來與(yu)TDengine數(shu)據源(yuan)交(jiao)互即可。下(xia)面的示例中,使用Spring Boot+TDengine實(shi)時存儲GPS坐標,實(shi)現過程非常的簡單。
第一步 在Linux上(shang)開啟TDengine服務(wu);
第二步?創建一個的(de)Spring Boot項目,在application.properties中配置(zhi)TDengine的(de)連接(jie)信(xin)息(xi)(ps:端口默(mo)認(ren)為0,用(yong)戶名默(mo)認(ren)為root,密碼默(mo)認(ren)為taosdata);
server.port=8085
server.servlet.context-path=/api
#taos
taosdata.url=jdbc:TAOS://192.168.1.241:0/db?user=root&password=taosdata
taosdata.driverClassName=com.taosdata.jdbc.TSDBDriver
第三步 在pom.xml中配置相(xiang)關(guan)依賴,下(xia)載jar包(bao);
<!-- taos Start -->
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>1.0.1</version>
</dependency>
<!-- taos END -->
第四步 建立(li)config文件,對應application.properties中(zhong)的url和(he)driverClassName;
@Component
@ConfigurationProperties(prefix = “taosdata”)
public class TaosdataConfig {
private String url;
private String driverClassName;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
}
第五步 實現(xian)相關業務邏輯(ps:與傳(chuan)統關系型數(shu)據庫一(yi)樣,采用sql語法)。創建庫,建表,插(cha)入,查詢等操作在Java中實現(xian)如下。
建庫、建表:
String sql1 = “create database if not exists coor”;
stmt.executeUpdate(sql1);
String sql2 = “use coor”;
stmt.executeUpdate(sql2);
String sql3 = “create table if not exists super (ts timestamp, lng double, lat double) tags (id nchar(32))”;
stmt.executeUpdate(sql3);
String sql4 = “create table if not exists “ + (“u” + userid) + “using super tags(‘” + userid + “’)”;
stmt.executeUpdate(sql4);
插入數據:
String sql5 = insert into “ + (“u” + userid) + “ values(“ + now.getTime()+”,” + lng + “,” + lat + “)”;
stmt.executeUpdate(sql5);
查詢:
StringBuilder sql6 = new StringBuilder(“select * from u”)
.append(userid)
.append(“ where ts>=’”)
.append(stime)
.append(“’ and ts <= ‘”)
.append(etime)
.append(“’”);
ResultSet resSet = stmt.executeQuery(sql6.toString());
Timestamp ts = null;
while(resSet.next()) {
ts = resSet.getTimestamp(“ts”);
lng = resSet.getDouble(“lng”);
lat = resSet.getDouble(“lat”);
//業務處理略去…
}
總結
雅(ya)恒(heng)通過(guo)將網格巡查位置數據(ju)從關系(xi)庫MySQL轉存入時序庫TDengine后(hou),解決了大(da)數據(ju)量(liang)、長周期查詢時的(de)性能(neng)和(he)易用性問題(ti),避免了分(fen)(fen)庫分(fen)(fen)表(biao)維護(hu)的(de)麻煩。通過(guo)微服務的(de)方式把TDengine集成進原有系(xi)統,提供時序數據(ju)存儲和(he)計(ji)算服務,整體上對原有系(xi)統沖擊很小,遷移(yi)改造(zao)比較順利(li)。數據(ju)壓縮(suo)率可能(neng)也(ye)(ye)是(shi)一個很有價(jia)值的(de)考量(liang)目標。后(hou)續也(ye)(ye)許會繼續查看TDengine自帶的(de)流計(ji)算等功(gong)能(neng),看是(shi)否能(neng)進一步減輕業務層的(de)計(ji)算壓力(li),提高(gao)計(ji)算資源利(li)用率。
作者簡介
黃(huang)勇,畢業于湖(hu)南工學院,從事Java開(kai)(kai)發(fa)工作多年,目(mu)前(qian)是雅恒核心研發(fa)成員。曾主持(chi)廣(guang)東省政法委基層網(wang)格化管理系統(tong)的(de)開(kai)(kai)發(fa)工作,并深度(du)參與過廣(guang)州市番禺區教育局(ju)教育信息素養提升平臺、海幢寺噪音(yin)監測系統(tong)等系統(tong)工程的(de)開(kai)(kai)發(fa)工作。
原文首發于雅恒科(ke)技公眾號,鏈接:


























