开源纯C#工控网关+组态软件(七)数据采集与归档
?一、???引子
?在當(dāng)前自動(dòng)化、信息化、智能化的時(shí)代背景下,數(shù)據(jù)的作用日漸凸顯。而工業(yè)發(fā)展到如今,科技含量和自動(dòng)化水平均顯著提高,但對(duì)數(shù)據(jù)的采集、利用才開(kāi)始起步。
對(duì)工業(yè)企業(yè)而言,數(shù)據(jù)采集日益受到重視,主要應(yīng)用場(chǎng)景包括:
節(jié)能降耗。投入(如車(chē)間的水電氣能耗、設(shè)備工時(shí)、原料耗用)和產(chǎn)出(產(chǎn)量、批數(shù))這些成本核算的關(guān)鍵數(shù)據(jù)通過(guò)傳感器采集,取代人工抄表已成為趨勢(shì)。
績(jī)效考評(píng)。投入、產(chǎn)出、損耗、工時(shí)數(shù)據(jù),其對(duì)管理者的決策支持、對(duì)員工的績(jī)效評(píng)估都很重要。
批次追溯。食品安全形勢(shì)日益嚴(yán)峻,對(duì)物料的追溯也成為國(guó)家硬指標(biāo)。追溯就是追根溯源,批次生產(chǎn)的每個(gè)環(huán)節(jié)都需要數(shù)據(jù)跟蹤。
設(shè)備管理。如設(shè)備的運(yùn)行時(shí)長(zhǎng)對(duì)于設(shè)備保養(yǎng)、故障頻率對(duì)于設(shè)備維護(hù)、設(shè)備參數(shù)對(duì)于工藝優(yōu)化。
數(shù)據(jù)既然如此重要,對(duì)于SCADA不但必須有,而且高要求:
準(zhǔn)確性。信號(hào)不能失真,采集精度和時(shí)間戳盡可能精確;也不能帶入太多干擾和噪音。
完整性。信號(hào)不能頻繁丟失、丟步、跳步,萬(wàn)一信號(hào)斷開(kāi),要快速重連,或者有冗余機(jī)制。
大容量。大數(shù)據(jù),首先要能撐的起這個(gè)“大”。大項(xiàng)目動(dòng)輒幾萬(wàn)點(diǎn),采集頻率又高,一天下來(lái)數(shù)據(jù)量都驚人,日積月累更是天量。例如對(duì)于 1萬(wàn)點(diǎn)的系統(tǒng), 1秒鐘存儲(chǔ)一次,每次單點(diǎn)占用 8字節(jié),保存 10年的數(shù)據(jù)量將有 10000*8*10*365*86400=25228800000000字節(jié),也就是 23TGB。若用 80GB硬盤(pán)存放,需 293塊硬盤(pán)。如此龐大的數(shù)據(jù)量,還要求快速插入、快速查詢。
要實(shí)現(xiàn)這些指標(biāo),非常具有挑戰(zhàn)性。
二、???實(shí)時(shí)庫(kù)與歷史庫(kù)
概述
工控環(huán)境特殊性在于,大量測(cè)點(diǎn)快速變化,需高速存取, IO密集型;數(shù)據(jù)結(jié)構(gòu)簡(jiǎn)單規(guī)則,無(wú)非就是名稱(chēng)/ID、值、時(shí)間戳這些;數(shù)據(jù)流式存儲(chǔ),只需在尾部插入,不刪不改。
因此常規(guī)的關(guān)系數(shù)據(jù)庫(kù)不僅存取速度跟不上,也顯得殺雞用牛刀。實(shí)時(shí)庫(kù)和歷史庫(kù)就是為工業(yè)環(huán)境準(zhǔn)備的,測(cè)點(diǎn)的實(shí)時(shí)數(shù)據(jù)存儲(chǔ)在內(nèi)存,保證最快的存取速度;數(shù)據(jù)超過(guò)一定范圍需要轉(zhuǎn)儲(chǔ)入歷史庫(kù),我這里用了自定義格式的二進(jìn)制文件,力求數(shù)據(jù)單元空間占用最小化、同時(shí)查詢速度最大化。
實(shí)時(shí)庫(kù)
測(cè)點(diǎn)數(shù)據(jù)在內(nèi)存中,包含【下位機(jī)映射緩存:ICache】→【快照數(shù)據(jù)集:TagList】→【歷史數(shù)據(jù)緩存:HistoryList】這樣的三級(jí)結(jié)構(gòu)。
ICache是下位機(jī)當(dāng)前數(shù)據(jù)的緩存,隨掃描過(guò)程實(shí)時(shí)更新,繼承IReaderWriter接口,可讀可寫(xiě),可以通過(guò)Tag的Read\Write讀取和更新。
對(duì)當(dāng)前所有測(cè)點(diǎn)數(shù)據(jù)的快照查詢,可以通過(guò)Tag的清單列表MetaTagList結(jié)合神器Linq實(shí)現(xiàn)。Linq對(duì)內(nèi)存列表數(shù)據(jù)的查詢能力可以說(shuō)既強(qiáng)大又優(yōu)雅,這是微軟送給C#碼農(nóng)的禮物,不再贅述。
測(cè)點(diǎn)數(shù)據(jù)改變就會(huì)生成一條新的記錄。這些記錄如馬上轉(zhuǎn)儲(chǔ)到數(shù)據(jù)庫(kù)或文件,則測(cè)點(diǎn)數(shù)量多變化快,其IO是系統(tǒng)不能承擔(dān)之重。但如果測(cè)點(diǎn)記錄堆積過(guò)多不及時(shí)清理,則一方面可靠性下降,如系統(tǒng)崩潰、斷電就會(huì)發(fā)生大量數(shù)據(jù)點(diǎn)丟失,同時(shí)內(nèi)存占用越來(lái)越大,影響系統(tǒng)性能。所以測(cè)點(diǎn)歷史數(shù)據(jù)的緩存容量應(yīng)可根據(jù)測(cè)點(diǎn)數(shù)量和存取頻率自適應(yīng)或由用戶自定義。
歷史庫(kù)
海量的測(cè)點(diǎn)數(shù)據(jù),普通關(guān)系數(shù)據(jù)庫(kù)是難以招架的。如SQL SERVER免費(fèi)版只有4-10個(gè)G上限。而這個(gè)容量可能一個(gè)月就溢出了。
因此,為了適應(yīng)天量數(shù)據(jù),就需要二進(jìn)制文件存儲(chǔ)。有人會(huì)問(wèn)為啥不用NO SQL,Hadoop這些高大上的東東,我的觀點(diǎn)是不追求高大上,因?yàn)楣た財(cái)?shù)據(jù)不同于搜索引擎,都是簡(jiǎn)單而標(biāo)準(zhǔn)的結(jié)構(gòu)。可以根據(jù)其特點(diǎn)進(jìn)行有針對(duì)性的設(shè)計(jì),無(wú)需部署復(fù)雜的NO SQL架構(gòu)也一樣可以實(shí)現(xiàn)高性能。
歷史數(shù)據(jù)庫(kù)要最大限度的壓縮數(shù)據(jù),同時(shí)又要保證快速插入、快速查詢。
如何保證數(shù)據(jù)單元最小化?
分析存儲(chǔ)結(jié)構(gòu),一條記錄包括變量名、當(dāng)前值、時(shí)間戳。
變量名可能為一個(gè)長(zhǎng)字符串,數(shù)據(jù)量大之后顯然是過(guò)于冗長(zhǎng)。因此代之以ID號(hào)(2字節(jié))。還可以進(jìn)一步壓縮,如相同變量存在一起,ID也可以省了。
當(dāng)前值大部分是浮點(diǎn)數(shù),4字節(jié),這個(gè)不能縮減,否則影響數(shù)據(jù)精度。
時(shí)間戳為DateTime,要占8字節(jié),但如果數(shù)據(jù)按日排序,日期部分省去,4個(gè)字節(jié)的時(shí)間部分就可以精確到毫秒。
這樣,通過(guò)合理設(shè)計(jì)存儲(chǔ)結(jié)構(gòu),一條記錄可以壓縮到8個(gè)字節(jié)(開(kāi)關(guān)量5個(gè)字節(jié))。
如何保證快速插入記錄?
存檔文件日積月累肯定是越來(lái)越龐大,如果采用覆蓋式寫(xiě)入或更新寫(xiě)入,不僅可靠性下降,讀寫(xiě)成本也越來(lái)越高。想快速插入必須保證每次寫(xiě)入不改變?cè)瓉?lái)的數(shù)據(jù),僅僅在末尾追加。
如何保證快速查詢?
首先為保證可靠性和數(shù)據(jù)容量限制,數(shù)據(jù)分月存放。文件名為【年-月.bin】。如需跨月查詢,按文件名搜索拼接即可。開(kāi)頭256個(gè)字節(jié)存放日期索引。32*8字節(jié),對(duì)應(yīng)每日記錄的頭指針,也即上一日記錄的末尾。
主索引下,每一天的記錄頭為日內(nèi)索引區(qū)。包含一個(gè)索引數(shù)組,每一項(xiàng)索引有變量ID、變量長(zhǎng)度、數(shù)量。如要查某日某ID的變量,即可先找到ID,再根據(jù)其變量長(zhǎng)度*數(shù)量累加計(jì)算,即可定位到該變量的第一條記錄。
同一變量的記錄按時(shí)間戳順序排列。這樣,要定位到該變量某一時(shí)間的記錄,即可對(duì)時(shí)間戳采用二分法快速定位。
字符串類(lèi)型的歸檔比較特殊,專(zhuān)門(mén)在EventLog作為日志存取。
三、???數(shù)據(jù)轉(zhuǎn)儲(chǔ)流程
為什么要建立三級(jí)轉(zhuǎn)儲(chǔ)
數(shù)據(jù)在什么情況下會(huì)被采集?默認(rèn)是變化了采集。如果一個(gè)數(shù)據(jù)長(zhǎng)期不變,但需要定期采樣,可以設(shè)置歸檔周期:
?
數(shù)據(jù)被采集之后首先是存在內(nèi)存中。內(nèi)存的特點(diǎn)是快,小。存取快,但是容量有限,采樣數(shù)據(jù)堆積多了就要清理轉(zhuǎn)儲(chǔ)到關(guān)系數(shù)據(jù)庫(kù)。
為什么要多一層關(guān)系數(shù)據(jù)庫(kù)?因?yàn)椴蓸拥臄?shù)據(jù)是時(shí)間序列的,但最終二進(jìn)制文件的索引結(jié)構(gòu)按照變量-時(shí)間戳排布,比如依次排入變量A-13:40,變量B-13:41,變量A-13:42這樣一個(gè)時(shí)間序列,如直接寫(xiě)二進(jìn)制存檔文件就需按變量排序并重新整理寫(xiě)入,文件越大其寫(xiě)入效率越低,對(duì)系統(tǒng)拖累越大。而先轉(zhuǎn)儲(chǔ)到關(guān)系數(shù)據(jù)庫(kù),再定期將上一日的數(shù)據(jù)轉(zhuǎn)儲(chǔ)到二進(jìn)制文件,既可以充分利用關(guān)系數(shù)據(jù)庫(kù)的高性能批量插入功能(在SQL SERVER就是Sqlbulkcopy),又可利用關(guān)系庫(kù)的查詢排序能力,一舉兩得,轉(zhuǎn)儲(chǔ)之后數(shù)據(jù)庫(kù)記錄清空,也避免關(guān)系庫(kù)容量溢出的問(wèn)題。
由上所述,轉(zhuǎn)儲(chǔ)包含【歷史數(shù)據(jù)緩存:HistoryList】→【關(guān)系數(shù)據(jù)庫(kù):Log_HDA】→【二進(jìn)制文件:bin文件】三級(jí)。
每轉(zhuǎn)儲(chǔ)成功一次,上一級(jí)的數(shù)據(jù)就清空,保證每一級(jí)之間的數(shù)據(jù)不重疊。
這樣一來(lái),數(shù)據(jù)記錄就分布于三個(gè)位置:內(nèi)存、關(guān)系庫(kù)、二進(jìn)制文件。要查詢數(shù)據(jù),就需要對(duì)這三部分?jǐn)?shù)據(jù)進(jìn)行“拼接”。拼接的規(guī)則就是以當(dāng)前級(jí)最末一條記錄的時(shí)間戳為準(zhǔn)。如當(dāng)前級(jí)中沒(méi)有,就查下一級(jí)。
源頭:內(nèi)存數(shù)據(jù)庫(kù)
內(nèi)存數(shù)據(jù)庫(kù)是一個(gè)HistoryData列表。有兩種情況可以觸發(fā)清理:定期清理、溢出清理。定期清理是設(shè)置固定的周期。溢出就是超過(guò)一定大小,到時(shí)間就轉(zhuǎn)到關(guān)系庫(kù)。可由server.xml配置。
中介:關(guān)系數(shù)據(jù)庫(kù)
就是數(shù)據(jù)庫(kù)的Log_HDA表。承上(內(nèi)存)啟下(二進(jìn)制文件),暫存數(shù)據(jù)。也包含ID、值、時(shí)間戳這幾個(gè)字段。每天凌晨開(kāi)始,網(wǎng)關(guān)服務(wù)調(diào)用DataHelper內(nèi)部的WriteToFile方法(實(shí)際是調(diào)用關(guān)系庫(kù)的WRITEHDATA存儲(chǔ)過(guò)程),對(duì)暫存的測(cè)點(diǎn)記錄按時(shí)間、變量排序,轉(zhuǎn)儲(chǔ)到二進(jìn)制文件中。如寫(xiě)入失敗,判斷最后一個(gè)時(shí)間戳,下一次繼續(xù)追加寫(xiě)入,類(lèi)似斷點(diǎn)續(xù)傳。
存儲(chǔ):二進(jìn)制數(shù)據(jù)庫(kù)
二進(jìn)制存檔文件按月存放,自帶索引。所有對(duì)其操作均在DataHelper的HDAIOHelper?類(lèi)中。包括從數(shù)據(jù)庫(kù)寫(xiě)入、查詢、定期轉(zhuǎn)儲(chǔ)、壓縮歸檔(用旋轉(zhuǎn)門(mén)算法)等。為提高讀寫(xiě)性能,采用內(nèi)存映射文件MemoryMappedFile。
四、???應(yīng)用場(chǎng)景
數(shù)據(jù)應(yīng)用場(chǎng)景
數(shù)據(jù)的應(yīng)用場(chǎng)景,主要是查詢、顯示、挖掘。查詢→生成各種報(bào)表、圖表,以供人工分析比較;顯示→圖形化展示,一目了然;挖掘→結(jié)合先進(jìn)的挖掘工具,找出數(shù)據(jù)內(nèi)在關(guān)聯(lián)性,提供決策支持。
?
數(shù)據(jù)查詢
目前支持的查詢場(chǎng)景包括:按時(shí)間段檢索、按變量ID檢索、獲取某變量在一段時(shí)間內(nèi)的平均值/最大值/最小值/初始值/當(dāng)前值。如要對(duì)一段記錄執(zhí)行復(fù)雜查詢(如按時(shí)間間隔分組等),需要取出該時(shí)間段內(nèi)所有記錄,用Linq查詢。
數(shù)據(jù)顯示
目前支持實(shí)時(shí)數(shù)據(jù)顯示和歷史數(shù)據(jù)趨勢(shì)圖。我這里用了一套微軟俄羅斯研究院的DynamicDataDisplay開(kāi)源組件,性能不錯(cuò),很適合動(dòng)態(tài)圖顯示,目前還發(fā)展出了javascript版本。
?
數(shù)據(jù)報(bào)表
利用微軟的RDLC報(bào)表和Chart圖表的強(qiáng)大功能,可以方便的設(shè)計(jì)出各種復(fù)雜報(bào)表、圖表。順帶贊一下RDLC,集成于Visual Studio和SQL SERVER,可以在Web顯示,支持內(nèi)嵌表格、儀表、圖表、鉆取報(bào)表,還可以方便的導(dǎo)出為Excel、Pdf、Word,與.NET 完美集成,強(qiáng)烈推薦。
未來(lái)改進(jìn)
分布式:對(duì)一個(gè)大系統(tǒng),分布式是必須的。即數(shù)據(jù)分別在不同節(jié)點(diǎn)采集、存儲(chǔ),但形式上依然是一個(gè)整體,可以統(tǒng)一查詢和傳輸。
內(nèi)存映像:目前的測(cè)點(diǎn)緩存模式存在可靠性不足的問(wèn)題(如突然斷電或系統(tǒng)崩潰造成的數(shù)據(jù)丟失),可依賴Sqlite和內(nèi)存映像解決。
MQTT:物聯(lián)網(wǎng)通行的MQTT協(xié)議可以解決不同系統(tǒng)之間的實(shí)時(shí)訂閱傳輸問(wèn)題。
查詢擴(kuò)展:原生支持按時(shí)間間隔分組取出數(shù)據(jù)等常用查詢場(chǎng)景,可以有效提高查詢性能。
安全控制:采用證書(shū)認(rèn)證方式,加強(qiáng)權(quán)限管理,防止數(shù)據(jù)傳輸過(guò)程中被篡改。
數(shù)據(jù)歸檔流程:
五、???下面的計(jì)劃
網(wǎng)關(guān)層接口概述
上下位機(jī)通訊原理
如何實(shí)現(xiàn)一個(gè)設(shè)備驅(qū)動(dòng)
如何設(shè)計(jì)圖元
數(shù)據(jù)采集與歸檔
VS插件模塊及原理
歸檔模塊及文件格式
如何進(jìn)行功能擴(kuò)展
組態(tài)變量表達(dá)式實(shí)現(xiàn)
github地址:https://github.com/GavinYellow/SharpSCADA。QQ群:102486275
相關(guān)文章:?
.NET十年回顧
開(kāi)源純C#工控網(wǎng)關(guān)+組態(tài)軟件
開(kāi)源純C#工控網(wǎng)關(guān)+組態(tài)軟件(三)加入一個(gè)新驅(qū)動(dòng):西門(mén)子S7
開(kāi)源純C#工控網(wǎng)關(guān)+組態(tài)軟件(四)上下位機(jī)通訊原理
開(kāi)源純C#工控網(wǎng)關(guān)+組態(tài)軟件(五)從網(wǎng)關(guān)到人機(jī)界面
開(kāi)源純C#工控網(wǎng)關(guān)+組態(tài)軟件(六)圖元組件
原文:http://www.cnblogs.com/evilcat/p/7909578.html
.NET社區(qū)新聞,深度好文,歡迎訪問(wèn)公眾號(hào)文章匯總 http://www.csharpkit.com
總結(jié)
以上是生活随笔為你收集整理的开源纯C#工控网关+组态软件(七)数据采集与归档的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 深港澳大湾区第三次.NET技术交流会圆满
- 下一篇: 使用Api分析器与Windows兼容包来