ELK
Elastic Stack(ELk) 相關產品
- Elasticsearch 一個基於JSON的分佈式搜索和分析引擎
- Kibana 可視化、一個可擴展的用戶界面
- Beats 採集數據工具
- Logstash 第三方數據庫中提取數據
概念
集羣
節點
類型type
文檔doc
索引index
分片shard
副本replica
index/type/doc
類比
ES:indices --> types --> documents --> fields
DB:databases --> tables --> rows --> columns
documents爲JSON形式
分片shard
需要配置一個主分片數量,並永不再改變
默認設置5個主分片
ES 的每個分片(shard)都是lucene的一個index,而lucene的一個index只能存儲20億個文檔,所以一個分片也只能最多存儲20億個文檔。
分片選擇公式
shard = hash(routing) % number_of_primary_shards
routing 默認爲文檔id
分片數過多會導致:
1、 會導致打開比較多的文件
2、 分片是存儲在不同機器上的,分片數越多,機器之間的交互也就越多;
分片數太少導致:
單個分片索引過大,降低整體的檢索速率
將單個分片存儲存儲索引數據的大小控制在20G左右;絕對不要超過50G , 否則性能很差
最終分片數量 = 數據總量/20G
副本replica
主分片不可用時,集羣選擇副本提升爲主分片。
ES禁止同一分片的主分片,副本在同一個節點上。
比如兩個節點其中 node1 有某個索引的分片1、2、3和副本分片4、5,node2 有該索引的分片4、5和副本分片1、2、3。
replication 配置 默認爲sync,即修改完成後,同步到其他節點後,才返回結果到客戶端。
原理
trie字典樹: 根據前綴快速找到單詞。
倒排索引: 將doc分詞後倒過來建立索引 詞value -> key(docId) -> doc
索引緩存在內存中
安裝Elastic Search
啓動腳本需要java8, 但101.3 java7?
下載地址 elasticsearch.org/download
elasticsearch/bin/elasticsearch 腳本運行
提供兩個端口進行訪問
- 9300 java API
- 9200 http RESTful API
原本已經裝好/app/ebn,瀏覽器10.78.101.3:9200 訪問後可以看到
即運行成功, 節點版本爲5.6.4。 開發時要選擇匹配的版本的客戶端進行請求。
Kibana
kibana 默認端口5601
kibana 可使用devTools
可使用以下格式測試請求
GET /megacorp/employee/_search
todo:
機器上默認端口 是ebn模塊在用es/kibana。 原來的ebn的功能還用嗎?
kibana 週期性關閉,需要手動打開,未知原因。
JAVA 客戶端
ES Java 客戶端目前主要提供兩種方式,分別是 Java API 和 Java REST Client:
Java API:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/index.html,其使用的核心傳輸對象是 TransportClient。但是 Elastic 官方已經計劃在 Elasticsearch 7.0 中廢棄 TransportClient,並在 8.0 中完全移除它,並由 Java High Level REST Client 代替。官網聲明如下:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/client.html
Java REST Client:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/index.html,Java REST Client 又分爲兩種,Java Low Level REST Client 和 Java High Level REST Client。目前官方推薦使用 Java High Level REST Client。
目前有flummi、Jest、還有國人開發的bboss。非官方封裝的client。
但更推薦使用官方支持的 Java High Level REST Client、或者spring-data-elasticsearch。
spring-data-elasticsearch 複雜的mapping可以自動完成,無需額外創建mapping。但版本要與spring版本匹配.
所以使用Java High Level REST Client 更爲合適。
基本操作
通過HTTP方法GET來檢索文檔,同樣的,我們可以使用DELETE方法刪除文檔,使用HEAD方法檢查某文檔是否存在。如果想更新已存在的文檔,我們只需再PUT一次。
POST /index/type/xxx 創建
DELETE /index/type/xxx 刪除
PUT /index/type/xxx 更新或創建
GET /index/type/xxx 查看
相應的JAVA中提供的API包含了檢查存在exist,增index/create、刪 delete、改index/update、查search。並提供帶Async後綴的異步API。批量操作,查詢ES基礎信息等API
插入index/create
第一步判斷是確定插入的文檔是否指定id,如果沒有指定id,系統會默認生成一個唯一id。這種情況下,不管index還是create會直接add文檔。如果用戶指定了id,那麼就會走底層Lucene update,成本比Lucene add要高。
第二步判斷,是通過id來get文檔版本號檢查是否衝突,但無論是index還是create都不會get整個doc的全部內容,只是get出了版號。這也從一定程度上減少了系統開銷。
index時會檢查_version。如果插入時沒有指定_version,那對於已有的doc,_version會遞增,並對文檔覆蓋。插入時如果指定_version,如果與已有的文檔_version不相等,則插入失敗,如果相等則覆蓋,_version遞增。
create使用內部版本控制,傳入_version會衝突
更新update
底層Lucene update 實際上是先刪除後創建,性能也比 Lucene add 差。
Es update都會調用 InternalEngine中的get方法,來獲取整個文檔信息,從而實現針對特定字段進行修改,這也就導致了每次更新要獲取一遍原始文檔,性能上會有很大影響。所以根據使用場景,有時候使用index會比update好很多。
搜索search
簡單搜索
GET /megacorp/employee/_search
不加條件,默認返回前10條
{
"took": 6,
"timed_out": false,
"_shards": { ... },
"hits": {
"total": 3,
"max_score": 1,
"hits": [
{
"_index": "megacorp",
"_type": "employee",
"_id": "3",
"_score": 1,
"_source": {
"first_name": "Douglas",
"last_name": "Fir",
"age": 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}
},
{
...
},
{
...
}
]
}
}
查詢語句可以附帶參數 q=fieldName:xxx
GET /megacorp/employee/_search?q=fieldName:xxx
DSL 語句查詢
term:查詢某個字段裏含有某個關鍵詞的文檔, 只能查單個詞
terms:查詢某個字段裏含有多個關鍵詞的文檔, 多個詞 或關係
match: 知道分詞器的存在,會對field進行分詞操作,然後再查詢
match_phrase: 短語搜索,要求所有的分詞同時出現在文檔中,位置緊鄰。
…
可以查看更多查詢
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
GET /megacorp/employee/_search
{
"query" : {
"filtered" : {
"filter" : {
"range" : {
"age" : { "gt" : 30 } <1>
}
},
"query" : {
"match" : {
"last_name" : "smith" <2>
}
}
}
}
}
全文搜索
會同時返回 含相關字段的結果 和 相關性評分
GET /megacorp/employee/_search
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
{
...
"hits": {
"total": 2,
"max_score": 0.16273327,
"hits": [
{
...
"_score": 0.16273327, <1>
"_source": {
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
},
{
...
"_score": 0.016878016, <2>
"_source": {
"first_name": "Jane",
"last_name": "Smith",
"age": 32,
"about": "I like to collect rock albums",
"interests": [ "music" ]
}
}
]
}
}
聚合
分爲以下幾種:
指標聚合 Metrics Aggregation: 需要計算指標的,如平均值、最大最小值
桶聚合 Bucket Aggregation: 給定邊界,數據落入不同分類的桶中
管道聚合(v5.6是實驗性) Pineline Aggregation:將其他聚合結果基礎上進行聚合 比如 每月 sum(sell)之後求 max
矩陣聚合(實驗性)
桶聚合的結果,每個桶代表一組文檔,因此桶聚合可以嵌套對裏面的數據進行聚合
除了矩陣聚合,其他幾種都可以加上腳本簡單計算(相當於自定義指標)
5.x後對排序,聚合這些操作用單獨的數據結構(fielddata)緩存到內存裏了,需要單獨開啓,官方解釋在此fielddata
text類型的字段是要分詞的, 默認不能作爲field字段作爲聚合用。Fielddata is disabled on text fields by default
java RestHighLevelClient 請求示例
查詢請求模版
//構造查詢請求
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.matchAllQuery());
searchRequest.source(searchSourceBuilder);
//查詢
SearchResponse resp = client.search(searchRequest);
// 插入等有類似IndexRequest 不再列舉。
聚合請求
請求結果
ES SQL
以上提到的,是dsl語句查詢。
另有兼容sql的查詢方法,但目前與目前測試機器上的版本不匹配。
5.x需要安裝相關插件
V6.3開始官方提供sql查詢,但有取消的可能。
SQL 特性是 xpack 的免費功能,語法爲直接把sql語句從query傳入
POST /_xpack/sql?format=txt
{
"query": "SELECT * FROM twitter"
}
v7.5 導入默認數據,請求url 有所變更
POST _sql?format=txt
{
"query":"SELECT COUNT(*), MONTH_OF_YEAR(order_date) AS month_of_year, AVG(products.min_price) AS avg_price FROM kibana_sample_data_ecommerce GROUP BY month_of_year"
}
如何處理join
這篇文章說得比較詳細了
https://blog.csdn.net/laoyang360/article/details/88784748