ElasticSearch學習之基本概念及單機/集群部署


一、ElasticSearch簡介

  1、ElasticSearch簡介

  Elasticsearch是一個基於Apache Lucene(TM)的開源搜索引擎。無論在開源還是專有領域,Lucene可以被認為是迄今為止最先進、性能最好的、功能最全的搜索引擎庫。 但是,Lucene只是一個庫。想要使用它,你必須使用Java來作為開發語言並將其直接集成到你的應用中,更糟糕的是,Lucene非常復雜,你需要深入了解檢索的相關知識來理解它是如何工作的。 Elasticsearch也使用Java開發並使用Lucene作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的 **RESTful API** 來隱藏Lucene的復雜性,從而讓全文搜索變得簡單。

  2、同類產品比較solr

  Solr 是Apache下的一個頂級開源項目,采用Java開發,它是基於Lucene的全文搜索服務器。Solr提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴展,並對索引、搜索性能進行了優化 。並自帶了圖形管理界面。

  • 數據相對少的請求下Solr的檢索效率更高
  • 建立索引時,Solr會產生阻塞IO,查詢性能較差,ElasticSearch有優勢
  • 數據量大時,Solr的搜索效率變低,而ElasticSearch沒有明顯變化
  • 安裝使用方面ElasticSearch更為簡單

  總結:

  • solr查詢快,但更新索引時慢(即插入刪除慢),用於電商等查詢多的應用,比如商品搜索 。
  • ES建立索引快(即查詢慢),即實時性查詢快,適用用於數據頻繁更新的應用,比如facebook新浪等搜索。
  • Solr 是傳統搜索應用的有力解決方案,但 Elasticsearch 更適用於新興的實時搜索應用。
  • ES沒有Solr成熟,學習成本相對較高。

二、ElasticSearch安裝和可視化界面Elasticsearch-Head

  1、ElasticSearch安裝

  下載Es安裝包:

ElasticSearch的官方地址:https://www.elastic.co/guide/en/elasticsearch/reference/master/index.html

  安裝(如Mac OS):

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.3-darwin-x86_64.tar.gz
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.9.3-darwin-x86_64.tar.gz.sha512
shasum -a 512 -c elasticsearch-7.9.3-darwin-x86_64.tar.gz.sha512 
tar -xzf elasticsearch-7.9.3-darwin-x86_64.tar.gz
cd elasticsearch-7.9.3/ 

  啟動命令如下(-d以進程的形式啟動elasticsearch,-p表示進程號記錄到pid文件中):

./bin/elasticsearch -d -p pid

  2、ES圖形化管理界面安裝

  2.1、安裝elasticsearch-head和Node.js

  注意elasticsearch和elasticsearch-head版本是對應的,否則會出現head無法支持elasticsearch的顯示。

  安裝完成 在cmd窗口執行node -v查看node.js的版本號 檢查是否安裝成功。

  2.2、安裝grunt

  通過node.js的包管理器npm安裝grunt為全局,grunt是基於Node.js的項目構建工具

npm install -g grunt-cli

  2.3、執行 npm install

  注:不執行該命寧 使用grunt server命令會報錯。

npm install

  2.4、啟動elasticsearch-head

  打開命寧窗口在elasticsearch-head解壓目錄下執行 grunt server 啟動服務:

HoudeMacBook-Pro:elasticsearch-head houjing$ grunt server
Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100

  然后訪問 http://localhost:9100 (elasticsearch-head服務端口)。

  2.5、配置ElasticSearch跨域訪問

  修改 config/elasticsearch.yml 文件

http.cors.enabled: true
http.cors.allow-origin: "*"

  注:需要重啟ES服務。

  2.6、head訪問

  在head頁面輸入鏈接的ElasticSearch地址,點擊連接按鈕。

  

三、 ElasticSearch的相關概念

  1、概述

  Elasticsearch是面向文檔(document oriented)的,這意味着它可以存儲整個對象或文檔(ducoment)。然而它不僅僅是存儲,還會索引(index)每個文檔的內容使之能搜索。在Elasticsearch中,你可以對文檔(而非成行成列的數據 )進行索引、排序、過濾。Elasticsearch比傳統關系型數據庫如下。

關系型數據庫  -> Databases -> Tables -> Rows -> Colums

ElasticSearch -> Indices -> Types(7版本已經沒有此概念,相當於一個Database只有一張table) ->Documents -> Fields

  2、ElasticSearch的核心概念

  2.1、索引 index

  一個索引就是有相似特征的文檔集合,比如用戶數據索引、訂單數據索引、商品數據索引。

  一個索引由一個全為小寫字母的名字標識,我們在對應這個索引文檔中進行索引、搜索、更新和刪除的時候,都要使用到這個名字。在一個群集中可以定義任意多個索引。

  2.2、類型type

  在一個索引中,你可以定義一個或多個類型,一個類型是你的索引的一個邏輯上的分類,其語義完全由你來定。通常,會為具有一組共同字段的文檔定義一個類型,比如說,我們訂單數據索引中我們把訂單信息作為一個類型,訂單相關的物流信息做為一個類型。但在6.0開始建議index只包含一個type,在7.0之后開始去除(也並不是完全去除,而是默認為了_doc)。

  2.3、字段field

  相當於是數據表的字段,對文檔根據不同的屬性進行的分類標識。

  2.4、映射 mapping (表結構)

  mapping是處理數據的方式和規則方面做一些限制,如某個字段的數據類型、默認值、分析器、是否被索引等等,這些都是映射里面可以設置的,其他的就是處理es里面的數據的一些使用規則設置也叫做映射,按着最優規則處理數據對性能提高很大,因此才需要建立映射,並且需要思考如何建立隱射才能對性能更好。

  3.2.5、文檔 document

  一個文檔是一個可被索引的基礎單元。文檔以JSON格式來表示,而JSON是一個到處存在的互聯網數據交互格式。

  在一個index/type里面,你可以存儲任意多的文檔。

  2.6、ElasticSearch版本問題說明

  Elasticsearch 官網提出的近期版本對 type 概念的演變情況如下:

  • 在 5.X 版本中,一個 index 下可以創建多個 type;
  • 在 6.X 版本中,一個 index 下只能存在一個 type;
  • 在 7.X 版本中,直接去除了 type的概念,就是說 index 不再會有 type。

  去除type的原因 :

  因為 Elasticsearch 設計初期,是直接查考了關系型數據庫的設計模式,存在了 type(數據表)的概念。但是,其搜索引擎是基於 Lucene的,這種 “基因”決定了 type 是多余的。Lucene 的全文檢索功能之所以快,是因為倒序索引的存在。而這種倒序索引的生成是基於 index 的,而並非 type。

四、 ElasticSearch基本操作

  基本操作在學習過程中可以使用單測工具進行,可以使用postman、jmeter,因為是使用http請求操作Es, 必須對RESTful 風格有所了解,所以在學習基本操作前,對RESTful 知識進行補充:

  RESTful 在兩方面做了相應規范:

  • 服務數據交互格式使用json、xml。
  • 采用HTTP協議規定的GET、POST、PUT、DELETE動作處理資源的增刪該查操作。

    

  1、ElasticSearch語法

  mapping字段詳解:

      

  type 可選類型:

    

  2、通過HTTP請求創建

  2.1、僅創建索引

  請求方式選擇Put;請求鏈接如:http://127.0.0.1:9200/news 。結果:

{
    "acknowledged": true,
    "shards_acknowledged": true,
    "index": "news"
}

  2.2、創建索引的同時創建mapping 以及分片復制參數

  傳入body參數執行:

{
    "settings": {
        "number_of_shards": 5,
        "number_of_replicas": 1,
        "refresh_interval": "30s",
        "index.analysis.analyzer.default.type": "ik_max_word" //分詞器,未指定默認elastic自帶的分詞器,對中文支持差。
    },
    "mappings": {
        "properties": {
            "newsid": {
                "type": "text",
                "store": false,
                "index": true,
                "analyzer": "standard"
            },
            "newsname": {
                "type": "text",
                "store": false,
                "index": true
            },
            "newsdesc": {
                "type": "text",
                "store": false,
                "index": true
            }
        }
    }
}

  2.3、刪除索引庫

  請求方式選擇Delete,請求鏈接如:http://127.0.0.1:9200/news 刪除news索引:

{
    "acknowledged": true
}

  2.4、向索引庫中添加文檔

  請求方式選 POST,單條插入請求url:

  • http://127.0.0.1:9200/news/_doc/1 (索引/"**_doc**"/文檔id)
  • http://127.0.0.1:9200/news/_doc

  文檔id為Es中的文檔主鍵id,不指定的情況下Es會給我們生成一個唯一的隨機字符串,如 BU7pG24Bm2YrPBUaN0wD

{
    "newsid":"1234",
    "newsname":"你猜不到的名字",
    "newsdesc":"這是一條新聞描述"
}

  如結果:

{
    "_index": "news",
    "_type": "_doc",
    "_id": "1",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 2,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}

  批量添加,請求url: http://127.0.0.1:9200/news/_bulk

{ "index":{} }
{ "newsid":"1234656","newsname":"miumiu" ,"newsdesc":"親承5為自己生下5個孩子 此前12個" }
{ "index":{} }
{ "newsid":"1234657","newsname":"乒聯" ,"newsdesc":"國際乒聯奧地利公開賽正賽展開" }
{ "index":{"_id":"iikdjsd"} }
{ "newsid":"1234658","newsname":"紛紛兩連敗" ,"newsdesc":"兩連敗+二當家傷停再遭困境 考驗歐文.." }
{ "index":{"_id":"iik3325"} }
{ "newsid":"1234659","newsname":"紛紛返回" ,"newsdesc":"33+9+4+5誤!這是最喬治!黑貝最.." }

  index可以指定參數,比如指定id,不指定則默認生成id。

  

  2.5、刪除文檔

  請求方式選擇Delete,請求url : http://127.0.0.1:9200/news/_doc/1 (索引/"**_doc**"/文檔id)

  2.6、查詢文檔

  請求方式選擇Get,請求url : http://127.0.0.1:9200/news/_doc/1 (索引/"**_doc**"/文檔id)

  2.7、修改文檔

  請求方式選擇POST,請求url : http://127.0.0.1:9200/news/_doc/1 (索引/"**_doc**"/文檔id)

{
    "newsname":"the new news name"        
}

  注意修改跟Mysql修改不一樣,如上值提供了newsname時,修改后其余字段均為空:

  

  2.8、根據關鍵詞查詢

  請求方式選擇Get:請求url http://127.0.0.1:9200/shop/_doc/_search (索引/"_doc"/"_search")

  請求參數query、term為固定命名,newsdesc為指定在哪個字段查詢什么關鍵字(支持什么樣的關鍵字查詢取決於mapping里指定的分析器,比如單個字為索引、分詞索引,之前測試的語句都是標准分詞,以單個字為索引,所以查詢的時候只支持一個漢字,如果輸入多個則查詢不到數據)

  基本查詢:

{
    "query": {
        "term": {
            "newsdesc": "國際"
        }
    }
}

  可以看出並未命中:

{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    }
}

  queryString是講輸入參數進行分詞然后去索引庫中檢索:

{
    "query": {
        "query_string": {
            "default_field": "newsdesc",
            "query": "國際"
        }
    }
}

  可以看到查詢命中了:

{
    "took": 20,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 0.5753642,
        "hits": [
            {
                "_index": "news",
                "_type": "_doc",
                "_id": "EZrseHUBe8Ie4tIUuaQ_",
                "_score": 0.5753642,
                "_source": {
                    "newsid": "1234657",
                    "newsname": "乒聯",
                    "newsdesc": "國際乒聯奧地利公開賽正賽展開"
                }
            }
        ]
    }
}

  因為默認的分詞器,針對中文是按字分詞的,terms查詢是精確查詢,所以查不出來。

五、ElasticSearch IK中文分詞器

  1、什么是分詞器?為什么要分詞器?

  在上面的學習例子中我們使用的是Es默認的分詞器,在中文的分詞上並不友好,會將語句每個字進行分詞作為索引,所以在使用Term關鍵字查詢的時候多個漢字無法命中文檔。這個時候就需要一個合理的分詞規則,將一個完整的語句划分為多個比較復合表達邏輯的獨立的詞條。

  分詞器包含三個部分:

  • character filter:分詞之前的預處理,過濾掉HTML標簽、特殊符號轉換(例如,將&符號轉換成and、將|符號轉換成or)等。
  • tokenizer:分詞
  • token filter:標准化

  2、ElasticSeach內置分詞器

  • standard分詞器:(默認的)它將詞匯單元轉換成小寫形式,並去掉停用詞(a、an、the等沒有實際意義的詞)和標點符號,支持中文采用的方法為單字切分(例如,‘你好’切分為‘你’和‘好’)。
  • simple分詞器:首先通過非字母字符來分割文本信息,然后將詞匯單元同一為小寫形式。該分析器會去掉數字類型的字符。
  • Whitespace分詞器:僅僅是去除空格,對字符沒有lowcase(大小寫轉換)化,不支持中文;並且不對生成的詞匯單元進行其他的標准化處理。
  • language分詞器:特定語言的分詞器,不支持中文。

  3、IK分詞器

  3.1、IK分詞器簡介

  IK分詞器在是一款 基於詞典和規則 的中文分詞器,提供了兩種分詞模式:ik_smart (智能模式)和ik_max_word (細粒度模式)

  輸入數據:

    IK Analyzer是一個結合詞典分詞和文法分詞的中文分詞開源工具包。它使用了全新的正向迭代最細粒度切分算法。 

  智能模式效果:

    ik  analyzer  是  一個  結合  詞典  分詞  和  文法  分詞  的  中文  分詞  開源  工具包  它  使  用了  全新  的  正向  迭代  最  細粒度  切分  算法

  細粒度模式:

    ik analyzer 是 一個 一 個 結合 詞典 分詞 和文 文法 分詞 的 中文 分詞 開源 工具包 工具 包 它 使用 用了 全新 的 正向 迭代 最 細粒度 細粒 粒度 切分 切 分 算法

  3.2、ElasticSearch集成Ik分詞器

  Ik分詞器下載:https://github.com/medcl/elasticsearch-analysis-ik/releases

  不同版本的集成會有所區別,請下載ES版本對應的ik分詞器版本。

  下載解壓后到你的 elasticsearch 插件目錄並重啟elasticsearch, 如: plugins/ik。

  3.3、使用ElasticSearch中的 analyze 測試Ik分詞效果

  請求方式post;請求url http://127.0.0.1:9200/_analyze

  請求參數:

{
    "analyzer": "ik_smart",//ik_max_word
    "text": "IK Analyzer是一個結合詞典分詞和文法分詞的中文分詞開源工具包。它使用了全新的正向迭代最細粒度切分算法。"
}

  3.4、Ik分詞器停用詞和擴展詞

  在實際使用過程中Ik分詞算法的過程中,還有一些場景的分詞規則是Ik無法設計的,很多時候一個網絡用語沒有被解析成一個詞條,以及其中的“的”這樣的助詞往往在建立索引的時候是沒有必要的。所以IK支持停用詞和擴展詞的配置。

  需要修改配置文件config/IKAnalyzer.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>IK Analyzer 擴展配置</comment>
    <!--用戶可以在這里配置自己的擴展字典 -->
    <entry key="ext_dict"></entry>
     <!--用戶可以在這里配置自己的擴展停止詞字典-->
    <entry key="ext_stopwords"></entry>
    <!--用戶可以在這里配置遠程擴展字典 -->
    <!-- <entry key="remote_ext_dict">words_location</entry> -->
    <!--用戶可以在這里配置遠程擴展停止詞字典-->
    <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
  • ext_dict填入擴展詞文件。
  • ext_stopwords填入停用詞文件。
  • 文件以dic后綴結尾,需要和IKAnalyzer.cfg在同級目錄。
  • dic文件每個詞需要占一行。

六、ElasticSearch集群

  在我們常見的項目中,很多時候都是分布式/集群部署的:對於不用的微服務通過Nginx負載或者注冊到APIGateway、Zuul網關,然后每個服務進行主從/集群部署,然后用到的數據存儲你產品也是基於分片+主從,保證可用性,如下圖所示:

      

  而我們的ElasticSearch也是一樣的集群部署。

  1、集群 cluster

  一個集群就是一個或多個節點組織在一起,他們共同持有整個庫的數據,並在一起提供索引和搜索功能,一個集群由一個唯一的名字表示。所有節點通過這個集群名字,來進入這個集群。

  2、節點node

  一個節點是由集群中的一個服務器,作為集群的一部分,它存儲數據,參與集群的索引和搜索功能。和集群類似,一個節點也是由一個名字來標識的,默認情況下,這個名字是一個隨機的。

  一個節點可以通過配置集群名稱的方式來加入一個指定的集群。

  3、分片和復制 shard & replicas

  3.1、分片

  一個索引可以存儲超過單個節點硬件限制的大量數據,比如說一個索引具有10億文檔,占據1T的磁盤空間,而任意一個節點都沒有這樣大的一個磁盤空間;或者單個節點處理搜索請求,響應太慢了,為了解決這個問題,ElasticSearch提供了將索引划分為多份的能力,每一份就叫做一個分片。當建立一個索引的時候,可以指定想要分配的分片數量。每個分片本身也是一個功能完善並且獨立的“索引”,這個“索引”可以被放置到集群中的任何節點上。分片很重要,主要體現在兩方面:

  • 允許你水平分割/擴展你的內容容量。
  • 允許你在分片之上進行分布式並行操作,從而提高性能和吞吐量

  至於分片怎么分布,查詢結果怎么聚合,完全由elasticsearch管理的。開發者不需要關心。

  3.2、復制

  在網絡環境或者說分布式環境中,通訊發生失敗是常有的事,所以當某個分片節點出現故障,故障轉移機制是非常有必要的。因此Elasticsearch允許你創建分片的一份或者多份拷貝,這些拷貝叫做復制分片,或者就叫復制。

  復制的存在提高了節點出現故障時的集群高可用性。因為這個原因,復制分片應注意與主分片不能在同一個節點上。

  總結的說,一個索引可以被分為多個分片,可以被復制0~N次,一旦復制了就有了主分片和復制分片之別。分片和復制的數量可以在索引創建的時候指定。在索引創建之后,復制的數量可以改變,但是分片數量不能改變。

  分片和復制邏輯結構:

      

  物理結構:

      

  4、集群搭建

  對於一個新建的節點需要保證安裝目錄的data目錄為空,修改 elasticsearch.yml 配置文件(注意冒號后面的空格)。

#集群名稱
cluster.name: my-elasticsearch
#節點名稱,不同的節點名稱必須不一樣
node.name: node-1 # 是否可以成為master節點
node.master: true #必須為本機的ip地址
network.host: 127.0.0.1 #服務端口,在同一機器下必須不一樣
http.port: 9201 #集群間通訊端口號,在同一機器必須不一樣
transport.tcp.port: 9301 #集群節點
discovery.seed_hosts:
- 127.0.0.1:9301
- 127.0.0.1:9302
- 127.0.0.1:9303 #集群中的主節點
cluster.initial_master_nodes:
- 127.0.0.1:9301

  不同節點注意修改節點名稱、服務端口、通訊端口、以及是否可以成為主節點屬性,修改完畢后依次啟動不同節點服務。

  5、節點的3中類型

  5.1、主節點

  即 Master 節點。主節點的主要職責是和集群操作相關的內容,如創建或刪除索引,跟蹤哪些節點是群集的一部分,並決定哪些分片分配給相關的節點。穩定的主節點對集群的健康是非常重要的。默認情況下任何一個集群中的節點都有可能被選為主節點。索引數據和搜索查詢等操作會占用大量的cpu,內存,io資源,為了確保一個集群的穩定,分離主節點和數據節點是一個比較好的選擇。雖然主節點也可以協調節點,路由搜索和從客戶端新增數據到數據節點,但最好不要使用這些專用的主節點。一個重要的原則是,盡可能做盡量少的工作。

  5.2、數據節點

  即 Data 節點。數據節點主要是存儲索引數據的節點,主要對文檔進行增刪改查操作,聚合操作等。數據節點對 CPU、內存、IO 要求較高,在優化的時候需要監控數據節點的狀態,當資源不夠的時候,需要在集群中添加新的節點。

  5.3、預處理節點

  也稱作 Ingest 節點,在索引數據之前可以先對數據做預處理操作(如:函數運算、類型轉換等),所有節點其實默認都是支持 Ingest 操作的,也可以專門將某個節點配置為 Ingest 節點。
  以上就是節點幾種類型,一個節點其實可以對應不同的類型,如一個節點可以同時成為主節點和數據節點和預處理節點,具體的類型可以通過具體的配置文件來設置。

    

  6、分片交互

​   我們能夠發送請求給集群中任意一個節點。每個節點都有能力處理任意請求。每個節點都知道任意文檔所在的節點,所以也可以將請求轉發到需要的節點。下面的例子中,我們將發送所有請求給`Node 1`,這個節點我們將會稱之為請求節點(requesting node)。 當我們發送請求,最好的做法是循環通過所有節點請求,這樣可以平衡負載,或者借助nginx、apache等反向代理服務器進行負載。

  6.1、新建、刪除索引和刪除文檔時

  新建、索引和刪除請求都是寫(write)操作,它們必須在主分片上成功完成才能復制到相關的復制分片上。

    

   6.2、單條檢索文檔集群交互流程

     

  6.3、批量查詢文檔

  請求拆成每個分片的請求,然后轉發每個參與的節點。

      

  7、集群節點自動分片及重啟

  我們先看啟動master,然后創建索引,再啟動剩余2個node節點,並在此創建一個索引,可以在elasticsearch-head看到索引的分片以及副本情況如下:

    

  elasticsearch集群的高可用和自動平衡方案會在節點掛掉(重啟)后自動在別的節點上復制該節點的分片,這將導致大量的IO和網絡開銷。

  如果離開的節點重新加入集群,elasticsearch為了對數據分片(shard)進行再平衡,會為重新加入的節點再次分配數據分片(shard),當一台ES因為壓力過大而掛掉以后,其他的ES服務器會備份本應那台ES保存的數據,造成更大的壓力,於是造成整個集群會發生雪崩。因此生產環境下建議關閉自動平衡

cluster.routing.rebalance.ennable: none

  可以設置延遲副本重新分配機制:

index.unassigned.node_left.delayed_timeout: 5m

  還可以指定集群節點到達多少數量才開始平衡:

gateway.recover_after_nodes: 8


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM