1. 程式人生 > >SpringCloud整合ElasticSearch,Logstash,Kibana,ELK,Kafka分散式日誌系統(一)

SpringCloud整合ElasticSearch,Logstash,Kibana,ELK,Kafka分散式日誌系統(一)

ELK

ElasticSearch介紹

在 《Elasticsearch : The Definitive Guide》裡,這樣介紹Elasticsearch,總的來說,Elasticsearch 是一個分散式的搜尋和分析引擎,可以用於全文檢索、結構化檢索和分析,並能將這三者結合起來。Elasticsearch 基於 Lucene 開發,現在是使用最廣的開源搜尋引擎之一,Wikipedia、Stack Overflow、GitHub 等都基於 Elasticsearch 來構建他們的搜尋引擎。

先介紹下 Elasticsearch 裡的基本概念,下圖是 Elasticsearch 外掛 head 的一個截圖。

Elasticsearch 外掛head截圖

  • node:即一個 Elasticsearch 的執行例項,使用多播或單播方式發現 cluster 並加入。
  • cluster:包含一個或多個擁有相同叢集名稱的 node,其中包含一個master node。
  • index:類比關係型資料庫裡的DB,是一個邏輯名稱空間。
  • alias:可以給 index 新增零個或多個alias,通過 alias 使用index 和根據index name 訪問index一樣,但是,alias給我們提供了一種切換index的能力,比如重建了index,取名customer_online_v2,這時,有了alias,我要訪問新 index,只需要把 alias 新增到新 index 即可,並把alias從舊的 index 刪除。不用修改程式碼。
  • type:類比關係資料庫裡的Table。其中,一個index可以定義多個type,但一般使用習慣僅配一個type。
  • mapping:類比關係型資料庫中的 schema 概念,mapping 定義了 index 中的 type。mapping 可以顯示的定義,也可以在 document 被索引時自動生成,如果有新的 field,Elasticsearch 會自動推測出 field 的type並加到mapping中。
  • document:類比關係資料庫裡的一行記錄(record),document 是 Elasticsearch 裡的一個 JSON 物件,包括零個或多個field。
  • field:類比關係資料庫裡的field,每個field 都有自己的欄位型別。
  • shard:是一個Lucene 例項。Elasticsearch 基於 Lucene,shard 是一個 Lucene 例項,被 Elasticsearch 自動管理。之前提到,index 是一個邏輯名稱空間,shard 是具體的物理概念,建索引、查詢等都是具體的shard在工作。shard 包括primary shard 和 replica shard,寫資料時,先寫到primary shard,然後,同步到replica shard,查詢時,primary 和 replica 充當相同的作用。replica shard 可以有多份,也可以沒有,replica shard的存在有兩個作用,一是容災,如果primary shard 掛了,資料也不會丟失,叢集仍然能正常工作;二是提高效能,因為replica 和 primary shard 都能處理查詢。另外,如上圖右側紅框所示,shard數和replica數都可以設定,但是,shard 數只能在建立index 時設定,後期不能更改,但是,replica 數可以隨時更改。但是,由於 Elasticsearch 很友好的封裝了這部分,在使用Elasticsearch 的過程中,我們一般僅需要關注 index 即可,不需關注shard。

綜上所述,shard、node、cluster 在物理上構成了 Elasticsearch 叢集,field、type、index 在邏輯上構成一個index的基本概念,在使用 Elasticsearch 過程中,我們一般關注到邏輯概念就好,就像我們在使用MySQL 時,我們一般就關注DB Name、Table和schema即可,而不會關注DBA維護了幾個MySQL例項、master 和 slave 等怎麼部署的一樣。

下表用Elasticsearch 和 關係資料庫做了類比:

  • index => databases
  • type => table
  • field => field
  • document => record
  • mapping => schema

最後,來從 Elasticsearch 中取出一條資料(document)看看:

ES result

由index、type和id三者唯一確定一個document,_source 欄位中是具體的document 值,是一個JSON 物件,有5個field組成。

1. Elasticsearch 基本使用

下面介紹下 Elasticsearch 的基本使用,這裡僅介紹 Elasticsearch 能做什麼,而不詳細介紹語法。

1.1 基礎操作

  • index:寫 document 到 Elasticsearch 中,如果不存在,就建立,如果存在,就用新的取代舊的。
  • create:寫 document 到 Elasticsearch 中,與 index 不同的是,如果存在,就丟擲異常DocumentAlreadyExistException
  • get:根據ID取出document。
  • update:如果是更新整個 document,可用index 操作。如果是部分更新,用update操作。在Elasticsearch中,更新document時,是把舊資料取出來,然後改寫要更新的部分,刪除舊document,建立新document,而不是在原document上做修改。
  • delete:刪除document。Elasticsearch 會標記刪除document,然後,在Lucene 底層進行merge時,會刪除標記刪除的document。

1.2 Filter 與 Query

Elasticsearch 使用 domain-specific language(DSL)進行查詢,DSL 使用 JSON 進行表示。

DSL 由一些子查詢組成,這些子查詢可應用於兩類查詢,分別是filter 和 query。

filter 正如其字面意思“過濾”所說的,是起過濾的作用,任何一個document 對 filter 來說,就是match 與否的問題,是個二值問題,0和1,沒有scoring的過程。

使用query的時候,是表示match 程度問題有scroing 過程。

另外,Filter 和 Query 還有效能上的差異,Elasticsearch 底層對Filter做了很多優化,會對過濾結果進行快取;同時,Filter 沒有相關性計算過程,所以,Filter 比 Query 快。

所以,官網推薦,作為一條比較通用的規則,僅在全文檢索時使用Query,其它時候都用Filter。但是,根據我們的使用情況來看,在過濾條件不是很強的情況下,快取可能會佔用較多記憶體,如果這些資料不是頻繁使用,用空間換時間不一定划算。

1.3 一些重要的查詢

在Elasticsearch 中,有幾類最重要的查詢子句,掌握了就可以覆蓋日常90%以上的需求。

1.3.1 match_all

{"match_all":{}}

表示取出所有documents,在與filter結合使用時,會經常使用match_all。

1.3.2 match

一般在全文檢索時使用,首先利用analyzer 對具體查詢字串進行分析,然後進行查詢;如果是在數值型欄位、日期型別欄位、布林欄位或not_analyzed 的字串上進行查詢時,不對查詢字串進行分析,表示精確匹配,兩個簡單的例子如:

{ "match": { "tweet": "About Search" }}
{ "match": { "age":    26           }}

1.3.3 term

term 用於精確查詢,可用於數值、date、boolean值或not_analyzed string,當使用term時,不會對查詢字串進行分析,進行的是精確查詢。

{ "term": { "date":   "2014-09-01" }}

1.3.4 terms

terms 和 term 類似,但是,terms 裡可以指定多個值,只要doc滿足terms 裡的任意值,就是滿足查詢條件的。與term 相同,terms 也是用於精確查詢。

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}

注意,terms 表示的是contains 關係,而不是 equals關係。

1.3.5 range

類比資料庫查詢的範圍查詢,舉個簡單的例子:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}

操作符可以是:

  • gt:大於
  • gte:大於等於
  • lt:小於
  • lte:小於等於

1.3.6 exists 和 missing

exists 用於查詢欄位含有一個或多個值的document,而missing用於查詢某欄位不存在值的document,可類比關係資料庫裡的 is not null (exists) 和 is null (missing).

{
    "exists":   {
        "field":    "title"
    }
}

1.3.7 bool

前面講的都是些最原子的查詢子句,那麼,怎麼實現複合查詢呢?Elasticsearch 使用bool 子句來將各種子查詢關聯起來,組成布林表示式,bool 子句可以隨意組合、巢狀。

bool子句主要包括:

  1. must:表示必須匹配。
  2. must_not:表示一定不能匹配。
  3. should:表示可以匹配,類似於布林運算裡的”或”。如果bool 子句裡,沒有must子句,那麼,should子句裡至少匹配一個,如果有must子句,那麼,should子句至少匹配零個。可以使用minimum_should_match 來對最小匹配數進行設定。
{
    "bool" : {
        "must" : {
            "term" : { "user" : "kimchy" }
        },
        "must_not" : {
            "range" : {
                "age" : { "from" : 10, "to" : 20 }
            }
        },
        "should" : [
            {
                "term" : { "tag" : "wow" }
            },
            {
                "term" : { "tag" : "elasticsearch" }
            }
        ],
        "minimum_should_match" : 1,
        "boost" : 1.0
    }
}

1.4 聚合功能

前面說的都是 Elasticsearch 當做搜尋引擎使用,Elasticsearch 還可以作為分析引擎使用。

和 MySQL 等關係資料庫類似,Elasticsearch 有聚合操作,而且,可作用於大量資料,提供實時的分析結果,速度快;同時,聚合操作可以與搜尋結合使用,例如將聚合作用於搜尋結果等。總之,Elasticsearch的聚合功能十分強大,有很多公司利用 Elasticsearch 來做分析,其中,廣泛使用的 ELK(Elasticsearch + Logstash + Kibana),Kibana的資料顯示和分析功能就是基於 Elasticsearch 的聚合功能做的。

1.5 Geolocation

Elasticsearch 還提供了基於地理位置的搜尋,而且能將地理位置與全文檢索、結構化搜尋、分析等結合起來使用,比如查詢距離某點一定範圍內的符合搜尋條件的地點、計算兩點的距離、判斷兩個形狀是否相交或包含等。

2. Elasticsearch 使用時注意的幾個問題

深度分頁問題:Elasticsearch 作為一個分散式搜尋與分析引擎,深度分頁問題會帶來嚴重的問題,給CPU、記憶體、IO、網路帶來巨大壓力,所以,在Elasticsearch 不建議使用深度分頁,如果要遍歷資料,可以採用 SCROLL的方式,可參考我另一篇部落格

排序問題:根據某field排序時,Elasticsearch 會將這個 field 的所有值給載入到記憶體,然後,這部分資料會常駐記憶體,如果資料量大或排序欄位多,就會給系統帶來巨大壓力,所以,在使用 field 進行排序時,要慎重。不過,在Elasticsearch 2.X版本,開始使用 doc value 來優化這部分。

terms 問題: terms 裡可以傳多個值,但是,量不能太多,搜尋引擎的基本資料結構是倒排索引,terms 裡傳多個值,原理上來說是查很多的倒排索引,量大了也會給系統帶來很大壓力。

安裝ElasticSearch(Linux Centos)

下載、解壓安裝包

目前最新版本為6.4.0

下載
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.4.0.tar.gz
如下載完整可以忽略完整性校驗,即不用下載下面的sha512檔案
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.4.0.tar.gz.sha512
如下載完整可以忽略完整性校驗,即不需要執行檔案下載完整性校驗
shasum -a 512 -c elasticsearch-6.4.0.tar.gz.sha512 
解壓
tar -xzf elasticsearch-6.4.0.tar.gz

執行安裝包

./bin/elasticsearch
後臺不掛斷執行,並輸出日誌到elasticsearch.out
nohup ./bin/elasticsearch >elasticsearch.out &

解決啟動問題

此時會有出錯提示

uncaught exception in thread [main] **** can not run elasticsearch as root

意思即不能使用root使用者執行elasticsearch

新增使用者 xxx為你要新增的使用者名稱
useradd xxx
給xxx使用者設定密碼
passwd xxx
輸入密碼
再次輸入密碼
給xxx使用者許可權,/ELK/elasticsearch-6.4.0是elasticsearch解壓根目錄
chown -R xxx /ELK/elasticsearch-6.4.0
切換使用者為xxx
su xxx

再執行
./bin/elasticsearch
或者後臺執行
nohup ./bin/elasticsearch >elasticsearch.out &
即可成功

解決啟動時max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]問題

#切換到root使用者修改
vim /etc/security/limits.conf
 
# 在最後面追加下面內容
xxx hard nofile 65536
xxx soft nofile 65536
xxx  是啟動ElasticSearch的使用者

重新啟動不再有上述錯誤提示,搞定OK

檢查是否安裝成功

tail elasticsearch.out

檢視log是否成功啟動

curl http://localhost:9200 

訪問本地9200地址看是否可以成功訪問

如果輸出下圖,則表示成功

{
  "name" : "F6mmx8s",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "j5O0hDX9QlyAryj95cvoFQ",
  "version" : {
    "number" : "6.4.0",
    "build_flavor" : "default",
    "build_type" : "tar",
    "build_hash" : "595516e",
    "build_date" : "2018-08-17T23:18:47.308994Z",
    "build_snapshot" : false,
    "lucene_version" : "7.4.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

允許外部9200訪問

可以訪問127.0.0.1:9200,但不能訪問 公網IP:9200 
後面ip就是127.0.0.1的區域網ip,如何解決?

修改配置檔案 config/elasticsearch.yml

network.host: 0.0.0.0