ES調研

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 更爲合適。

另附5.6的文檔
API
請求示例

基本操作

通過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 不再列舉。

聚合請求
agg
請求結果
aggResult

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章