開(kāi)源IndexR:如何對(duì)上千億的數(shù)據(jù)進(jìn)行秒級(jí)探索式分析
在當(dāng)前信息大爆炸的時(shí)代,“大數(shù)據(jù)”已成為互聯(lián)網(wǎng)行業(yè)人人談?wù)摰臒嵩~和話題,比如近幾年快速發(fā)展的基于大數(shù)據(jù)進(jìn)行精準(zhǔn)用戶定向的程序化廣告,以及去年馬云提出的利用大數(shù)據(jù)重塑商品的生產(chǎn) - 流量 - 銷售流程的“新零售”模式等。大數(shù)據(jù)已經(jīng)滲透到眾多的行業(yè),為許多企業(yè)帶來(lái)了變革性影響。那么,何為“大數(shù)據(jù)”呢?大數(shù)據(jù)(Big Data),可以簡(jiǎn)單的理解為無(wú)法在一定時(shí)間范圍內(nèi)用常規(guī)手段進(jìn)行處理的海量數(shù)據(jù)集合。所有企業(yè)的業(yè)務(wù)分析都是基于數(shù)據(jù)的,每家企業(yè)對(duì)數(shù)據(jù)的收集、整合及處理能力在一定程度上決定了企業(yè)的業(yè)務(wù)發(fā)展水平。因此,提升數(shù)據(jù)分析性能也是當(dāng)前許多企業(yè)共同面臨的重大挑戰(zhàn)。
行業(yè)現(xiàn)狀
目前,行業(yè)中的大數(shù)據(jù)分析架構(gòu)一般使用基于 Hadoop 體系的分布式計(jì)算引擎 + 分布式存儲(chǔ)系統(tǒng)架構(gòu)(如下圖)。
Hadoop 體系的架構(gòu)特點(diǎn)是上層解決計(jì)算問(wèn)題,下層解決存儲(chǔ)問(wèn)題。它可以讓開(kāi)發(fā)者在不了解分布式底層細(xì)節(jié)的情況下,進(jìn)行分布式程序的開(kāi)發(fā)。但是,這種架構(gòu)同時(shí)也存在一些問(wèn)題:
1.整合工作量大
分布式存儲(chǔ)目前的標(biāo)準(zhǔn)比較統(tǒng)一,一般使用 HDFS。HDFS 能有效解決海量數(shù)據(jù)的存儲(chǔ)問(wèn)題,并且有多種方便的工具鏈。但是,分布式計(jì)算引擎為了適應(yīng)不同場(chǎng)景,會(huì)有不同特性的數(shù)據(jù)倉(cāng)庫(kù)工具,僅 Apache 就有 Hive、Spark、Drill、Impala、Presto 等產(chǎn)品,除此之外,還有獨(dú)立于 Hadoop 體系之外其它產(chǎn)品項(xiàng)目(如 ClickHouse、Kudu、Druid 等)。由于每個(gè)產(chǎn)品都有各自的特性,當(dāng)需要利用多個(gè)產(chǎn)品來(lái)解決不同問(wèn)題時(shí),就需要額外的整合工作,降低了工作效率。
2.數(shù)據(jù)交換速度慢
由于計(jì)算層必然是駐于內(nèi)存的,從存儲(chǔ)層到計(jì)算層的速度限制就成了系統(tǒng)的普遍瓶頸。有些系統(tǒng)為了加快速度全部使用內(nèi)存存儲(chǔ)(比如內(nèi)存數(shù)據(jù)庫(kù)、基于 Spark 的 SnappyData),這種方式在數(shù)據(jù)量較大時(shí)會(huì)造成巨大的成本壓力,因此目前還遠(yuǎn)未成為主流。
3.數(shù)據(jù)實(shí)時(shí)分析性差
由于文件系統(tǒng)的天然限制,數(shù)據(jù)一般是批量導(dǎo)入系統(tǒng)的。導(dǎo)入的時(shí)間會(huì)依據(jù)數(shù)據(jù)量的大小而有所不同,在數(shù)據(jù)量較大時(shí)常會(huì)出現(xiàn)入庫(kù)滯后現(xiàn)象,從而影響了數(shù)據(jù)分析的及時(shí)性。
因此,我們需要一個(gè)可以充分解決以上問(wèn)題的大數(shù)據(jù)儲(chǔ)存格式,也就是筆者接下來(lái)要為大家介紹的 IndexR 開(kāi)源大數(shù)據(jù)存儲(chǔ)數(shù)據(jù)庫(kù)。
IndexR 簡(jiǎn)介
IndexR 是一個(gè)開(kāi)源的大數(shù)據(jù)存儲(chǔ)格式(下載地址 https://github.com/shunfei/indexr),于 2017 年 1 月初正式開(kāi)源,目前已經(jīng)更新至 0.5.0 版本。IndexR 旨在通過(guò)添加索引、優(yōu)化編碼方式、提高 IO 效率等各種優(yōu)化方式來(lái)提高計(jì)算層和存儲(chǔ)層的數(shù)據(jù)交換效率,從而提升整體性能。同時(shí),IndexR 可以接收實(shí)時(shí)數(shù)據(jù),并對(duì)上層提供統(tǒng)一的數(shù)據(jù)接口。數(shù)據(jù)一旦到達(dá) IndexR 系統(tǒng)即可立刻進(jìn)行數(shù)據(jù)分析。
架構(gòu)剖析
基于 IndexR 系統(tǒng)的典型架構(gòu)示例如下:
1.IndexR 為上層計(jì)算引擎提供數(shù)據(jù),相當(dāng)于對(duì) IO 層做了整體的性能加速,提升了系統(tǒng)的分析能力。
2.IndexR 為下層數(shù)據(jù)存儲(chǔ)解決了在線分析和數(shù)據(jù)調(diào)用的問(wèn)題,同時(shí)還能解決實(shí)時(shí)數(shù)據(jù)和歷史數(shù)據(jù)的分割問(wèn)題。
- IndexR 能實(shí)時(shí)拉取 Kafka 的數(shù)據(jù)流,并打包上傳到 HDFS。整個(gè)數(shù)據(jù)層對(duì)于計(jì)算層是透明的。IndexR 通過(guò)結(jié)合實(shí)時(shí)數(shù)據(jù)和歷史數(shù)據(jù),保證了數(shù)據(jù)分析的實(shí)時(shí)性。
- 數(shù)據(jù)存放于 HDFS,不同的分析工具可同時(shí)分析同一份數(shù)據(jù)。
- 利用 Hadoop、Drill、Spark 等的分布式、高可用、可擴(kuò)展特點(diǎn),解決海量數(shù)據(jù)場(chǎng)景的分析問(wèn)題。
使用場(chǎng)景
IndexR 從開(kāi)源至今,歷經(jīng)不同團(tuán)隊(duì)從調(diào)研、測(cè)試到***部署生產(chǎn)環(huán)境的實(shí)踐,已獲得了國(guó)內(nèi)外數(shù)十家團(tuán)隊(duì)的認(rèn)可(如尼爾森、佰安信息等),包括廣告、電商、AI 等領(lǐng)域的大型互聯(lián)網(wǎng)公司和創(chuàng)業(yè)團(tuán)隊(duì)以及政府、咨詢、物流等擁有超大數(shù)據(jù)集且對(duì)數(shù)據(jù)質(zhì)量有極高要求的行業(yè)。其中:尼爾森(Nielsen-CCData)使用 IndexR 產(chǎn)品服務(wù)全面支撐了其六大產(chǎn)品線的核心業(yè)務(wù),應(yīng)對(duì)海量數(shù)據(jù)的在線監(jiān)測(cè)、治理、分析以及復(fù)雜多變的智能化數(shù)據(jù)產(chǎn)品輸出,專注于全媒體與受眾研究業(yè)務(wù)。佰安信息則使用 IndexR 產(chǎn)品服務(wù)進(jìn)行公共信息的明細(xì)查詢與統(tǒng)計(jì)分析,單表數(shù)據(jù)量近 2 千億,每日入庫(kù)近 4 億條數(shù)據(jù)。
下面列舉幾種常見(jiàn)的使用場(chǎng)景:
- 替換 Parquet 等存儲(chǔ)格式:利用 IndexR 的性能和索引優(yōu)勢(shì),加速查詢系統(tǒng)。
- 替換 Druid 等分布式系統(tǒng):利用 IndexR 實(shí)現(xiàn)實(shí)時(shí)入庫(kù),進(jìn)行多維數(shù)據(jù)分析。
- 替換 MySQL、Oracle 等業(yè)務(wù)數(shù)據(jù)庫(kù),或 ES、Solr 等搜索引擎:把統(tǒng)計(jì)分析工作移交到 IndexR 系統(tǒng),通過(guò)模塊分離,提高服務(wù)能力。
- 結(jié)合其他開(kāi)源工具(如 Drill,搭建 OLAP 查詢系統(tǒng)):IndexR 基于 Hadoop 生態(tài)的特點(diǎn)及支持實(shí)時(shí)入庫(kù)、高效查詢的優(yōu)勢(shì),能夠滿足當(dāng)前或未來(lái)對(duì)于 OLAP 系統(tǒng)的實(shí)時(shí)分析海量數(shù)據(jù)、線性擴(kuò)展、高可用、多功能、業(yè)務(wù)靈活等多種需求。數(shù)據(jù)分析不再被純預(yù)計(jì)算的局限性所困擾,且在線分析和離線分析可以使用同一份數(shù)據(jù),提高了數(shù)據(jù)利用率并降低了成本。
- 作為數(shù)據(jù)倉(cāng)庫(kù)的存儲(chǔ)格式:利用 IndexR 存放海量歷史數(shù)據(jù),同時(shí)支持海量數(shù)據(jù)的實(shí)時(shí)入庫(kù)。數(shù)據(jù)使用方式包括明細(xì)查詢、在原始數(shù)據(jù)上做分析查詢和定期的預(yù)處理腳本。
IndexR 特性
IndexR 具有六大特性:自帶索引、靈活性強(qiáng)、實(shí)時(shí)性高、速度快、省資源、預(yù)聚合。
1. 自帶索引:存儲(chǔ)格式自帶索引。
IndexR 包含三層索引,即粗糙集索引(Rough Set Index)、內(nèi)索引(Inner Index)和可選的外索引(Outer Index)。
目前的 On Hadoop 存儲(chǔ)格式如 ORC、Parquet 等都沒(méi)有真正的索引,只靠分區(qū)和利用一些簡(jiǎn)單的統(tǒng)計(jì)特征如***最小值等大概滿足離線分析的需求。在服務(wù)在線業(yè)務(wù)時(shí) On Hadoop 就顯得非常力不從心,需要從磁盤中讀取大量無(wú)用數(shù)據(jù)。事實(shí)上并不是每次查詢都需要獲取全部數(shù)據(jù),特別是 Ad-hoc 類型的查詢。而 IndexR 通過(guò)多層索引的設(shè)計(jì),不僅極大地提高了 IO 效率,只讀取部分有效數(shù)據(jù),而且把索引的額外開(kāi)銷降到了***。
一般傳統(tǒng)數(shù)據(jù)庫(kù)系統(tǒng)的索引設(shè)計(jì)是通過(guò)索引直接***具體的數(shù)據(jù)行,但這種方式只適用于 OLTP 場(chǎng)景,即每次查詢只獲取少量數(shù)據(jù),在 OLAP 場(chǎng)景下并不適合。OLAP 場(chǎng)景下每次查詢可能要涉及上萬(wàn)甚至上億行數(shù)據(jù),這樣的索引設(shè)計(jì)開(kāi)銷極大(內(nèi)存、IO、CPU),并會(huì)帶來(lái)磁盤隨機(jī)讀的問(wèn)題,很多時(shí)候還不如直接對(duì)原始數(shù)據(jù)進(jìn)行掃描更加快速。
IndexR 的索引設(shè)計(jì)是分層的。打個(gè)比喻,如果要定位全國(guó)具體的某個(gè)街道,傳統(tǒng)的方式是把“省市 - 街道”組成一個(gè)索引,而 IndexR 是通過(guò)把“街道”映射在相應(yīng)的“省市”的集合(Pack)里,然后再在具體的集合了里做細(xì)致的索引。
- Rough Set Index - 粗糙集索引的工作方式類似于熟知的 Bloom Filter,它的特點(diǎn)是成本極低,速度超快,幾乎不會(huì)對(duì)查詢有性能損耗。IndexR 數(shù)據(jù)格式通過(guò)粗糙集索引快速定位區(qū)域塊,所以并不依賴分區(qū)。
- Outer Index - 外索引目前使用倒排索引和 Bitmap,它的優(yōu)點(diǎn)是支持豐富的過(guò)濾條件,并且非常適合做交、并運(yùn)算。IndexR 對(duì)倒排索引的使用方式做了優(yōu)化,避免了在 Scan 場(chǎng)景下大量隨機(jī)讀或者巨大內(nèi)存使用的問(wèn)題,并且把 Bitmap 的 merge 操作做了加速處理,不會(huì)出現(xiàn)范圍條件(大于、小于)下的大量 merge 問(wèn)題。
- Inner Index - 內(nèi)索引由具體的 Pack 內(nèi)部編碼特性決定,支持在壓縮狀態(tài)下對(duì)數(shù)據(jù)進(jìn)行過(guò)濾。具體查詢時(shí) IndexR 先進(jìn)行粗糙集索引過(guò)濾,再對(duì)剩下的數(shù)據(jù)集進(jìn)行倒排索引過(guò)濾,然后把***的 Pack 直接加載入內(nèi)存,對(duì)其進(jìn)行高效的細(xì)致查詢。這種方式解決了分布式架構(gòu)、海量數(shù)據(jù)場(chǎng)景下索引困難的問(wèn)題,避免了隨機(jī)讀問(wèn)題,不管是在需要大范圍掃描還是少量數(shù)據(jù)查詢都更加高效。
2. 靈活性強(qiáng):雙存儲(chǔ)模式,適應(yīng)不同場(chǎng)景。
- vlt 模式 - 默認(rèn)模式,適用于絕大部分場(chǎng)景。特點(diǎn)是速度極快,遍歷速度比 Parquet 快 2~4 倍,支持倒排索引,且隨機(jī)查詢性能優(yōu)越。默認(rèn)情況下文件大小是 Parquet 的 75%。
- basic 模式 - 壓縮率極高,可達(dá) 10:1,一般文件大小是 Parquet 的 1/3。并且仍然保持非常高的讀取性能,優(yōu)于其他開(kāi)源格式。適用于存放超大量歷史數(shù)據(jù),并支持隨時(shí)快速訪問(wèn)。
3. 實(shí)時(shí)性高:支持流式導(dǎo)入,實(shí)時(shí)分析。
目前的 Hadoop 生態(tài)對(duì)于實(shí)時(shí)的數(shù)據(jù)分析還是比較困難。Storm、Spark Streaming 等系統(tǒng)屬于對(duì)數(shù)據(jù)進(jìn)行預(yù)計(jì)算,在業(yè)務(wù)頻繁改動(dòng)或需要對(duì)原始數(shù)據(jù)進(jìn)行啟發(fā)式分析(Ad-hoc)的情況下沒(méi)法滿足需求。而 Druid、Kudu 等系統(tǒng)雖然支持實(shí)時(shí)寫入,但其體系自成,在實(shí)際運(yùn)用中常會(huì)出現(xiàn)部署、整合甚至性能方面的問(wèn)題。
IndexR 支持實(shí)時(shí)數(shù)據(jù)寫入,比如從 Kafka 導(dǎo)入,并且數(shù)據(jù)到達(dá)系統(tǒng)之后可以立刻被分析。它與 Hadoop 生態(tài)的無(wú)縫整合也使得它在業(yè)務(wù)設(shè)計(jì)上非常靈活。目前 IndexR 單表單節(jié)點(diǎn)入庫(kù)速度每秒超過(guò) 3w 條數(shù)據(jù),入庫(kù)速度會(huì)隨著節(jié)點(diǎn)數(shù)量呈線性增加,每個(gè)表使用單獨(dú)線程,表間互不影響。此外,對(duì)于 OLAP 型的多維分析場(chǎng)景,IndexR 還支持實(shí)時(shí)、離線預(yù)聚合處理,將指標(biāo)基于維度進(jìn)行預(yù)先組織,大大減少了數(shù)據(jù)量,數(shù)據(jù)分析更加快速。
4. 速度快:媲美內(nèi)存數(shù)據(jù)庫(kù)。
IndexR 使用深度優(yōu)化的編碼方式,大大加快了數(shù)據(jù)解析,甚至可以媲美一些內(nèi)存數(shù)據(jù)庫(kù)。它的數(shù)據(jù)組織形式根據(jù)向量化執(zhí)行的特點(diǎn)定制,把全部數(shù)據(jù)存放于堆外內(nèi)存,并且優(yōu)化到各個(gè) byte 的組織方式,把 JVM 的 GC 和虛函數(shù)開(kāi)銷降到***。
IndexR 是基于 Hadoop 的數(shù)據(jù)格式,意味著文件存放于 HDFS,這樣可以非常方便地利用 HDFS 本身的高可用特性保證數(shù)據(jù)安全,并且可以方便的使用 Hadoop 生態(tài)上的所有分析工具。IndexR 對(duì)基于 HDFS 的文件讀取做了大量的優(yōu)化,把計(jì)算盡量分發(fā)到離數(shù)據(jù)最近的本地節(jié)點(diǎn),HDFS 層的開(kāi)銷基本被剔除,與直接讀取本地?cái)?shù)據(jù)無(wú)異。
以下是使用 TPC-H 數(shù)據(jù)集,IndexR 與 Parquet 格式在相同的 Drill 集群上做的一個(gè)性能對(duì)比。
***表 lineitem 數(shù)據(jù)總量 6 億,5 個(gè)節(jié)點(diǎn),節(jié)點(diǎn)配置 [Intel(R) Xeon(R) CPU E5-2620 v2 @ 2.10GHz] x 2, RAM 64G(實(shí)際使用約 12G), HDD STATA with 7200RPM。
IndexR 與 Parquet 的 Hive 表 schema 都沒(méi)有設(shè)置 TBLPROPERTIES,使用默認(rèn)參數(shù)。
- 單項(xiàng)性能對(duì)比
柱狀圖:
- 使用 TPC-H 標(biāo)準(zhǔn)測(cè)試 SQL,SQL 內(nèi)容可以在 http://www.tpc.org/tpch/ 上獲取(貼出來(lái)太長(zhǎng)了),覆蓋了包 Join、子查詢等常見(jiàn)統(tǒng)計(jì)分析查詢 SQL,where 條件***的數(shù)據(jù)量一般超過(guò)***表的 50%。其中 Q2,Q15 等 SQL 由于 Drill 不支持沒(méi)有顯示。
柱狀圖:
5. 省資源:減少內(nèi)存使用量
為了避免 Java 中對(duì)象和抽象的開(kāi)銷,IndexR 的代碼大量使用了 Code C In Java 的編程風(fēng)格(調(diào)侃),通過(guò)內(nèi)存結(jié)構(gòu)而非接口進(jìn)行解耦。緊湊的內(nèi)存結(jié)構(gòu)減少了尋址開(kāi)銷,且非常利于優(yōu)化 JVM 的運(yùn)行。IndexR 在保證了高性能、有效索引的基礎(chǔ)上極大地節(jié)省了內(nèi)存,與使用 Parquet 格式查詢時(shí)的內(nèi)存使用量差不多,不會(huì)出現(xiàn)像 CarbonData 需要配置超大內(nèi)存的情況。但是為什么不直接使用 C 或者 C++ 呢?因?yàn)槟壳?Hadoop 生態(tài)最適合的開(kāi)發(fā)語(yǔ)言還是基于 JVM,JVM 語(yǔ)言可與其他系統(tǒng)無(wú)縫集成,在工具鏈支持方面也是最全面的。
6. 易整合:深度整合 Hadoop 生態(tài)。
IndexR 通過(guò)與 Hadoop 生態(tài)的深度整合,適合用來(lái)搭建海量數(shù)據(jù)場(chǎng)景下的數(shù)據(jù)倉(cāng)庫(kù)。
IndexR 與行業(yè)通用方案對(duì)比:
- Parquet,ORC - 他們與 IndexR 一樣都屬于存儲(chǔ)格式,功能上比較類似。目前 IndexR 還不支持較復(fù)雜的數(shù)據(jù)格式,但額外支持索引、實(shí)時(shí)導(dǎo)入、預(yù)聚合等特性。
- CarbonData - CarbonData 也是用于大數(shù)據(jù)分析場(chǎng)景的數(shù)據(jù)格式,并且支持索引,官方文檔稱適用于大量數(shù)據(jù)掃描和少量數(shù)據(jù)查詢的場(chǎng)景,與 IndexR 在存儲(chǔ)格式上的定位非常相近。同樣 IndexR 還額外支持實(shí)時(shí)導(dǎo)入、預(yù)聚合等特性。筆者嘗試使用 CarbonData 與 IndexR 在相同的 Hadoop 集群上做性能對(duì)比,發(fā)現(xiàn) CarbonData 的表現(xiàn)不穩(wěn)定,特別是 Q9 和 Q10,以下是測(cè)試結(jié)果,歡迎同行討論。
使用以上測(cè)試相同集群,CarbonData 1.1.0, Hadoop 2.5.2, Spark 2.1.0. Spark 啟動(dòng)參數(shù):bin/spark-submit --class org.apache.carbondata.spark.thriftserver.CarbonThriftServer --num-executors 5 --executor-cores 10 --executor-memory 31G carbonlib/carbondata_2.11-1.1.0-shade-hadoop2.2.0.jar hdfs://rttest/user/hive/warehouse/carbon.storeCarbonData 表 schema 沒(méi)有設(shè)置 TBLPROPERTIES,使用默認(rèn)參數(shù)。
- Druid - Druid 屬于時(shí)間序列數(shù)據(jù)庫(kù),支持流式導(dǎo)入、實(shí)時(shí)預(yù)聚合,適用于 OLAP 場(chǎng)景。從架構(gòu)上,IndexR 基于 Hadoop,上層使用第三方查詢引擎,而 Druid 只是把文件備份到 Hadoop,數(shù)據(jù)讀取并不經(jīng)過(guò) Hadoop。IndexR 系統(tǒng)支持完整的 SQL,而 Druid 使用自定義 JSON 查詢語(yǔ)句,不支持 SQL(目前有實(shí)驗(yàn) feature,但是支持非常有限),無(wú)法做 JOIN、UNION 等操作。此外,IndexR 還額外支持表結(jié)構(gòu)更新,且過(guò)期數(shù)據(jù)不會(huì)丟棄,在運(yùn)維方面也更加簡(jiǎn)單。
- Kudu、ClickHouse - IndexR 和他們都可以用來(lái)做 OLAP 分析。Kudu 支持 OLTP 的大部分操作,包括數(shù)據(jù)插入、更新、刪除等;IndexR 和 ClickHouse 數(shù)據(jù)只能使用 append 的模式,并且不支持在線更新,目前只能使用分區(qū)管理。Kudu 和 ClickHouse 都獨(dú)立于 Hadoop 生態(tài)之外。