ElasticSearch安裝及使用
ELK由Elasticsearch、Logstash和Kibana三部分組件組成。
Elasticsearch 是個開源分布式搜索引擎,它的特點有:分布式,零配置,自動發現,索引自動分片,索引副本機制,restful風格接口,多數據源,自動搜索負載等。
Logstash 是一個完全開源的工具,它可以對你的日志進行收集、分析,並將其存儲供以后使用。
kibana 是一個開源和免費的工具,它可以為 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以幫助您匯總、分析和搜索重要數據日志。
本文將用本地安裝模式安裝集群, 如果有條件,請使用雲平台如AWS上的服務。
我的環境是Ubuntu16.04, 並且安裝了Java環境, ElasticSearch是由Java開發的哦。
一.安裝ElasticSearch
1.1 單機運行
從官網下載tar
包:
# 解壓
tar -zxvf elasticsearch-6.1.0.tar.gz
# 新建文件夾
mkdir -p $HOME/escluster
# 移動到我們的新文件夾中
mv elasticsearch-6.1.0 $HOME/escluster/es1
# 嘗試單機運行
cd $HOME/escluster/es1
./bin/elasticsearch -V
./bin/elasticsearch
打開http://127.0.0.1:9200
可以觀察是否成功.
測試:
curl -XPUT 'http://localhost:9200/twitter/doc/1?pretty' -H 'Content-Type: application/json' -d '
{
"user": "kimchy",
"post_date": "2009-11-15T13:12:00",
"message": "Trying out Elasticsearch, so far so good?"
}'
curl -XGET 'http://localhost:9200/twitter/doc/1?pretty=true'
1.2 Docker安裝老版本
Dockerfile
FROM elasticsearch:2.3
RUN plugin install mobz/elasticsearch-head
EXPOSE 9200
EXPOSE 9300
docker build -t es-me .
docker run -d --name es --restart always -v $PWD/data:/usr/share/elasticsearch/data:rw -p 9200:9200 -p 9300:9300 es-me
打開http://127.0.0.1:9200/_plugin/head/
1.2 Docker安裝新版本
Dockerfile:
FROM elasticsearch:5.6
EXPOSE 9200
EXPOSE 9300
docker-compose.yaml
version: '2'
services:
elas:
restart: always
image: elasticsearch:5.5
ports:
- "9200:9200"
- "9300:9300"
volumes:
- "/home/superpika/data:/usr/share/elasticsearch/data:rw"
docker-compose up
現在可以請求127.0.0.1:9200
1.3 集群安裝
簡單使用請參見上面。
ElasticSearch ELK日志分析。
我們要搭建集群, 因為ElasticSearch
是分布式全文搜索引擎。
安裝包下有很多目錄:
目錄 | 作用 |
---|---|
bin | 主要是各種啟動命令 |
config | 主要存放配置文件 |
data | 該節點的索引存放目錄, 可改 |
lib | es依賴的一些依賴包 |
logs | 日志存放目錄, 可改 |
plugins | es強大的插件系統 |
我們在本機裝個兩個節點的集群.
我們修改elasticsearch.yml
來做集群, 相關解釋已經在注釋中, 部分參考ElasticSearch單機雙實例的配置方法.
cd $HOME/escluster/es1
vim config/elasticsearch.yml
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster: 標明了整個集群的名字,只有節點在相同的集群在能互相發現。
#
cluster.name: my-application
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node: 當前節點名稱的標識,各個節點的名稱不能重復, 切記!
#
node.name: node-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
# 新建文件夾, 將數據和日志定位到$HOME/testes中
# sudo mkdir /app/testes
# 將該文件夾賦予執行ES的用戶
# sudo chown superpika testes
# sudo chgrp superpika testes
# 不同節點node的保存路徑應該不一樣
# mkdir /app/testes/node1
# mkdir /app/testes/node2
# 下面必須寫全路徑
path.data: /app/testes/node1/data
#
# Path to log files:
#
path.logs: /app/testes/node1/logs
#
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#
#bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6): 指定為本機IP, 否則可能導致外部無法訪問
#
network.host: 127.0.0.1
#
# Set a custom port for HTTP: 節點間通信端口, 節點在不同機器可以一樣, 但單機模擬集群, 不能一樣
#
http.port: 9200
transport.tcp.port: 9300
# 本地集群必須設置, 切記!!!
# 這個配置限制了單節點上可以開啟的ES存儲實例的個數,我們需要開多個實例,因此需要把這個配置寫到配置文件中,並為這個配置賦值為2或者更高。
node.max_local_storage_nodes: 2
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when new node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
# 由於到了2.x版本之后,ES取消了默認的廣播模式來發現master節點,需要使用該配置來指定發現master節點。這個配置在單機雙實例的配置中需要特別注意下,因為習慣上我們配置時並未指定master節點的tcp端口,如果實例的transport.tcp.port配置為9301,那么實例啟動后會認為discovery.zen.ping.unicast.hosts中指定的主機tcp端口也是9301,可能導致這些節點無法找到master節點。因此在該配置中需要指定master節點提供服務的tcp端口。
#discovery.zen.ping.unicast.hosts: ["host1", "host2"]
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","127.0.0.1:9301"]
# es配置當前集群中最少的主節點數,對於多於兩個節點的集群環境,建議配置大於1。我們的節點目前沒有多於兩個, 所以不設置
# discovery.zen.minimum_master_nodes: 2
#
# Prevent the "split brain" by configuring the majority of nodes (total number of master-eligible nodes / 2 + 1):
#
#discovery.zen.minimum_master_nodes:
#
# For more information, consult the zen discovery module documentation.
#
# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#
#gateway.recover_after_nodes: 3
#
# For more information, consult the gateway module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#
#action.destructive_requires_name: true
我們再拷貝一份:
cp -r $HOME/escluster/es1 $HOME/escluster/es2
將另一份的配置改為:
path.data: /app/testes/node1/data
改為path.data: /app/testes/node2/data
,
path.logs: /app/testes/node1/logs
改為path.logs: /app/testes/node2/logs
,
node.name: node-1
改為node.name: node-2
,
http.port: 9200
改為http.port: 9201
,
transport.tcp.port: 9300
改為transport.tcp.port: 9301
跑起來(跑起來后關掉一個再連, 集群還會保持):
$HOME/escluster/es1/bin/elasticsearch -d
$HOME/escluster/es2/bin/elasticsearch -d
訪問: http://127.0.0.1:9200
和http://127.0.0.1:9201
GET 127.0.0.1:9200/_cluster/health
PS: 也可以不復制整個安裝包成兩份, 只需復制兩份配置, 然后更改配置, 運行:
$HOME/escluster/es1/bin/elasticsearch -Des.path.conf=config/instance1 -d -p /tmp/elasticsearch_1.pid
$HOME/escluster/es1/bin/elasticsearch -Des.path.conf=config/instance2 -d -p /tmp/elasticsearch_2.pid
更多參考: ElasticSearch源碼地址
1.4 腦裂問題
參考: http://blog.csdn.net/cnweike/article/details/39083089
正常情況下,集群中的所有的節點,應該對集群中master的選擇是一致的,這樣獲得的狀態信息也應該是一致的,不一致的狀態信息,說明不同的節點對master節點的選擇出現了異常——也就是所謂的腦裂問題。這樣的腦裂狀態直接讓節點失去了集群的正確狀態,導致集群不能正常工作。
可能導致的原因:
- 網絡:由於是內網通信,網絡通信問題造成某些節點認為master死掉,而另選master的可能性較小;進而檢查Ganglia集群監控,也沒有發現異常的內網流量,故此原因可以排除。
- 節點負載:由於master節點與data節點都是混合在一起的,所以當工作節點的負載較大(確實也較大)時,導致對應的ES實例停止響應,而這台服務器如果正充當着master節點的身份,那么一部分節點就會認為這個master節點失效了,故重新選舉新的節點,這時就出現了腦裂;同時由於data節點上ES進程占用的內存較大,較大規模的內存回收操作也能造成ES進程失去響應。所以,這個原因的可能性應該是最大的。
應對問題的辦法:
1.對應於上面的分析,推測出原因應該是由於節點負載導致了master進程停止響應,繼而導致了部分節點對於master的選擇出現了分歧。為此,一個直觀的解決方案便是將master節點與data節點分離。為此,我們添加了三台服務器進入ES集群,不過它們的角色只是master節點,不擔任存儲和搜索的角色,故它們是相對輕量級的進程。可以通過以下配置來限制其角色:
node.master: true
node.data: false
當然,其它的節點就不能再擔任master了,把上面的配置反過來即可。這樣就做到了將master節點與data節點分離。當然,為了使新加入的節點快速確定master位置,可以將data節點的默認的master發現方式由multicast修改為unicast, 這兩種是ES的默認自動發現(Disovery):
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: ["master1", "master2", "master3"]
2.還有兩個直觀的參數可以減緩腦裂問題的出現:
discovery.zen.ping_timeout(默認值是3秒):默認情況下,一個節點會認為,如果master節點在3秒之內沒有應答,那么這個節點就是死掉了,而增加這個值,會增加節點等待響應的時間,從一定程度上會減少誤判。
discovery.zen.minimum_master_nodes(默認是1):這個參數控制的是,一個節點需要看到的具有master節點資格的最小數量,然后才能在集群中做操作。官方的推薦值是(N/2)+1,其中N是具有master資格的節點的數量(我們的情況是3,因此這個參數設置為2,但對於只有2個節點的情況,設置為2就有些問題了,一個節點DOWN掉后,你肯定連不上2台服務器了,這點需要注意)
二.安裝Kibana
從官網下載tar
包.
解壓並修改配置
tar -zxvf kibana-6.1.0-linux-x86_64.tar.gz
cd kibana-6.1.0-linux-x86_64
vim config/kibana.yml
elasticsearch.url: "http://127.0.0.1:9200"
運行:
bin/kibana
# 后台運行
nohup bin/kibana &
打開: http://127.0.0.1:5601
即可.
三.使用Logstash
Logstash是一個數據分析軟件,主要目的是分析log日志。整一套軟件可以當作一個MVC模型,logstash是controller層,Elasticsearch是一個model層,kibana是view層。
首先將數據傳給logstash,它將數據進行過濾和格式化(轉成JSON格式),然后傳給Elasticsearch進行存儲、建搜索的索引,kibana提供前端的頁面再進行搜索和圖表可視化,它是調用Elasticsearch的接口返回的數據進行可視化。logstash和Elasticsearch是用Java寫的,kibana使用node.js框架。
這里是全文重點.
3.1 安裝
從官網下載tar
包.
tar -zxvf logstash-6.1.0.tar.gz
cd logstash-6.1.0
3.2 運行
定義一個簡單的示例日志收集處理配置logstash.conf
:
input { stdin { } }
output {
elasticsearch { hosts => ["127.0.0.1:9200"] }
stdout { codec => rubydebug }
}
這里input
從標准輸入stdin
接收日志, output
將日志輸出到elasticsearch
, stdout.codecs是基於數據流的過濾器,它可以作為input,output的一部分配置。Codecs可以幫助你輕松的分割發送過來已經被序列化的數據。流行的codecs包括 json,msgpack,plain(text)。
開始跑:
bin/logstash -f logstash.conf
> 隨便打
打開kibana
來分析: http://127.0.0.1:5601/app/kibana#/management/kibana/index?_g=()
接着可以打開Discover
進行日志查看:
也可以進Visualize
進行Create a visualization
操作:
四. 筆記
Elasticsearch是面向文檔(document oriented)的,這意味着它可以存儲整個對象或文檔(document)。然而它不僅僅是存儲,還會索引(index)每個文檔的內容使之可以被搜索。在Elasticsearch中,你可以對文檔(而非成行成列的數據)進行索引、搜索、排序、過濾。這種理解數據的方式與以往完全不同,這也是Elasticsearch能夠執行復雜的全文搜索的原因之一。
在Elasticsearch中,文檔歸屬於一種類型(type),而這些類型存在於索引(index)中,我們可以畫一些簡單的對比圖來類比傳統關系型數據庫:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch集群可以包含多個索引(indices)(數據庫),每一個索引可以包含多個類型(types)(表),每一個類型包含多個文檔(documents)(行),然后每個文檔包含多個字段(Fields)(列)。
為了創建員工目錄,我們將進行如下操作:
為每個員工的文檔(document)建立索引,每個文檔包含了相應員工的所有信息。
每個文檔的類型為employee。
employee類型歸屬於索引megacorp。
megacorp索引存儲在Elasticsearch集群中。
實際上這些都是很容易的(盡管看起來有許多步驟)。我們能通過一個命令執行完成的操作(參見ES權威指南):
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
GET /megacorp/employee/1
HEAD /megacorp/employee/1
GET /megacorp/employee/_search
GET /_cluster/health
在Elasticsearch中,每一個字段的數據都是默認被索引的。也就是說,每個字段專門有一個反向索引用於快速檢索。而且,與其它數據庫不同,它可以在同一個查詢中利用所有的這些反向索引,以驚人的速度返回結果。
文檔在Elasticsearch中是不可變的——我們不能修改他們。
在內部,Elasticsearch已經標記舊文檔為刪除並添加了一個完整的新文檔。舊版本文檔不會立即消失,但你也不能去訪問它。Elasticsearch會在你繼續索引更多數據時清理被刪除的文檔。
update API。這個API似乎允許你修改文檔的局部,但事實上Elasticsearch遵循與之前所說完全相同的過程,這個過程如下:
- 從舊文檔中檢索JSON
- 修改它
- 刪除舊文檔
- 索引新文檔
當使用 index API更新文檔的時候,我們讀取原始文檔,做修改,然后將整個文檔(wholedocument)一次性重新索引。最近的索引請求會生效——Elasticsearch中只存儲最后被索引的任何文檔。如果其他人同時也修改了這個文檔,他們的修改將會丟失。
比如:
一天,老板決定做一個促銷。瞬間,我們每秒就銷售了幾個商品。想象兩個同時運行的web進程,兩者同時處理一件商品的訂單.
web_1讓stock_count 失效是因為web_2沒有察覺到stock_count 的拷貝已經過期(譯者注: web_1取數據,減一后更新了stock_count。可惜在web_1更新stock_count前它就拿到了數據,這個數據已經是過期的了,當web_2再回來更新stock_count時這個數字就是錯的。這樣就會造成看似賣了一件東西,其實是賣了兩件,這個應該屬於幻讀。)。結果是我們認為自己確實還有更多的商品,最終顧客會因為銷售給他們沒有的東西而失望。
變化越是頻繁,或讀取和更新間的時間越長,越容易丟失我們的更改。在數據庫中,有兩種通用的方法確保在並發更新時修改不丟失:
悲觀並發控制(Pessimistic concurrency control)
這在關系型數據庫中被廣泛的使用,假設沖突的更改經常發生,為了解決沖突我們把訪問區塊化。典型的例子是在讀一行數據前鎖定這行,然后確保只有加鎖的那個線程可以修改這行數據。
樂觀並發控制(Optimistic concurrency control):
被Elasticsearch使用,假設沖突不經常發生,也不區塊化訪問,然而,如果在讀寫過程中數據發生了變化,更新操作將失敗。這時候由程序決定在失敗后如何解決沖突。實際情況中,可以重新嘗試更新,刷新數據(重新讀取)或者直接反饋給用戶。
Elasticsearch是分布式的。當文檔被創建、更新或刪除,文檔的新版本會被復制到集群的其它節點。Elasticsearch即是同步的又是異步的,意思是這些復制請求都是平行發送的,並無序(out of sequence)的到達目的地。這就需要一種方法確保老版本的文檔永遠不會覆蓋新的版本。上文我們提到index/get/delete 請求時,我們指出每個文檔都有一個version號碼,這個號碼在文檔被改變時加一。Elasticsearch使用這個 _version保證所有修改都被正確排序。當一個舊版本出現在新版本之后,它會被簡單的忽略。
409沖突:
PUT /website/blog/1?version=1
更多查看https://www.gitbook.com/book/looly/elasticsearch-the-definitive-guide-cn