巨头垂涎却不能染指,loT 数据库风口已至

 

 

作者 | 马超

责编 | 胡巍巍

出品 | CSDN(ID:CSDNnews)

随着移动端发展走向饱和,现在整个IT行业都期待着“万物互联”的物联网时代所带来的流量红利,前期笔者也曾经撰文介绍国产物联网操作系统的情况(https://blog.csdn.net/BEYONDMA/article/details/101147942),我们可以看到BAT等巨头们的逻辑是要让其它公司免费使用其OS上车控制住入口,引导使用物联网行业新秀接入其loT云平台,创业成者直接收购,无缝整合进入自身体系;失败者任其自生自灭,从而让巨头自身完全立于不败之地。

一般物联网的信息传递流程如下,先由终端接入层完成数据的采集,再插入数据库,然后再进行展示及后续的大数据分析。

在终端入口层我们可以看到国内厂商相继发布并开源了鸿蒙LiteOS、Tencent Tiny OS、Ali Things 3.0,展示分析及大数据层各巨头不缺少相应强大手段,不过在承上启下的物联网数据层还是巨头们的留白,所以目前还没有哪家巨头能够完全控制整个物联网的信息链条,物联网数据库将会迎来一波巨大的发展机遇。

 

 

天下武功唯快不破,传统数据库没有物联网的速度基因

 

BAT们并不是没有杀手组级的数据库产品,比如前几天阿里的OceanBase就以很好的成绩在TPC-C测试中夺冠,笔者也曾经撰文介绍过OceanBase的相应情况(https://blog.csdn.net/BEYONDMA/article/details/102089673),不过传统数据库其底层逻辑是不能错,比如在“双十一”秒杀时,在并发请求超限的极端情况下,数据库可以放弃处理某些请求,但是已经处理的请求是绝不能允许出错的。

而且“增删改查”是传统数据库的最基本任务,在执行上述任务的过程中对于准确性的要求是第一位的。

而物联网时代产生的数据量比互联时代时代大了一个数量级,但是其数据的价值密度,也相对较低,loT终端往往都是一些传感器,其自身单点设备可靠性有限,一般都是靠多点这冗余相互验证来保证整体稳定性的,但如果数据不能及时采集就会丢失,因此物联网时对于数据库的要求聚焦于速度与效率,这正是时序数据库所擅长的。

如果用汽车类比,传统数据库的最高目标是做类似迈巴赫、宾利这样的顶级家用轿车以安全优先;而物联网则要做类似于法拉利这样为速度而生的跑车。

 

时序数据库的数据存储设计

 

在典型的物联网场景中,往往有许多各类不同的终端设备,布署在不同的位置,去采集各种数据,比如某一生产区有5万个终端,每个终端每10秒发送一次数据。那么每年会产生1600亿个数据点。

而这些数据都是顺序产生的,并且每次监测产生数据的格式全部是一致的、结构化的,并且没有删除和修改的需求,所以时序数据库一般使用LSM Tree模型,从而将随机写转化为顺利写,以提升效率。典型的LSM模型如下:

 

WAL:在设计数据库的时候经常被使用,当插入一条数据时,数据先顺序写入 WAL 文件中,之后插入到内存中的 MemTable 中。这样就保证了数据的持久化,不会丢失数据,并且都是顺序写,速度很快。当程序挂掉重启时,可以从 WAL 文件中重新恢复内存中的 Cache。

Cache(MemTable):Cache 对应的就是 WAL 文件,是该文件内容在内存中的存储结构,通常用 SkipList 来实现。Cache一般 k-v 数据的写入、删除以及读取的操作接口。其内部将 k-v 对按照 key 值有序存储,这样方便之后快速序列化到 SSTable 文件中,仍然保持数据的有序性。

TSM File:由于内存是有限的,通常时序数据库会设一个阀值,当Cache占用的内存达到阀值后就自动转换为TSM File,一般来说TSM file会使用与Cache不同的文件格式,对查询及压缩进行优化。

Compactor:一般就是压缩转存的模块,当Cache到达阈值后使用Compactor将其转录到TSM File中。

写操作过程:在这种模型下写入是相当快速的,只需要在 WAL 文件中顺序写入本轮采集的数据,然后转录入内存Cache,而在Cache到达阈值后的转录为TSM File操作,不是每轮数据采集都需要执行,效率比传统关系型数据库的存储方式肯定高得多。

 

当然以上是时序数据库的通用做法,而某些时序数据库针对物联网场景,有针对性的做了很多优化工作,其中TDEngine就使用了数据时序性和结构化的特点,要求对每个采集设备单独建表。

其实我们刚刚也提到了每个物联终端所产生的数据其实都是时序且结构化的,所以对每个设备单独建表能够充分发挥出数据时序化的优势,进一步提升效率。

Prometheus为了效率则更是只支持Numeric data的处理,字符串类型是不被支持的,不过想想这也合理,因为物联网所采集的数据一般都不是文字型的,放弃对于字符串的支持也未尝不可。

 

古老的话题:时序数据库编程语言之争

 

我们前文也提到了可以把时序数据库比做以速度为生的跑车,不过之前主流的时序数据库一般都是用Go或者Java开发的。

其中使用C开发的TimescaleDB还是基于传统关系型数据库PostgreSQL 进行的二次开发,本质上并不是完整的时序数据库。

 

 所以前一段时间使用C语言开发的国产时序数据库TDEngine宣布开源并正式发布后,在性能上对于其它时序数据库形成全面碾压的态势其实并不奇怪。原因无外乎有以下两点:

1.数据库做为一种特殊的应用软件,需要更多的底层操作:我在之前的文章中也曾经介绍过TDEngine为了减少线程数量,降低上下文切换的损耗,自身实现了一个定时器服务,详见(https://blog.csdn.net/BEYONDMA/article/details/98473143)。

也就是数据库在很多时候不能直接使用系统调用,那样效率太低。而在实现系统级功能时C语言的优势非常明显。

2.大量的数据读写及索引操作,会频繁触发GC:我们知道无论是GO还是JAVA都会有自动垃圾的清理机制(GC),虽然据称华为方舟编译器的出现将大幅提升GC的效率,不过无论如何物联网天量的数据读取,尤其是索引操作,肯定会频繁触发GC,而这也必将牺牲一部分性能。

其实以速度至上的物联网时序数据库,并不太能发挥出GO及JAVA等高级语言的长处,而C语言在这种平台级软件的开发上反而有得天独厚的优势。

 

时序数据库整合趋势明显

 

TDEngine这种C语言的数据库能够战胜InfluxDB、OpenTSDB我并不感到奇怪,不过当我看到测试报告(https://www.taosdata.com/downloads/TDengine_Testing_Report_cn.pdf)发现在单机环境下连接数增加到20个TDengine的处理还能游刃有余,而openTSDB等数据库达到3个连接就出现crash现象,这个情况让笔者感到特别好奇,由于以上项目都是开源的,所以我又翻阅了一下相关代码发现最重要的原因是TDengine使用线程处理连接,而其它时序库大多通过folk进程处理连接。

 

当然TD将缓存、消息队列等功能整合的设计也非常值得称道,其架构如下所示:

 

从https://github.com/taosdata/TDengine/blob/master/src/client/src/tscServer.c中的函数tscGetConnToMgmt,

其实是使用taosGetConnFromCache函数从缓存中取链接,这样速度肯定会提高,具体代码如下:

void tscGetConnToMgmt(SSqlObj *pSql, uint8_t *pCode) { STscObj *pTscObj = pSql->pTscObj;
 if (pSql->retry < 1) {
   *pCode = 0;
   pSql->retry++;
   void *thandle = taosGetConnFromCache(tscConnCache, tsServerIp, TSC_MGMT_VNODE, pTscObj->user);//有缓存层
   if (thandle == NULL) {
     SRpcConnInit connInit;
     memset(&connInit, 0, sizeof(connInit));
     connInit.cid = 0;
     connInit.sid = 0;
     connInit.meterId = pSql->pTscObj->user;
     connInit.peerId = 0;
     connInit.shandle = pTscMgmtConn;
     connInit.ahandle = pSql;
     connInit.peerPort = tsMgmtShellPort;
     connInit.spi = 1;
     connInit.encrypt = 0;
     connInit.secret = pSql->pTscObj->pass;
     connInit.peerIp = tsServerIpStr;
     thandle = taosOpenRpcConn(&connInit, pCode);
}
   
   pSql->thandle = thandle;
   pSql->ip = tsServerIp;
   pSql->vnode = TSC_MGMT_VNODE;
 }
}

TDengine缓存功能实现的https://github.com/taosdata/TDengine/blob/master/src/client/src/tscCache.c,其基本的工作原理总结是这样,有空建议大家细读:

1.初始化:首先初始化缓存对象SConnCache,再初始化哈希表connHashList,并调用taosTmrReset,重置timer(这也就是咱们上次解读的timer)

2.链接加入缓存:首先通过ip、port、username计算其哈希值(hash),然后将此链接(connInfo)加入connHashList[hash]对应的pNode节点,pNode本身又是一个双链表,也会根据添加时间将哈希值相同的connInfo排序,放入pNode双链表中。注意这里pNode是哈希表connHashList的一个节点,而其自身也是一个链表。

3.将链接由缓存中取出:根据ip、port、username计算其哈希值(hash),取出connHashList[hash]对应的pNode节点,再从pNode当中取出ip、port与需求相同的元素。

而这样的设计,对比建立几个链接就会崩溃的OpenTSDB真是要高出几个数量级。

 

写在最后

 

随着物联网时代的到来,国产操作lot操作系统迎来一波集体的强势崛起,但是国产IoT数据库却不似那么兴旺,除了Tdengine外,只有百度云TSDB产品有对外发布,不过也不成熟。由于和传统关系型数据库底层逻辑不同,时序数据库还属于新兴事物,这恰恰也是给我国相关产业弯道超车的一次机会。

而且笔者在本文中也提到了,时序数据库在物联网应用中还大有整合其它中间件的趋势,可谓是风口已至,但巨头未至,今后必将迎来巨大机遇期。

作者简介:本文为CSDN博主马超(ID:beyondma)的原创约稿文章。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页