1. 程式人生 > >Elastic Stack 開源的大資料解決方案

Elastic Stack 開源的大資料解決方案

目的


本文主要介紹的內容有以下三點:
一. Elastic Stack是什麼以及組成部分
二. Elastic Stack前景以及業務應用
三. Elasticsearch原理(索引方向)
四. Elasticsearch相對薄弱的地方

一、Elastic Stack是什麼以及組成部分


介紹Elastic Stack是什麼,其實只要一句話就可以,就是: 一套完整的大資料處理堆疊,從攝入、轉換到儲存分析、視覺化。

它是不同產品的集合,各司其職,形成完整的資料處理鏈,因此Elastic Stack也可以簡稱為BLEK。

Beats 輕量型資料採集器

Logstash 輸入、過濾器和輸出

Elasticsearch

查詢和分析

Kibana 視覺化,可自由選擇如何呈現資料

1. Beats - 全品類採集器,搞定所有資料型別

Filebeat(日誌檔案):對成百上千、甚至上萬的伺服器生成的日誌彙總,可搜尋。

Metricbeat(指標): 收集系統和服務指標,CPU 使用率、記憶體、檔案系統、磁碟 IO 和網路 IO 統計資料。

Packetbeat(網路資料):網路資料包分析器,瞭解應用程式動態。

Heartbeat(執行時間監控):通過主動探測來監測服務的可用性
......
Beats支援許許多多的beat,這裡列的都是比較的常用的beat,瞭解更多可以點選連結:Beats 社群

2. Logstash - 伺服器端資料處理管道

介紹Logstash之前,我們先來看下Linux下常用的幾個命令

cat alldata.txt | awk ‘{print $1}’ | sort | uniq | tee filterdata.txt

只要接觸過Linux同學,應該都知道這幾個命名意思

cat alldata.txt #將cat alldata.txt的內容輸出到標準裝置上
awk ‘{print $1}’ #對上面的內容做擷取,只取每一行第一列資料
sort | uniq  #對擷取後的內容,進行排序和唯一性操作
tee filterdata.txt #將上面的內容寫到filterdata.txt

上面的幾個簡單的命令就可以看出來,這是對資料進行了常規的處理,用名詞修飾的話就是:資料獲取/輸入、資料清洗、資料過濾、資料寫入/輸出

而Logstash做的也是相同的事(看下圖)。

將系統的日誌檔案、應用日誌檔案、系統指標等資料,輸入到Input,再通過資料清洗以及過濾,輸入到儲存裝置中,這裡當然是輸入到Elasticsearch

3. Elasticsearch - 分散式文件儲存、RESTful風格的搜尋和資料分析引擎

Elasticsearch主要也是最原始的功能就是搜尋和分析功能。這裡就簡單說一下,下面講原理的時候會著重講到Elasticsearch

搜尋:全文搜尋,完整的資訊源轉化為計算機可以識別、處理的資訊單元形成的資料集合 。

分析:相關度,搜尋所有內容,找到所需的具體資訊(詞頻或熱度等對結果排序)

4. Kibana- 視覺化

視覺化看下圖(來源官網)便知

可以對日誌分析、業務分析等做視覺化

現在從總體上來了解下,在心中對Elastic Stack有個清楚的認知(下圖)。

二、Elastic Stack前景以及業務應用

1. DB-Engines 排名

Elasticsearch是Elastic Stack核心,由圖可以看出在搜尋領域Elasticsearch暫時沒有對手。

2. ES社群

ES中文社群也是相當活躍的,會定期做一下分享,都是大公司的寶貴經驗,值得參考。

3. 2018年攜程的使用情況(讓我們看看能處理多大的資料)

叢集數量是94個,最小的叢集一般是3個節點。全部節點數量大概700+。

最大的一個叢集是做日誌分析的,其中資料節點330個,最高峰一天產生1600億文件,寫入值300w/s。

現在有2.5萬億文件,大概是幾個PB的量

三、Elasticsearch(ES)原理

因為篇目有限,本篇只介紹ES的索引原理。

ES為什麼可以做全文搜尋,主要就是用了倒排索引,先來看下面的一張圖

看圖可以簡單的理解倒排索引就是:關鍵字 + 頁碼

對倒排索引有個基本的認識後,下面來做個簡單的資料例子。

現在對Name做到排索引,記住:關鍵字 + ID(頁碼)。

對Age做到排索引。

對Intersets做到排索引。

現在搜尋Age等於18的,通過倒排索引就可以快速得到1和3的id,再通過id就可以得到具體資料,看,這樣是不是快的狠。

如果是用Mysql等關係資料庫,現在有十多億資料(大資料嘛),就要一條一條的掃描下去找id,效率可想而知。而用倒排索引,早到所有的id就輕輕鬆鬆了。

在ES中,關鍵詞叫Term,頁碼叫Posting List。

但這樣就行了嗎? 如果Name有上億個Term,要找最後一個Term,效率豈不是還是很低?

再來看Name的倒排索引,你會發現,將Armani放在了第一個,Tyloo放在了第三個,可以看出來,對Term做了簡單的排序。雖然簡單,但很實用。這樣查詢Term就可以用二分查詢法來查找了,將複雜度由n變成了logn。

在ES中,這叫Term Dictionary。

到這裡,再來想想MySQL的b+tree, 你有沒有發現原理是差不多的,那為什麼說ES搜尋比MySQL快很多,究竟快在哪裡? 接下來再看。

有一種資料結構叫Trie樹,又稱字首樹或字典樹,是一種有序樹。這種資料結構的好處就是可以壓縮字首和提高查詢資料。

現在有這麼一組Term: apps, apple, apply, appear, back, backup, base, bear,用Trie樹表示如下圖。

通過線路路徑字元連線就可以得到完成的Term,並且合用了字首,比如apps, apple, apply, appear合用了app路徑,節省了大量空間。

這個時候再來找base單詞,立即就可以排除了a字元開頭的單詞,比Term Dictionary快了不知多少。

在ES中,這叫Term Index

現在我們再從整體看下ES的索引

先通過Trie樹快速定位block(相當於頁碼), 再到Term Dictionary 做二分查詢,得到Posting List。

索引優化

ES是為了大資料而生的,這意味著ES要處理大量的資料,它的Term資料量也是不可想象的。比如一篇文章,要做全文索引,就會對全篇的內容做分詞,會產生大量的Term,而ES查詢的時候,這些Term肯定要放在記憶體裡面的。

雖然Trie樹對字首做了壓縮,但在大量Term面前還是不夠,會佔用大量的記憶體使用,於是就有ES對Trie樹進一步演化。

FST(Finite State Transducer )確定無環有限狀態轉移器 (看下圖)

可以看appear、bear 對共同的字尾做了壓縮。

Posting List磁碟壓縮

假設有一億的使用者資料,現在對性別做搜尋,而性別無非兩種,可能"男"就有五千萬之多,按int4個位元組儲存,就要消耗50M左右的磁碟空間,而這僅僅是其中一個Term。

那麼面對成千上萬的Term,ES究竟是怎麼儲存的呢?接下來,就來看看ES的壓縮方法。

Frame Of Reference (FOR) 增量編碼壓縮,將大數變小數,按位元組儲存

只要能把握“增量,大數變小數,按位元組儲存”這幾個關鍵詞,這個演算法就很好理解,現在來具體看看。

現在有一組Posting List:[60, 150, 300,310, 315, 340], 按正常的int型儲存,size = 6 * 4(24)個位元組。

  1. 按增量儲存:60 + 90(150)+ 150(300) + 10(310) + 5(315)+ 25(340),也就是[60, 90, 150, 10, 5, 25],這樣就將大數變成了小數。

  2. 切分成不同的block:[60, 90, 150]、[10, 5, 25],為什麼要切分,下面講。

  3. 按位元組儲存:對於[60, 90, 150]這組block,究竟怎麼按位元組儲存,其實很簡單,就是找其中最大的一個值,看X個位元能表示這個最大的數,那麼剩下的數也用X個位元表示(切分,可以儘可能的壓縮空間)。

[60, 90, 150]最大數150 < 2^8 = 256,也就是這組每個數都用8個位元表示,也就是 3*8 = 24個位元,再除以8,也就是3個位元組存在,再加上一個8的標識位(說明每個數是8個位元儲存),佔用一個位元組,一共4個位元組。

[10, 5, 25]最大數25 < 2^5 = 32,每個數用5個位元表示,3*5=15位元,除以8,大約2個位元組,加上5的標識位,一共3個位元組。

那麼總體size = 4 + 3(7)個位元組,相當於24個位元組,大大壓縮了空間。

再看下圖表示

Posting List記憶體壓縮

同學們應該都知道越複雜的演算法消耗的CPU效能就越大,比如常見的https,第一次互動會用非對稱密碼來驗證,驗證通過後就轉變成了對稱密碼驗證,FOR同樣如此,那麼ES是用什麼演算法壓縮記憶體中的Posting List呢?

Roaring Bitmaps 壓縮點陣圖索引

Roaring Bitmaps 涉及到兩種資料結構 short[] 、bitmap。

short好理解就是2個位元組的整型。

bitmap就是用位元表示資料,看下面的例子。

Posting List:[1, 2, 4, 7, 10] -> [1, 1, 0, 1, 0, 0, 1,0, 0, 1],取最大的值10,那麼就用10個位元表示這組Posting List,第1, 2, 4, 7, 10位存在,就將相對應的“位”置為1,其他的為0。

但這種bitmap資料結構有缺陷,看這組Posting List: [1, 3, 100000000] -> [1, 0, 1, 0, 0, 0, …, 0, 0, 1 ],最大數是1億,就要1億的位元表示,這麼算下來,反而消耗了更多的記憶體。

那如何解決這個問題,其實也很簡單,跟上面一樣,將大數變成小數。

看下圖:

第一步:將每個數除以65536,得到(商,餘數)。

第二步:按照商,分成不同的block,也就是相同的商,放在同一個block裡面,餘數就是這個值在這個block裡面的位置(永遠不會超過65536,餘數嘛)。

第三步:判斷底層block用什麼資料結構儲存資料,如果block裡面的餘數的個數超過4096個,就用short儲存,反之bitmap。

上面那個圖是官網的圖,看下我畫的圖,可能更好理解些。

到這裡,ES的索引原理就講完了,希望大家都能理解。

四、Elasticsearch(ES)相對薄弱的地方

1. 多表關聯

其實ES有一個很重要的特性這裡沒有介紹到,也就是分散式,每一個節點的資料和,才是整體資料。

這也導致了多表關聯問題,雖然ES裡面也提供了Nested& Join 方法解決這個問題,但這裡還是不建議用。

那這個問題在實際應用中應該如何解決? 其實也很簡單,裝換思路,ES無法解決,就到其他層解決,比如:應用層,用面向物件的架構,拆分查詢。

2. 深度分頁

分散式架構下,取資料便不是那麼簡單,比如取前1000條資料,如果是10個節點,那麼每個節點都要取1000條,10個節點就是10000條,排序後,返回前1000條,如果是深度分頁就會變的相當的慢。

ES提供的是Scroll + Scroll_after,但這個採取的是快取的方式,取出10000條後,快取在記憶體裡,再來翻頁的時候,直接從快取中取,這就代表著存在實時性問題。

來看看百度是怎麼解決這個問題的。

一樣在應用層解決,翻頁到一定的深度後,禁止翻頁。

3. 更新應用

頻繁更新的應用,用ES會有瓶頸,比如一些遊戲應用,要不斷的更新資料,用ES不是太適合,這個看大家自己的應用情況