韋統(tǒng)邊,司帥鋒,溫麗梅,唐瑩,蘇德
(上汽通用五菱汽車股份有限公司廣西汽車新四化重點(diǎn)實(shí)驗(yàn)室,廣西柳州,545007)
當(dāng)前汽車成為大部分家庭生活必須品。電動(dòng)化、網(wǎng)聯(lián)化、智能化和共享化成為新一代汽車的基本要求,汽車上數(shù)百個(gè)傳感器在不間斷的采集數(shù)據(jù),這些數(shù)據(jù)的傳輸和利用蘊(yùn)藏著巨大的價(jià)值,在2030年我國汽車保有量將增長到4.3億輛,每輛智能網(wǎng)聯(lián)汽車每秒可產(chǎn)生8.6MB數(shù)據(jù)[1]。海量數(shù)據(jù)的傳輸、存儲(chǔ)和計(jì)算成本之間的均衡成為當(dāng)前最急需解決的問題之一。
本文將基于整車大數(shù)據(jù)目前狀況,簡要說明常用的數(shù)據(jù)存儲(chǔ)格式優(yōu)缺點(diǎn),選擇Parquet數(shù)據(jù)格式原由,并結(jié)合數(shù)據(jù)歸類和歸檔策略,總體上實(shí)現(xiàn)存儲(chǔ)壓縮和計(jì)算性能提升的目標(biāo)。總體上實(shí)現(xiàn)存儲(chǔ)壓縮和計(jì)算性能提升的目標(biāo)。
Txt是微軟在操作系統(tǒng)上附帶的一種文本格式,主要是用于存儲(chǔ)文本信息,此處我們利用txt格式文件按行存儲(chǔ)車輛上傳的加密數(shù)據(jù),所有車輛信號(hào)項(xiàng)以及對(duì)應(yīng)的值都以十六進(jìn)制進(jìn)行傳輸,需要使用時(shí)再用制定好的規(guī)則把十六進(jìn)制數(shù)據(jù)解析為明文數(shù)據(jù)。
優(yōu)點(diǎn):沒有對(duì)應(yīng)的解密規(guī)則無法將數(shù)據(jù)解密,數(shù)據(jù)的安全性高。壓縮比高,節(jié)省網(wǎng)絡(luò)帶寬,因?yàn)橥瑯游粩?shù)的十六進(jìn)制能比十進(jìn)制和二進(jìn)制表達(dá)的信息更多。
缺點(diǎn):當(dāng)使用數(shù)據(jù)時(shí)必須先解析為明文數(shù)據(jù),再進(jìn)行數(shù)據(jù)分析,若需要分別實(shí)現(xiàn)多個(gè)算法,會(huì)多次讀取源數(shù)據(jù),導(dǎo)致數(shù)據(jù)解析工作重復(fù)進(jìn)行,即使讀取一個(gè)信號(hào)項(xiàng)的值,也必須遍歷所有數(shù)據(jù)后再解析出指定信號(hào)項(xiàng)的值,重復(fù)解析工作耗費(fèi)大量的集群計(jì)算資源。
應(yīng)用場(chǎng)景:低頻歸檔數(shù)據(jù)。
一種按行存儲(chǔ)的輕量級(jí)的數(shù)據(jù)交換格式,采用完全獨(dú)立于語言的文本格式,包含對(duì)象(鍵值對(duì))和數(shù)組(包含多個(gè)對(duì)象)這兩種結(jié)構(gòu)[2]。由字符串、數(shù)字、對(duì)象和數(shù)組組成的數(shù)據(jù)結(jié)構(gòu)都可以通過Json來表示,其中對(duì)象是有一對(duì)大括號(hào){}包裹起來的內(nèi)容,數(shù)據(jù)結(jié)構(gòu)為多個(gè){key1:value1,key2:value2,…}形式的鍵值對(duì),key為對(duì)象的屬性,value為對(duì)象的值,key一般用整數(shù)和字符串表示,value可以是Json支持的任意數(shù)據(jù)類型;而數(shù)組是由中括號(hào)[]包裹起來的內(nèi)容,數(shù)據(jù)結(jié)構(gòu)為 [“java”, 123, “vb”, ...] 的索引結(jié)構(gòu),同樣數(shù)組的值也可以是任意數(shù)據(jù)類型。整車數(shù)據(jù)解析后轉(zhuǎn)為JSON數(shù)據(jù)格式再按行存儲(chǔ),文件格式可以是json和txt等。
優(yōu)點(diǎn):數(shù)據(jù)讀取速度快,一次解析多次使用,大量節(jié)省數(shù)據(jù)重復(fù)解析的時(shí)間;按需讀取信號(hào)項(xiàng)值,省去逐個(gè)遍歷信號(hào)項(xiàng)的時(shí)間。
缺點(diǎn):占用存儲(chǔ)空間大,因?yàn)槊恳恍袛?shù)據(jù)都重復(fù)存儲(chǔ)相同的key值,以及大量的冒號(hào)、雙引號(hào)、大括號(hào)和逗號(hào)等,數(shù)據(jù)冗余問題較為嚴(yán)重。
應(yīng)用場(chǎng)景:數(shù)據(jù)量低于百萬級(jí)別系統(tǒng)。
一種非單純的列式存儲(chǔ)格式,ORC數(shù)據(jù)格式遵循“先對(duì)行分組,再按列存儲(chǔ)”的理念,首先會(huì)按行組去分割整個(gè)數(shù)據(jù)表,每一個(gè)行組內(nèi)再進(jìn)行按列存儲(chǔ),以strip為邏輯單位分為行組,每一個(gè)邏輯單位的大小一般與HDFS的block大小一致,保存了每一列的索引和數(shù)據(jù),這可以保證邏輯單位內(nèi)所有行都能保存在一個(gè)集群節(jié)點(diǎn)上;邏輯單位內(nèi)的數(shù)據(jù)再按列存儲(chǔ)。這樣可以保證讀取多列數(shù)據(jù)時(shí)不會(huì)出現(xiàn)跨節(jié)點(diǎn)通信組裝元組的情況[3]。
ORC數(shù)據(jù)格式讀取是從文件的尾部開始,第一次讀取16KB大小的數(shù)據(jù),盡可能將元數(shù)據(jù)信息和文件結(jié)構(gòu)信息讀入內(nèi)存,至此數(shù)據(jù)讀取初始化完畢。之后就可以通過元數(shù)據(jù)信息指定需要讀取的列編號(hào),如果不指定列編號(hào)則默認(rèn)讀取全部列。同時(shí)ORC文件是自描述的,它的元數(shù)據(jù)使用Protocol Buffers序列化,使用兩級(jí)壓縮機(jī)制,首先將一個(gè)數(shù)據(jù)流使用流式編碼器進(jìn)行編碼,然后使用可選的壓縮器對(duì)編碼后的數(shù)據(jù)進(jìn)一步壓縮,達(dá)到降低存儲(chǔ)空間的目的。
優(yōu)點(diǎn):具有極高的壓縮比,并且文件是可分割的,可支持更高的任務(wù)并行度。
缺點(diǎn):對(duì)多層數(shù)據(jù)嵌套結(jié)構(gòu)支持不夠友好,在使用多層數(shù)據(jù)嵌套結(jié)構(gòu)時(shí)性能和空間損失較大。
應(yīng)用場(chǎng)景:數(shù)據(jù)結(jié)構(gòu)較為簡單的大數(shù)據(jù)集群。
一種以二進(jìn)制方式存儲(chǔ)的列式存儲(chǔ)格式,對(duì)多層數(shù)據(jù)嵌套結(jié)構(gòu)支持比較友好,它的文件不可直接讀取和修改,它的文件也是自解析的[4]。Parquet數(shù)據(jù)格式主要分為三層,遵守自下而上的交互方式,最上層為數(shù)據(jù)存儲(chǔ)層,這層定義Parquet的文件格式/類型,包括原始類型定義、page類型、編碼類型和壓縮類型等;中間層為對(duì)象轉(zhuǎn)換層,這層作用是完成其他對(duì)象模型與Parquet內(nèi)部數(shù)據(jù)模型的映射和轉(zhuǎn)換;最底層為對(duì)象模型層,該層定義如何讀取Parquet文件的內(nèi)容,并對(duì)外提供接口,實(shí)現(xiàn)java對(duì)象和Parquet文件的轉(zhuǎn)換。Parquet的存儲(chǔ)模型主要由行組(Row Group)、列塊(Column Chuck)、頁(Page)組成,Row Group:將數(shù)據(jù)水平分割劃分為行組,默認(rèn)行組大小與HDFS block塊大小一致,保證一個(gè)行組會(huì)被一個(gè)Mapper處理,Column Chuck:行組中的每一列保存在一個(gè)列塊中,每一個(gè)列塊只包含一種數(shù)據(jù)類型的數(shù)據(jù),并且不同列塊可以使用不同的壓縮算法,Page:Parquet是按照塊頁方式去存儲(chǔ)數(shù)據(jù),每個(gè)列塊包含多個(gè)頁,頁是最小的編碼單位,同樣不同的頁可以用不同的編碼方式。同時(shí)在ORC的基礎(chǔ)上采用Striping/Assembly壓縮算法,通過該算法,Parquet可使用較少的存儲(chǔ)空間表示復(fù)雜的嵌套格式。
優(yōu)點(diǎn):支持的系統(tǒng)多,數(shù)據(jù)壓縮比高,數(shù)據(jù)使用復(fù)雜的嵌套格式時(shí)占用存儲(chǔ)空間較少。
缺點(diǎn):壓縮比沒有ORC數(shù)據(jù)格式高。
應(yīng)用場(chǎng)景:數(shù)據(jù)為復(fù)雜嵌套格式的大數(shù)據(jù)集群。
列舉的數(shù)據(jù)格式各項(xiàng)指標(biāo)對(duì)比結(jié)果如下[5]:
數(shù)據(jù)格式指標(biāo) Text Json ORC Parquet壓縮比 低 極低 高 較高ACID 不支持 不支持 支持 不支持UPDATE操作 不支持 不支持 支持 不支持索引 不支持 不支持 粗粒度索引 粗粒度索引Impala、Drill、Spark、Hive單表查詢耗時(shí) — — 9t 10t支持平臺(tái) Hdfs Hdfs Spark、Hive
綜合以上對(duì)比結(jié)果,Parquet更適合我們當(dāng)前大數(shù)據(jù)業(yè)務(wù)場(chǎng)景,因?yàn)镺RC和Parquet查詢性能接近,但是Parquet支持更多的平臺(tái),方便后續(xù)引入其他大數(shù)據(jù)組件。
利用kafka作為消息緩存隊(duì)列,加密數(shù)據(jù)全都暫存HDFS,一天數(shù)據(jù)存入一個(gè)文件中,凌晨時(shí)解析數(shù)據(jù)并轉(zhuǎn)為Parquet數(shù)據(jù)格式,Parquet格式數(shù)據(jù)用于數(shù)據(jù)分析,不常使用的加密數(shù)據(jù)轉(zhuǎn)存?zhèn)溆肏DFS中,詳情請(qǐng)看圖1。
圖1 整車大數(shù)據(jù)數(shù)據(jù)流
為提高Parquet格式數(shù)據(jù)計(jì)算并行度,每一天數(shù)據(jù)將劃分為多個(gè)文件進(jìn)行存儲(chǔ),對(duì)文件存儲(chǔ)結(jié)構(gòu)制定如下規(guī)則:
(1)解析后數(shù)據(jù)分類存儲(chǔ):解析后的數(shù)據(jù)按/車型/采集日期/壓縮算法_時(shí)段_from_數(shù)據(jù)接收日期/Parquet文件目錄結(jié)構(gòu)進(jìn)行存儲(chǔ),無法區(qū)分車型的車輛統(tǒng)一存儲(chǔ)到車型為UNKNOWN的文件夾下。
(2)清洗異常數(shù)據(jù):過濾采集時(shí)間異常的數(shù)據(jù),例如:過濾掉年份不屬于2019年至當(dāng)年年份的數(shù)據(jù) ,過濾掉月份不屬于1月至12月的數(shù)據(jù),過濾掉日期不屬于1日至31日的數(shù)據(jù),過濾掉時(shí)段不屬于0時(shí)至23時(shí)的數(shù)據(jù),過濾掉分和秒不屬于0至59的數(shù)據(jù)。
(3)文件大小限制單個(gè)Parquet文件大小不允許超過512M,并且同一個(gè)文件夾下不允許有多個(gè)名稱相同,且文件大小都小于256M的文件出現(xiàn),如果有要求把小文件合并為大文件。
整車大數(shù)據(jù)Text轉(zhuǎn)Parquet壓縮算法實(shí)現(xiàn)如下:
(1)按行讀取Text文件,講數(shù)據(jù)轉(zhuǎn)為便于計(jì)算的RDD數(shù)據(jù)集。
(2)將數(shù)據(jù)解析為key-value形式,key為采集的信號(hào)項(xiàng)名稱,value為信號(hào)項(xiàng)值。
(3)過濾采集時(shí)間異常的數(shù)據(jù)。
(4)對(duì)過濾后的RDD數(shù)據(jù)集分組,分組key為車型和數(shù)據(jù)采集日期拼接的字符串,例如:SUV20211111,表示該條數(shù)據(jù)于2021年11月11日采集的SUV車型數(shù)據(jù),value為過濾后的RDD數(shù)據(jù)集。
(5)遍歷分組后RDD數(shù)據(jù)集,根據(jù)key生成數(shù)據(jù)文件存儲(chǔ)路徑,將RDD數(shù)據(jù)集轉(zhuǎn)為DataFrame數(shù)據(jù)集,通過控制每個(gè)文件數(shù)據(jù)條數(shù)來控制每個(gè)文件的大小,最后通過DataFrame的coalesce方法控制此次分組生成的Parquet文件個(gè)數(shù)。
基于現(xiàn)有的Parquet格式數(shù)據(jù),我們要實(shí)現(xiàn)一個(gè)統(tǒng)計(jì)功能,統(tǒng)計(jì)晚高峰期(18時(shí)-19時(shí))每一個(gè)時(shí)段數(shù)據(jù)上傳的條數(shù),通過同比每個(gè)時(shí)段數(shù)據(jù)量可分析出集群是否發(fā)生過數(shù)據(jù)延遲問題?,F(xiàn)有的樣例數(shù)據(jù)8451條,樣例數(shù)據(jù)如圖2和圖3所示。
圖2 樣例數(shù)據(jù)
圖3 輸出結(jié)果圖
用于統(tǒng)計(jì)的代碼如下:
(1)初始化 spark 環(huán)境
(2)讀取Parquet格式文件數(shù)據(jù)
(3)將DataFrame數(shù)據(jù)緩存,防止后續(xù)多次Action操作導(dǎo)致多次加載DataFrame數(shù)據(jù)
(4)利用列式存儲(chǔ)優(yōu)勢(shì),按需選擇需要統(tǒng)計(jì)的字段
(5)根據(jù)條件過濾掉非高峰期時(shí)段的數(shù)據(jù)
(6)統(tǒng)計(jì)每個(gè)日期每個(gè)時(shí)間段數(shù)據(jù)條數(shù)
(7)釋放緩存的DataFrame
最終輸出結(jié)果如圖3所示。相比傳統(tǒng)的按行分析數(shù)據(jù),列式存儲(chǔ)Parquet可按需篩選字段,極大減少用于讀取數(shù)據(jù)的資源開銷,而且可使用近似Sql語法去分析數(shù)據(jù),極大減少數(shù)據(jù)分析的工作量,
本文介紹一種基于Parquet數(shù)據(jù)格式實(shí)現(xiàn)整車大數(shù)據(jù)存儲(chǔ)與計(jì)算優(yōu)化,減少了數(shù)據(jù)存儲(chǔ)成本,同時(shí)數(shù)據(jù)分析速度提升,為企業(yè)實(shí)現(xiàn)降本增效的根本目的。