各位運維同行朋友們,大家好,非常高興能有這麼個機會與大家一起交流一些技術問題。此前的各位分享達人們在技術領域或管理領域均有十分精彩的分享,他們帶給我們的是多個領域中研究或實踐的最前沿知識。這使我本人獲益良多,首先要鄭重感謝他們。
開始之前,本人首先做一下自我介紹。
馬永亮,馬哥Linux運維教育訓練創始人,已直接培養Linux運維工程師一千多人,他們絕大多數從事Linux運維和相關管理崗位,就業公司包括但不限于阿裡、騰訊、百度、京東、網易、新浪、搜狐、大衆點評、餓了麼等。課程的間接受益者數萬人。
這些一線的運維或運維開發工程師不斷地将知識、經驗或應用趨勢等回報給我們,也是以,我們的課程體系也發展為了快速疊代和演進的模式。另外,不斷地通過各種管道指導他們解決實踐中的問題的經驗也成為課堂中案例的組成部分。
比如今天的分享,沿用我們的一貫方式,初衷是為那些不甚了解、即将或剛用到ELK stack的朋友們提供一個可落地的思路和實踐方法。而ELK達人們還請多批評指正。
下面進入正題。今天的分享共分為如下幾個組成部分。不過,如果時間上來不及,可能隻會聊前兩個而不及其餘。
1、搜尋引擎元件介紹;
2、ElasticSearch工作原理、查詢及常用插件;
3、日志收集器Logstash及常見的同類工具;
4、可視化工具Kibina;
5、使用案例及優化思路;
一、關于搜尋引擎
各位知道,搜尋程式一般由索引鍊及搜尋元件組成。
索引鍊功能的實作需要按照幾個獨立的步驟依次完成:檢索原始内容、根據原始内容來建立對應的文檔、對建立的文檔進行索引。
搜尋元件用于接收使用者的查詢請求并傳回相應結果,一般由使用者接口、建構可程式設計查詢語句的方法、查詢語句執行引擎及結果展示元件組成。
如圖所示。

著名的開源程式Lucene是為索引元件,它提供了搜尋程式的核心索引和搜尋子產品,例如圖中的“Index”及下面的部分;而ElasticSearch則更像一款搜尋元件,它利用Lucene進行文檔索引,并向使用者提供搜尋元件,例如“Index”上面的部分。二者結合起來組成了一個完整的搜尋引擎。
二、索引元件
索引是一種資料結構,它允許對存儲在其中的單詞進行快速随機通路。當需要從大量文本中快速檢索文本目标時,必須首先将文本内容轉換成能夠進行快速搜尋的格式,以建立針對文本的索引資料結構,此即為索引過程。
它通常由邏輯上互不相關的幾個步驟組成。
第一步:擷取内容。
過網絡爬蟲或蜘蛛程式等來搜集及界定需要索引的内容。Lucene并不提供任何擷取内容的元件,是以,需要由其它應用程式負責完成這一功能,例如著名的開源爬蟲程式Solr、Nutch、Grub及Aperture等。必要時,還可以自行開發相關程式以高效擷取自有的特定環境中的資料。擷取到的内容需要建立為小資料塊,即文檔(Document)。
第二步:建立文檔。
擷取的原始内容需要轉換成專用部件(文檔)才能供搜尋引擎使用。
一般來說,一個網頁、一個PDF文檔、一封郵件或一條日志資訊可以作為一個文檔。文檔由帶“值(Value)”的“域(Field)”組成,例如标題(Title)、正文(body)、摘要(abstract)、作者(Author)和連結(url)等。不過,二進制格式的文檔處理起來要麻煩一些,例如PDF檔案。
對于建立文檔的過程來說有一個常見操作:向單個的文檔和域中插入權重值,以便在搜尋結果中對其進行排序。權值可在索引操作前靜态生成,也可在搜尋期間才動态生成。權值決定了其搜尋相關度。
第三步:文檔分析。
搜尋引擎不能直接對文本進行索引,确切地說,必須首先将文本分割成一系列被稱為語彙單元(token)的獨立原子元素,此過程即為文檔分析。每個token大緻能與自然語言中的“單詞”對應起來,文檔分析就是用于确定文檔中的文本域如何分割成token序列。
此即為切詞,或分詞。
文檔分析中要解決的問題包括如何處理連接配接一體的各個單詞、是否需要文法修正(例如原始内容存在錯别字)、是否需要向原始token中插入同義詞(例如laptop和notebook)、是否需要将大寫字元統一轉換為小寫字元,以及是否将單數和複數格式的單詞合并成同一個token等。這通常需要詞幹分析器等來完成此類工作,Lucene提供了大量内嵌的分析器,也支援使用者自定義分析器,甚至聯合Lucene的token工具和過濾器建立自定義的分析鍊。
第四步:文檔索引
在索引步驟中,文檔将被加入到索引清單。事實上,Lucene為此僅提供了一個非常簡單的API,而後自行内生地完成了此步驟的所有功能。
接下來,我們說搜尋元件。
索引處理就是從索引中查找單詞,進而找到包含該單詞的文檔的過程。搜尋品質主要由查準率(Precision)和查全率(Recall)兩個名額進行衡量。查準率用來衡量搜尋系列過濾非相關文檔的能力,而查全率用來衡量搜尋系統查找相關文檔的能力。
另外,除了快速搜尋大量文本和搜尋速度之後,搜尋過程還涉及到了許多其它問題,例如單項查詢、多項查詢、短語查詢、通配符查詢、結果ranking和排序,以及友好的查詢輸入方式等。這些問題的解決,通常需要多個元件協作完成。
1、使用者搜尋界面
UI(User Interface)是搜尋引擎的重要組成部分,使用者通過搜尋引擎界面進行搜尋互動時,他們會送出一個搜尋請求,該請求需要先轉換成合适的查詢對象格式,以便搜尋引擎能執行查詢。
2、建立查詢
戶送出的搜尋請求通常以HTML表單或Ajax請求的形式由浏覽器送出到搜尋引擎伺服器,是以,需要事先由查詢解析器一類的元件将這個請求轉換成搜尋引擎使用的查詢對象格式。
3、搜尋查詢
當查詢請求建立完成後,就需要查詢檢索索引并傳回與查詢語句比對的并根據請求排好序的文檔。搜尋查詢元件有着複雜的工作機制,它們通常根據搜尋理論模型執行查詢操作。常見的搜尋理論模型有純布爾模型、向量空間模型及機率模型三種。Lucene采用了向量空間模型和純布爾模型。
4、展現結果
查詢獲得比對查詢語句并排好序的文檔結果集後,需要用直覺、經濟的方式為使用者展現結果。UI也需要為後續的搜尋或操作提供清晰的向導,如完善搜尋結果、尋找與比對結果相似的文檔、進入下一頁面等。
三、Lucene
Lucene是一款高性能的、可擴充的資訊檢索(IR)工具庫,是由Java語言開發的成熟、自由開源的搜尋類庫,基于Apache協定授權。Lucene隻是一個軟體類庫,如果要發揮Lucene的功能,還需要開發一個調用Lucene類庫的應用程式。
文檔是Lucene索引和搜尋的原子機關,它是包含了一個或多個域的容器,而域的值則是真正被搜尋的内容。每個域都有其辨別名稱,通常為一個文本值或二進制值。将文檔加入索引中時,需要首先将資料轉換成Lucene能識别的文檔和域,域值是被搜尋的對象。例如,使用者輸入搜尋内容“title:elasticsearch”時,則表示搜尋“标題”域值中包含單詞“elasticsearch”的所有文檔。
都是文字,大家可能看的眼花。參考一幅從網際網路上擷取的圖檔吧。
如前所述,ElasticSearch在底層利用Lucene完成其索引功能,是以其許多基本概念源于Lucene。
四、ES的基本概念
索引(Index)
ES将資料存儲于一個或多個索引中,索引是具有類似特性的文檔的集合。類比傳統的關系型資料庫領域來說,索引相當于SQL中的一個資料庫,或者一個資料存儲方案(schema)。索引由其名稱(必須為全小寫字元)進行辨別,并通過引用此名稱完成文檔的建立、搜尋、更新及删除操作。一個ES叢集中可以按需建立任意數目的索引。
類型(Type)
類型是索引内部的邏輯分區(category/partition),然而其意義完全取決于使用者需求。是以,一個索引内部可定義一個或多個類型(type)。一般來說,類型就是為那些擁有相同的域的文檔做的預定義。例如,在索引中,可以定義一個用于存儲使用者資料的類型,一個存儲日志資料的類型,以及一個存儲評論資料的類型。類比傳統的關系型資料庫領域來說,類型相當于“表”。
文檔(Document)
文檔是Lucene索引和搜尋的原子機關,它是包含了一個或多個域的容器,基于JSON格式進行表示。文檔由一個或多個域組成,每個域擁有一個名字及一個或多個值,有多個值的域通常稱為“多值域”。每個文檔可以存儲不同的域集,但同一類型下的文檔至應該有某種程度上的相似之處。
三者關系,如圖中所示。
映射(Mapping)
ES中,所有的文檔在存儲之前都要首先進行分析。使用者可根據需要定義如何将文本分割成token、哪些token應該被過濾掉,以及哪些文本需要進行額外處理等等。另外,ES還提供了額外功能,例如将域中的内容按需排序。事實上,ES也能自動根據其值确定域的類型。
節點(Node)
運作了單個執行個體的ES主機稱為節點,它是叢集的一個成員,可以存儲資料、參與叢集索引及搜尋操作。類似于叢集,節點靠其名稱進行辨別,預設為啟動時自動生成的随機Marvel字元名稱。使用者可以按需要自定義任何希望使用的名稱,但出于管理的目的,此名稱應該盡可能有較好的識别性。節點通過為其配置的ES叢集名稱确定其所要加入的叢集。
分片(Shard)和副本(Replica)
ES的“分片(shard)”機制可将一個索引内部的資料分布地存儲于多個節點,它通過将一個索引切分為多個底層實體的Lucene索引完成索引資料的分割存儲功能,這每一個實體的Lucene索引稱為一個分片(shard)。每個分片其内部都是一個全功能且獨立的索引,是以可由叢集中的任何主機存儲。建立索引時,使用者可指定其分片的數量,預設數量為5個。
Shard有兩種類型:primary和replica,即主shard及副本shard。Primary shard用于文檔存儲,每個新的索引會自動建立5個Primary shard,當然此數量可在索引建立之前通過配置自行定義,不過,一旦建立完成,其Primary shard的數量将不可更改。Replica shard是Primary Shard的副本,用于備援資料及提高搜尋性能。每個Primary shard預設配置了一個Replica shard,但也可以配置多個,且其數量可動态更改。ES會根據需要自動增加或減少這些Replica shard的數量。
ES叢集可由多個節點組成,各Shard分布式地存儲于這些節點上。
ES可自動在節點間按需要移動shard,例如增加節點或節點故障時。簡而言之,分片實作了叢集的分布式存儲,而副本實作了其分布式處理及備援功能。
ElasticSearch的RESTful API通過tcp協定的9200端口提供,可通過任何趁手的用戶端工具與此接口進行互動,這其中包括最為流行的curl。curl與ElasticSearch互動的通用請求格式如下面所示。
例如,檢視ElasticSearch工作正常與否的資訊。
與ElasticSearch集×××互時,其輸出資料均為JSON格式,多數情況下,此格式的易讀性較差。cat API會在互動時以類似于Linux上cat指令的格式對結果進行逐行輸出,是以有着較JSON好些的可讀性。調用cat API僅需要向“_cat”資源發起GET請求即可。具體使用方法請查閱官方文檔。
另外,ES叢集的CRUD操作也非常容易進行,朋友們參考官方文檔即可。
五、ES中的資料查詢簡介
需要注意的是,文檔中每個域的值可能會存儲為特定類型,而非字元串類型,是以,_all域的索引方式與特域的索引方式未必完全相同。
文檔中,域的資料存儲時支援“string”、“numbers”、“Booleans”和“dates”幾種類型,不同類型的資料在索引時是略有差別的。在建立文檔時,Elasticsearch會通過檢查域的值來動态為其建立mapping,可通過Mapping API來檢視type的mapping,其通路端點是_mapping。
下面,我們聊一個麻煩一點的問題,ES的精确值、full-text及反向索引。
精确值(Exact values)就是指資料未曾加工過的原始值,而Full-text則用于引用文本中的資料。在查詢中,精确值是很容易進行搜尋的,但full-text則需要判斷文檔在“多大程度上”比對查詢請求,換句話講,即需要評估文檔與給定查詢的相關度(relevant)。是以,所謂的full-text查詢通常是指在給定的文本域内部搜尋指定的關鍵字,但搜尋操作該需要真正了解查詢者的目的。
例如:
(1) 搜尋“UK”應該傳回包含“United Kingdom”的相關文檔;
(2) 搜尋“jump”應該傳回包含“JUMP”、“jumped”、“jumps”、“jumping”甚至是“leap”的文檔;
(3) 搜尋“johnny walker”應該比對包含“Johnnie Walker”的文檔;
為了完成此類full-text域的搜尋,ES必須首先分析文本并将其建構成為反向索引(inverted index),反向索引由各文檔中出現的單詞清單組成,清單中的各單詞不能重複且需要指向其所在的各文檔。是以,為了建立反向索引,需要先将各文檔中域的值切分為獨立的單詞(也稱為term或token),而後将之建立為一個無重複的有序單詞清單。這個過程稱之為“分詞(tokenization)”。
六、Queries and Filters
盡管統一稱之為query DSL,事實上Elasticsearch中存在兩種DSL:查詢DSL(query DSL)和過濾DSL(filter DSL)。查詢子句和過濾子句的自然屬性非常相近,但在使用目的上略有差別。簡單來講,當執行full-text查詢或查詢結果依賴于相關度分值時應該使用查詢DSL,當執行精确值(extac-value)查詢或查詢結果僅有“yes”或“no”兩種結果時應該使用過濾DSL。
Filter DSL計算及過濾速度較快,且适于緩存,是以可有效提升後續查詢請求的執行速度。而query DSL不僅要查找比對的文檔,還需要計算每個檔案的相關度分值,是以為更重量級的查詢,其查詢結果不會被緩存。不過,得益于反向索引,一個僅傳回少量文檔的簡單query或許比一個跨數百萬文檔的filter執行起來并得顯得更慢。
Filter DSL中常見的有term Filter、terms Filter、range Filter、exists and missing Filters和bool Filter。而Query DSL中常見的有match_all、match 、multi_match及bool Query。鑒于時間關系,這裡不再細述,朋友們可參考官方文檔學習。
Queries用于查詢上下文,而filters用于過濾上下文,不過,Elasticsearch的API也支援此二者合并運作。組合查詢可用于合并查詢子句,組合過濾用于合并過濾子句,然而,Elasticsearch的使用習慣中,也常會把filter用于query上進行過濾。不過,很少有機會需要把query用于filter上的。
好了,朋友們,今天的分享就先到這裡吧。感謝大家的時間。這些内容是我用來講課的講義精練出的内容,用于微信的方式分享可能顯得過于啰嗦,請大家将就着看啦。