本周在數(shù)據(jù)庫研發(fā)和運營組做了關(guān)于ELK的分享,這個分享主要是居于ES部分做的相關(guān)理論和測試的結(jié)論。下面是對此次分享的文字版整理,希望對研究學(xué)習(xí)ElasticSearch的朋友們有幫助。
分享的主要內(nèi)容如下:

先來說一下去調(diào)研ES的初衷,是為了確認ElasticSearch是否能比較好地解決目前監(jiān)控DB遇到的幾個問題,如下圖所示:
監(jiān)控DB目前面臨的三個問題分別是:

容量瓶頸
監(jiān)控DB的數(shù)據(jù)量越來越大,單個表壓縮后有的已經(jīng)接近100G(一天的數(shù)據(jù)),目前采用的是MySQL來存儲,使用的TokuDB引擎。MySQL的擴容型并不好,因此無法快速的進行數(shù)據(jù)的擴容,目前的做法更多的是對過期的歷史數(shù)據(jù)進行清理。但是需要保留月初、月末以及節(jié)假日的數(shù)據(jù)。
性能瓶頸
監(jiān)控有很多聚合的查詢,在單表特別大的情況下,一個聚合SQL需要很長時間才能查詢出結(jié)果。無法很好展現(xiàn)監(jiān)控的實時效果。給業(yè)務(wù)的體驗也很糟糕。
穩(wěn)定性
如果監(jiān)控DB出現(xiàn)問題,會導(dǎo)致線上監(jiān)控曲線掉底,業(yè)務(wù)側(cè)會以為是自己線上出現(xiàn)了問題,這會給業(yè)務(wù)帶來很大的困擾,因此對監(jiān)控DB的穩(wěn)定性要求很高??雨犛训氖虑楸O(jiān)控DB還是盡量少干。
下面就來單獨介紹各個部分的內(nèi)容:
一、ELK簡介
(一)ELK的涵義
ELK其實是由三個組建組成,分別是ElasticSearch、Logstash以及Kibana。
1、E代表ElasticSearch,如下圖所示:

正上圖說的那樣,ELasticSearch是整個ELK的心臟,它負責(zé)索引的創(chuàng)建、搜索、分析以及數(shù)據(jù)的存儲等工作,這個組將在后面做詳細介紹。
2、L代表Logstash,如下圖所示:

Logstash是用來做數(shù)據(jù)采集、接收、處理和轉(zhuǎn)發(fā)的工具,它講采集來的數(shù)據(jù)經(jīng)過分析和處理以后,將數(shù)據(jù)發(fā)送到ElasticSearch存儲。它本身支持非常多的數(shù)據(jù)源。
3、K代表Kibana,如下圖所示:

Kibana的主要功能是負責(zé)將ES中數(shù)據(jù)進行炫酷的展示。
整理概括一下整個ELK就是:
Logstash負責(zé)數(shù)據(jù)采集、分析和處理,然后將數(shù)據(jù)發(fā)送給ElasticSearch做進一步的存儲、分析和搜索,最后Kibana講ElasticSearch中的數(shù)據(jù)炫酷地展示出來。
(二)ELk常用架構(gòu)
ELK的常用架構(gòu)如下圖所示(偷懶盜個圖):

使用Logstash Shipper來在機器上采集相關(guān)的數(shù)據(jù)或者日志,你可以理解為logstash的一個agent
中間使用redis做隊列,也有很多的公司使用kafka來代替redis。
(三)ELK在業(yè)界的使用情況
目前ELK比較活,社區(qū)也很活躍,有很業(yè)務(wù)都在使用,主要分為三類應(yīng)用:
1、全文檢索
比如github和維基百科
2、日志監(jiān)控類
比如騰訊云監(jiān)控、斗魚日志分析平臺
3、數(shù)據(jù)分析和查詢
比如:DELL,sprint
此外國外還有一些公司用ES來存儲地理位置數(shù)據(jù),比如Foursquare公司,結(jié)合搜索和地理位置兩者提供更優(yōu)質(zhì)的服務(wù)。
二、ES技術(shù)細節(jié)
ES技術(shù)細節(jié)部分主要介紹如下幾個方面:
(一)、ES的特性
1、Base on Apache Lucense
Lucense是高性能的搜索引擎庫,提供了查詢引擎、搜索引擎和文本分析引擎。但是使用Lucense成本很高,需要掌握很多關(guān)于搜索的知識。而ES使用Lucense作為底層架構(gòu),在其上做了大量的易用性、擴展性、容災(zāi)以及性能方面的工作,使得用戶經(jīng)過很少的配置就可以快速ES進行數(shù)據(jù)存儲和檢索。
2、Distributed and horizontally scalable
ES是分布式的,可以水平擴展,比如添加節(jié)點的時候能自動均衡數(shù)據(jù)。
3、Full-text search and powerful search
ES支持前文支持全文索引,并且搜索功能非常強大。
4、Document & Json
ES是基于文檔的強大組件,交互數(shù)據(jù)全部采用Json標(biāo)準(zhǔn)格式。
5、Restful API
6、Open Source
7、Query DSL
ES提供了基于JSON的query DSL查詢語言,傳統(tǒng)的SQL語句很容易轉(zhuǎn)化成query DSL。后面做的關(guān)于MySQL和ES的性能比對也是將標(biāo)準(zhǔn)SQL改寫成query DSL實現(xiàn)的。
(二)、ES集群組成和名詞解析

1、名稱解析
a、Cluster
ES由個data節(jié)點和1個master節(jié)點構(gòu)成ES 集群,ES集群具有容災(zāi)能力,官方建議的也是使用ES集群的方式來運維ES。
b、Node
Node是ES的節(jié)點,一般集群會有1個master節(jié)點,多個data節(jié)點,ES節(jié)點有如下幾種類型:
master節(jié)點
master的功能是維護ES集群的元數(shù)據(jù),比如創(chuàng)建刪除索引;監(jiān)控其他的節(jié)點,比如對故障節(jié)點進行剔除和協(xié)調(diào)故障恢復(fù)工作;此外master節(jié)點還負責(zé)分片具體分配給哪些節(jié)點。因此在擴容和這故障的時候,分片遷移到哪臺機器上也需要master來協(xié)調(diào)。
需要注意的是所有的涉及到路由變化的操作都必須master來做。
建議:master非常重要,比較大的集群建議講master獨立部署
data節(jié)點
data節(jié)點負責(zé)數(shù)據(jù)的存儲和檢索。
Coordinating節(jié)點
Coordinating節(jié)點不負責(zé)數(shù)據(jù)的存儲,只負責(zé)請求的轉(zhuǎn)發(fā),有點類似于負載均衡器
Tribal節(jié)點
tribal節(jié)點成為部落節(jié)點,通過它能夠查詢不通集群的ES數(shù)據(jù),有點類似于spider的功能。
c、Shard
Shard是分片的意思,一般一個很大的表為了保證其擴展能力都會水平切分為多個分片,類似于mysql的水平分表的概念。每個分片只存儲自己那部分的數(shù)據(jù)和索引信息,全部的分片數(shù)據(jù)的集合就是全量的數(shù)據(jù)。
因為分片建立以后,如果后面要增加分片,需要全量導(dǎo)入數(shù)據(jù),因此分片必須在創(chuàng)建索引之前就規(guī)劃好。具體的可以從索引的數(shù)據(jù)量、集群節(jié)點的個數(shù)和預(yù)計集群的規(guī)模等方面進行合理的評估。
d、Replica
Replica副本,ES官方建議至少1副本,否則容易出現(xiàn)數(shù)據(jù)丟失的風(fēng)險。在ES中副本主要有2個作用:
其一是提供數(shù)據(jù)安全性保障,其二副本也能夠分擔(dān)讀的請求,提高ES的性能。
e、Index
Index是索引的意思,和關(guān)系型數(shù)據(jù)庫中的索引很不一樣。ES中Index的概念類似于關(guān)系型數(shù)據(jù)庫中的database。
f、Type
Type是分類的意思,和關(guān)系型數(shù)據(jù)庫中table的概念比較類似。為提高性能,建議最好是一個Index就存儲一個Type的數(shù)據(jù)就好。
g、Mapping
Mapping的概念和關(guān)系型數(shù)據(jù)庫中的字段類型比較類似,如下ES中定義的Type字段類型:

h、Document
ES是文檔型的組建,Document類似于關(guān)系型數(shù)據(jù)庫的一行。在ES中就是一個文檔。
2、集群組成
從上圖中可以看到,ES集群是由多個節(jié)點組成,上圖中有1個master節(jié)點和2個data節(jié)點組成,并且創(chuàng)建了1個索引,索引有4個數(shù)據(jù)分片和1個副本組成。Translog為ES提供高性能以及數(shù)據(jù)安全保障。
(三)、ES的寫邏輯
ES的寫入簡圖如下:

ES的寫操作分為兩類,一類是涉及到路由變更的索引創(chuàng)建和刪除(簡稱為索引的寫入),另一類是基于文檔的創(chuàng)建、更新和刪除(簡稱為文檔的寫入)。
下面單獨來進行介紹:
1、索引的寫入
無論是索引的創(chuàng)建還是刪除,都必須在master上進行。因此,如果寫入的請求是發(fā)到了非master節(jié)點,該節(jié)點會講對應(yīng)的創(chuàng)建或者刪除的請求轉(zhuǎn)發(fā)給master,master會創(chuàng)建并修改元數(shù)據(jù)和路由信息,并將對應(yīng)的修改同步到其他的候選的master機器上,至少需要需要一半以上的候選master返回后才算寫入成功。
2、文檔的寫入
文檔的寫入的前提是所有的寫入都必須先發(fā)送到主分片上,大致的步驟為:
a、文檔寫入請求發(fā)送到任意的一個節(jié)點
b、節(jié)點根據(jù)shard = hash(routing) % number_of_primary_shards確定數(shù)據(jù)所在的分片以及根據(jù)元數(shù)據(jù)確認主分片是在哪臺機器
c、在主分片上執(zhí)行寫入操作和translog寫入操作,并且將請求發(fā)送到副本上進行寫入和translog寫入
d、默認是同步操作,必須主分片和副本分片都些成功財返回結(jié)果,也可以人為調(diào)整為異步操作,不過會有數(shù)據(jù)安全性問題。
注意:默認ES提供近實時的搜索,也就是說文檔寫入或者更新后不是馬上就能搜索出最新的變更,默認需要過1秒reflush后才能看到,如果業(yè)務(wù)對實時性要求非常高,也可以將reflush的相關(guān)的參數(shù)設(shè)置為request,即有新的請求就執(zhí)行reflush的操作,這種方式性能會比較差。此外你還可以調(diào)用reflush的API手動進行reflush的操作。
(四)、ES的讀邏輯
ES的讀邏輯如下圖所示:

ES查詢的時候如果指定了routing相關(guān)的值,就會只掃描確定的1個或者少數(shù)文檔,如果沒有指定routing相關(guān)的值就需要掃描所有的分片。因此還會涉及到查詢的拆分和合并的步驟。詳情如下:
a、查詢請求發(fā)送到任意一個節(jié)點
b、如果指定了routing的相關(guān)值,根據(jù)shard = hash(routing) % number_of_primary_shards公式就能直接計算出請求的數(shù)據(jù)所在的分片,然后將請求發(fā)送到對應(yīng)的分片就OK。如果指定routing的相關(guān)值,那么會發(fā)送到對應(yīng)查詢涉及到的所有分片(這就是請求拆分)。
c、如果查詢只涉及到1個分片,查詢的分片所在的機器返回查詢結(jié)果到初始請求的節(jié)點,初始請求節(jié)點再將數(shù)據(jù)返回給業(yè)務(wù)。而如果查詢涉及到多個分片,初始節(jié)點就會將請發(fā)送給多個分片并發(fā)查詢,此時查詢的分片所在的機器返回查詢結(jié)果到初始請求的節(jié)點后,初始節(jié)點還需要再進行結(jié)果的合并。初始節(jié)點將合并后的數(shù)據(jù)返回個業(yè)務(wù)。
(五)、ES的容災(zāi)
ES有很完善的容災(zāi)機制,候選master一般有多個,data節(jié)點也有多個,因此節(jié)點異常的時候通過將訪問切換到別的節(jié)點來容災(zāi)。具體流程包含如下幾個流程:
1、故障發(fā)現(xiàn)
故障發(fā)現(xiàn)如下圖所示:

從上圖中可以看出,Master會去ping各個其他的節(jié)點,圖中只畫了datanode節(jié)點。而其他的節(jié)點也會去ping master節(jié)點,確認master節(jié)點是否正常。默認ping規(guī)則如下:
Discovery.zen.fd.ping_interval=1s ?默認每隔1秒探測1次
Discovery.zen.fd.ping_timeout=30s 默認ping探測的超時時間為30秒
Discovery.zen.fd.ping_retry=3 ?默認重試3次
#備注,以上參數(shù)可以根據(jù)自己的網(wǎng)絡(luò)情況和業(yè)務(wù)需求進行調(diào)整。
2、節(jié)點切換
master節(jié)點切換
當(dāng)其他節(jié)點探測到master異常并達到重試次數(shù)后,候選節(jié)點會進行競爭,選master的具體規(guī)則如下:
a、每次選舉每個節(jié)點會把自己所知道的候選master節(jié)點根據(jù)nodeid進行一次排序,然后選出第1個節(jié)點,暫且人為它是master節(jié)點;
b、如果對某個節(jié)點的投票數(shù)達到 候選master數(shù)/2+1 個并且該節(jié)點也選舉自己為master,那么這個節(jié)點即為master。否則重新選舉;
備注:之所以節(jié)點的投票數(shù)需要達到候選master數(shù)/2+1,是為了防止腦裂的問題發(fā)生。
data節(jié)點切換
當(dāng)master節(jié)點檢測到某個data節(jié)點有異常的時候,做的操作大致如下:
a、master剔除該data節(jié)點,如果ES數(shù)據(jù)配置了1份副本保存,此時不存在數(shù)據(jù)丟失的風(fēng)險,集群狀態(tài)為yelllow。如果數(shù)據(jù)沒有配置副本保存,則存在數(shù)據(jù)丟失,集群狀態(tài)為red。
b、master對找出異常的data節(jié)點對應(yīng)的所有的數(shù)據(jù)分片,如果是主分片,則將其他節(jié)點上的副本分片提升為主分片,全部主分片恢復(fù)后,異常data節(jié)點涉及的數(shù)據(jù)讀寫都恢復(fù)正常。
c、業(yè)務(wù)恢復(fù)正常以后,master會將異常節(jié)點的數(shù)據(jù)遷移到正常的節(jié)點
d、全部數(shù)據(jù)遷移完成后,集群狀態(tài)恢復(fù)為green
(六)、ES的擴容
ES設(shè)計成能讓你靈活地擴縮容模型,當(dāng)你添加或者減少data節(jié)點的時候,ES會自動的對數(shù)據(jù)進行均衡。如下幾個簡圖能讓你幾秒鐘了解ES的擴容問題,下面幾個圖的索引設(shè)置為number_of_shards=3 &&?number_of_replicas=1,即索引為3個分片并且每個分片有1個副本。
1、一個節(jié)點的ES Cluster

從上圖中可以看到雖然設(shè)置了1個副本,但是datanode1只分配了3個主分片。這是因為ES認為如果副本和主分片在1臺機器上和沒有副本的效果一樣,當(dāng)那臺機器異常的時候,數(shù)據(jù)一樣丟失。因此ES沒有在那臺機器上分配副本分片。
2、擴容一個節(jié)點后的ES Cluster

從上圖中,可以看到添加1個節(jié)點后,data節(jié)點2分配了2個副本。
3、再擴容一個節(jié)點后的ES Cluster

從上圖中可以看到,data節(jié)點1上的P1被移動到了data節(jié)點3,data節(jié)點2上的R3被移動到了data節(jié)點3,這是因為添加節(jié)點后,ES會自動均衡數(shù)據(jù)。
三、ES讓人驚喜的功能
做為一個運維人員,在學(xué)習(xí)ES的時候,遇到了很多讓人驚喜的功能,整理出來和大家共享:
(一)、ES的GROUP功能
ES的group功能和HBase的group功能類似,可以將某些節(jié)點放到某一個GROUP中,從而實現(xiàn)業(yè)務(wù)之間的隔離。比如想講重點業(yè)務(wù)和普通業(yè)務(wù)隔離開來,就可以將重點業(yè)務(wù)放到指定的某個組,這個組不存在過保的設(shè)備,負載也比較低。而將普通業(yè)務(wù)放到普通的組中,這各組的設(shè)備由于比較老,故障率會比較搞,組內(nèi)的機器負載也會高一些。如下圖所示:

圖中有兩個組,分別是GroupA和GroupB,其中GroupA中保存這某些索引,GroupB中也保存著某些分片。ES有專門的參數(shù)控制索引可以存儲在某個Group或則節(jié)點,具體的參數(shù)如下:
cluster.routing.allocation.awareness.attributes
cluster.routing.allocation.include
cluster.routing.allocation.require
cluster.routing.allocation.exclude
(二)、ES部落節(jié)點功能

ES從1.0版本開始支持使用部落節(jié)點(tribe node),所謂的部落節(jié)點,就是作為聯(lián)合客戶端提供訪問多個ElasticSearch集群的能力。業(yè)務(wù)只需要訪問部落節(jié)點,就可以獲取多個ES集群的數(shù)據(jù)。并且可以通過部落節(jié)點寫入數(shù)據(jù),寫入數(shù)據(jù)的時候部落節(jié)點會將寫入請求轉(zhuǎn)發(fā)到后端的集群節(jié)點進行數(shù)據(jù)寫入。但是不支持創(chuàng)建索引的操作。注意:如果部落節(jié)點對應(yīng)后端的ES集群含有相同的索引名稱就會出現(xiàn)莫名其妙的問題,因為ES的默認行為是從中選擇一個。也就是說如果后端2個集群含有相同的索引名字,那么知會有一個索引會被訪問到。部落節(jié)點的圖解如下:
(三)、ES的IO流控功能
ES還有個比較好的功能就是IO流控的功能,這個功能對于分布式存儲是非常必要的,比如可以限制文件合并的時候的IO,從而使系統(tǒng)更平穩(wěn)地運行。ES主要有節(jié)點級和索引級兩個限流機制。分別介紹如下:
節(jié)點級別限流
Indices.store.throttle.type(none/merge/all)
可以選擇為none/merge/all三個值,意義分別如下:
none為不流控
merge為對合并做IO流控
all為對所有的操作做IO流控
Indices.store.throttle.max_bytes_per_sec
索引級別限流
Index.store.throttle.type(none/merge/all/node)
Index.store.throttle.max_bytes_per_sec
(四)、ES的慢日志功能
ES有類似于MySql的慢查詢功能,可以記錄下慢的操作,從而讓運維人員能通過慢的操作找到問題所在。默認情況下,慢日志是不開啟的,有三種動作可以定義,分別是query、fetch、index三類,如下是一個query的慢日志定義:
PUT /my_index/_settings
{
"index.search.slowlog.threshold.query.warn" : "10s",
"index.search.slowlog.threshold.fetch.debug": "500ms",
"index.indexing.slowlog.threshold.index.info": "5s"
}
上面設(shè)置的意思如下:
查詢慢于 10 秒輸出一個 WARN 日志。
獲取慢于 500 毫秒輸出一個 DEBUG 日志。
索引慢于 5 秒輸出一個 INFO 日志。
(五)、ES的發(fā)現(xiàn)熱點功能
ES有個查詢集群熱點線程的功能,這個功能在集群突然變慢的場景下特別有用,它將幫助你找到消耗資源最多的線程。熱點線程的使用方法如下:
curl 'http://localhost:9200/_nodes/hot_threads'
返回的結(jié)果中含有線程所在的節(jié)點信息、線程消耗資源的情況、線程名稱以及相關(guān)的堆棧信息,如下圖所示:

四、ES的性能
ES的性能主要從兩個維度來評估
(一)、ES VS InfluxDB
1、單節(jié)點ES和InfluxDB寫入性能對比(數(shù)據(jù)來自:http://km.oa.com/articles/show/334237?kmref=search&from_page=1&no=1)

結(jié)論:ES單節(jié)點寫入性能最高在19w,InfluxDB在15w。在并發(fā)數(shù)超過20時,ES與InfluxDB的寫入性能均呈現(xiàn)出下降趨勢。
2、單節(jié)點ES和InfluxDB讀性能對比(數(shù)據(jù)來自:http://km.oa.com/articles/show/334237?kmref=search&from_page=1&no=1)

結(jié)論:ES查詢性能整體比InfluxDB好很多,當(dāng)并發(fā)數(shù)較高時(40),ES查詢性能比InfluxDB高出近4倍,在2w左右。在并發(fā)線程數(shù)達到50時,InfluxDB出現(xiàn)鏈接錯誤,拒絕查詢請求。
備注:測試結(jié)果只所以和influxDB官方測試數(shù)據(jù)比較大,我因為TEG側(cè)對es本身和influx的測試工具都做了很多優(yōu)化,主要的優(yōu)化如下:
es優(yōu)化:關(guān)閉不必要的字段,routing,調(diào)整刷盤策略、shard數(shù)量等
influxDB測試工具優(yōu)化:支持routing、在保證查詢結(jié)果一致的情況下盡量優(yōu)化查詢語句
(二)、ES VS MySQL
這部分的測試是采用人工寫的SQL以及線上慢的SQL像結(jié)合的方式,測試結(jié)果如下:

備注:MySQL測試數(shù)據(jù)采用的是innodb引擎,并采用50%的壓縮比。
從性能來看ES要比MySQL要好,尤其在聚合的場景下。
五、ES替代監(jiān)控DB評估
1、性能評估
從線上實際SQL評估,ES的性能要比MySQL的性能好100倍以上,性能方面應(yīng)該不是瓶頸。
2、容量評估
優(yōu)化前ES實際占用容量和MySQL差不多,優(yōu)化后ES占用的容量為MySQL的40%左右。
3、可用性評估
ES本身有很好的伸縮機制和容災(zāi)機制,從目前的容災(zāi)測試來看,可用性能達到要求。
4、成本評估
目前監(jiān)控DB的瓶頸主要是在容量瓶頸,因此存儲量下降50%的情況下,設(shè)備量能下降到原來的50%,即成本下降50%。
5、研發(fā)評估
ES目前無權(quán)限認證(TEG已經(jīng)添加了ES的權(quán)限認證功能)
不支持事務(wù)目前監(jiān)控側(cè)也暫時沒問題。此外還有很大的部分需要研發(fā)側(cè)的評估,因為采用ES后如下兩個地方會有很大的變動:
數(shù)據(jù)上報部分需要改寫
查詢部分SQL以及格式處理需要改寫
六、感謝
特別感謝TEG同事@johngqjiang的指點,順便廣告一下,TEG基于ES上開發(fā)的時序數(shù)據(jù)庫CTSDB已經(jīng)開始大規(guī)模試用,需要試用的同事可以找johngqjiang進一步溝通。