Elastic Search知識點整理、入門

ES簡介

一個叫Shay Banon開發(fā)者,在2010年2月發(fā)布了第一個公開版本。

Elasticsearch(ES)是一個基于Lucene(Lucene:Lucene是一個Java全文搜索引擎,完全用 Java 編寫。Lucene不是一個完整的應用程序,而是一個代碼庫和API)構(gòu)建的開源、分布式、RESTful接口的全文搜索引擎。Elasticsearch還是一個分布式文檔數(shù)據(jù)庫,其中每個字段均可被索引,而且每個字段的數(shù)據(jù)均可被搜索,ES能夠橫向擴展至數(shù)以百計的服務器存儲以及處理PB級的數(shù)據(jù)??梢栽跇O短的時間內(nèi)存儲、搜索和分析大量的數(shù)據(jù)。通常作為具有復雜搜索場景情況下的核心發(fā)動機。

相關(guān)概念解讀

全文檢索引擎

其工作原理是計算機索引程序通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞再文章中出現(xiàn)的次數(shù)和位置。當用戶查詢時,檢索程序就根據(jù)實現(xiàn)建立的索引進行查找,并將查找的結(jié)果反饋給用戶的檢索方式(舉例:字典)

數(shù)據(jù)類型

  • 結(jié)構(gòu)化數(shù)據(jù):具有固定格式或有限長度的數(shù)據(jù)
  • 非結(jié)構(gòu)化數(shù)據(jù):又稱全文數(shù)據(jù),指不定長度或無固定格式的數(shù)據(jù)

搜索方式

針對數(shù)據(jù)類型的不同,對應的搜索方式也有別:

  • 結(jié)構(gòu)化數(shù)據(jù):通過關(guān)系型數(shù)據(jù)庫的table方式存儲和搜索
  • 非結(jié)構(gòu)化數(shù)據(jù):
    • 順序掃描————按照順序依次查找->耗時、低效
    • 全文檢索————將數(shù)據(jù)中的一部分信息提取出來,重新組織使其變得有一定結(jié)構(gòu),然后對此有一定結(jié)構(gòu)的數(shù)據(jù)進行搜索,從而達到搜索相對較快的目的(這部分從非結(jié)構(gòu)化數(shù)據(jù)中心提取出來的然后重新組織的信息,就叫索引)

全文檢索使用背景

  • 搜索數(shù)據(jù)對象是大量的非結(jié)構(gòu)化文本數(shù)據(jù)
  • 文件記錄量達到數(shù)十萬或數(shù)百萬甚至更多
  • 支持大量基于交互式文本的查詢
  • 需要非常靈活的全文搜索查詢
  • 對高度相關(guān)的搜索結(jié)構(gòu)有特殊需求
  • 對不同記錄類型,非文本數(shù)據(jù)操作或事務處理需求相對較少

主流全文檢索引擎

Lucene、Solr、Elastic Search

ES特點

  • 基于分布式————將數(shù)據(jù)進行分段分片存儲并在各個分片上進行查詢操作
  • 容差容錯機制————集群部署時,通過設(shè)置副本分片的機制,實現(xiàn)即時一個節(jié)點掛掉,數(shù)據(jù)也能在別的節(jié)點分片上正常進行查詢
  • 基于文檔————文檔存儲
  • 全文全庫檢索
  • 可處理數(shù)據(jù)量大
  • 分布式實施文檔存儲,每個字段可以被索引和搜索
  • 能勝任上百個服務節(jié)點的擴展,支持PB級別的結(jié)構(gòu)化數(shù)據(jù)和非結(jié)構(gòu)化數(shù)據(jù)

ES索引方式————倒排索引

一個倒排索引由文檔中所有不重復詞的列表構(gòu)成,對于其中每個詞,有一個包含它的文檔列表。
對于不同的文檔中每個詞的出現(xiàn)與否做出標記。

例如有兩個文檔:

  • The quick brown fox jumped over the lazy dog
  • Quick brown foxes leap over lazy dogs in summer

生成的倒排索引如下圖所示:

image

ES核心概念

  • Cluster集群: 一個集群是由一個或多個節(jié)點組成的(集群中的節(jié)點通過設(shè)置相同的 cluster.name,來分類集群的)
  • Node節(jié)點: 一個運行中的Elasticsearch實力稱為一個節(jié)點
  • Shade分片: 一個分片是一個底層的工作單元,它僅保存了全部數(shù)據(jù)中的一部分(主分片即主要存儲數(shù)據(jù)的分片,副分片即主分片的備份,存在于不同的節(jié)點上,若節(jié)點越多,主分片對應的副分片存在的節(jié)點也會越多。容差容錯機制就是在備份中產(chǎn)生的,如果運行中一個節(jié)點出現(xiàn)故障、主分片上的數(shù)據(jù)全部丟失,那么存有該主分片副本的節(jié)點就會自動接替之前的工作)
  • Index索引: 相當于sql中的database
  • Type類型: 相當于db中的table
  • Document文檔: 相當于table中的一條數(shù)據(jù)

集群內(nèi)的原理

  • 一個運行中的Elasticsearch實例稱為一個節(jié)點,而集群是由一個或者多個擁有相同 cluster.name 配置的節(jié)點組成,它們共同承擔數(shù)據(jù)和負載的壓力。當有節(jié)點加入集群中或者從集群中移除節(jié)點時,集群將會重新平均分布所有的數(shù)據(jù)。
  • 當一個節(jié)點被選舉成為主節(jié)點時,它將負責管理集群范圍內(nèi)的所有變更,例如增加、刪除索引,或者增加、刪除節(jié)點等。而主節(jié)點并不需要涉及到文檔級別的變更和搜索等操作。任何節(jié)點都可以成為主節(jié)點。

一個集群中有一個包含空內(nèi)容的節(jié)點

image

同一個集群中有兩個節(jié)點,其中Node1為主節(jié)點

image

分片與副本分片

  • 一個分片是一個底層的工作單元,它僅保存了全部數(shù)據(jù)中的一部分。
  • Elasticsearch 是利用分片將數(shù)據(jù)分發(fā)到集群內(nèi)各處的。分片是數(shù)據(jù)的容器,文檔保存在分片內(nèi),分片又被分配到集群內(nèi)的各個節(jié)點里。當你的集群規(guī)模擴大或者縮小時,Elasticsearch會自動的在各節(jié)點中遷移分片,使得數(shù)據(jù)仍然均勻分布在集群里。
  • 一個分片可以是主分片或者副本分片。索引內(nèi)任意一個文檔都歸屬于一個主分片,所以主分片的數(shù)目決定著索引能夠保存的最大數(shù)據(jù)量。

關(guān)于索引和分片

一個Lucene索引在es稱為分片,一個es索引是分片的集合。

Elasticsearch在索引中搜索時,它發(fā)送查詢到每一個屬于索引的分片,然后合并每個分片的結(jié)果到一個全局的結(jié)果集(分布式搜索,后面有提到)。

以下為分片的例子:

image

(上圖表示有一個節(jié)點,節(jié)點中有三個主分片)

image

(上圖表示有兩個節(jié)點<其中Node1為主節(jié)點>,且Node中存有三個主分片,Node2中存有三個副本分片<主要的數(shù)據(jù)被復制了一次,產(chǎn)生了一套主分片的副本分片>)

image

(上圖表示共有三個節(jié)點,主分片被復制了一次,產(chǎn)生了一套副本分片,主分片與副本分片平均分派在三個節(jié)點中)

image

(上圖表示共有三個節(jié)點,主分片被復制了兩次,產(chǎn)生了兩套副本分片,主分片與副本分片平均分派在三個節(jié)點中)

image

(上圖表示共有兩個節(jié)點,其中Node1掛掉,隨機分配Node2為主節(jié)點,并轉(zhuǎn)移分配對應的主分片————容差容錯機制的體現(xiàn))

分片內(nèi)的原理

以索引一個新文檔為例:

當用戶向一個節(jié)點提交了一個索引新文檔的請求,節(jié)點會計算新文檔應該加入到哪個分片(shard)中。每個節(jié)點都存儲有每個分片存儲在哪個節(jié)點的信息,因此協(xié)調(diào)節(jié)點會將請求發(fā)送給對應的節(jié)點。注意這個請求會發(fā)送給主分片,等主分片完成索引,會并行將請求發(fā)送到其所有副本分片,保證每個分片都持有最新數(shù)據(jù)。

image

(一個Lucene索引包含一個提交點和三個段,如上圖所示)

image

(一個文檔被索引之后,就會被添加到內(nèi)存緩沖區(qū),并且追加到了translog)

image

(分片每秒被刷新(refresh)一次,這些在內(nèi)存緩沖區(qū)中的文檔被寫入到一個新的段中,這個段被打開,當前可以被搜索到,但該段并未被寫入到磁盤中,因此,此時節(jié)點掛掉的話,該段將不復存在;內(nèi)存緩沖區(qū)被清空,但事務日志不會<為節(jié)點掛掉重啟后做數(shù)據(jù)恢復>)

image

(這個進程繼續(xù)工作,更多的文檔被添加到內(nèi)存緩沖區(qū)和追加到事務日志)

image

(每隔一段時間--索引被刷新(flush);一個新的translog被創(chuàng)建,并且一個全量提交被執(zhí)行;所有在內(nèi)存緩沖區(qū)中的文檔被寫入一個新的段中,緩沖區(qū)被清空;一個提交點被寫入磁盤中;文件系統(tǒng)緩存通過fsync被刷新;老的事務日志被刪除)

段合并

圖示(兩個提交了的段和一個未提交的段正在被合并到一個更大的段)

image
  • 背景:由于自動刷新流程每秒會創(chuàng)建一個新的段,這樣會導致短時間內(nèi)的段數(shù)量暴增。而段數(shù)目太多會帶來較大的麻煩。每一個段都會消耗文件句柄、內(nèi)存和cpu運行周期。更重要的是,每個搜索請求都必須輪流檢查每個段;所以段越多,搜索也就越慢。
  • 實施:合并進程選擇一小部分大小相似的段,并且在后臺將它們合并到更大的段中。這并不會中斷索引和搜索。
  • 結(jié)果:新的段被刷新(flush)到了磁盤;新的段被打開用來搜索;老的段被刪除。

結(jié)果圖示

image

總流程圖

image

分布式搜索

圖示

image
  • 查詢請求可以被某個主分片或某個副本分片處理,協(xié)調(diào)節(jié)點將在之后的請求中輪詢所有的分片拷貝來分攤負載。
  • 如果客戶端要求返回結(jié)果排序中從第from名開始的數(shù)量為size的結(jié)果集,則每個節(jié)點都需要生成一個from+size大小的結(jié)果集,因此優(yōu)先級隊列的大小也是from+size。分片僅會返回一個輕量級的結(jié)果給協(xié)調(diào)節(jié)點,包含結(jié)果集中的每一個文檔的ID和進行排序所需要的信息。
  • 協(xié)調(diào)節(jié)點會將所有分片的結(jié)果匯總,并進行全局排序,得到最終的查詢排序結(jié)果。此時查詢階段結(jié)束。

ES安裝

系統(tǒng)環(huán)境

  • CentOS 7.6.1810
  • jdk 1.8.0_201

elasticsearch安裝方法

tar -zxvf elasticsearch-6.6.0.tar.gz -C /opt/module/ # 解壓安裝包
vi elasticsearch.yml # 修改配置文件
cluster.name: my-application # 集群名稱(多集群時候只需節(jié)點名稱一直即可)
node.name: node-1 # 節(jié)點名稱————同一集群中不能重復
path.data: /opt/module/elasticsearch-6.6.0/data # 數(shù)據(jù)路徑
path.logs: /opt/module/elasticsearch-6.6.0/logs # 日志路徑
bootstrap.memory_lock: false
bootstrap.system_call_filter: false
network.host: 192.168.1.8 # 網(wǎng)絡地址
http.port: 9200 # 端口
discovery.zen.ping.unicast.hosts: ["Hosts"] # 主機名

ES啟動

elasticsearch禁止使用root用戶啟動,需要新建一個用戶

./bin/elasticsearch    // 解壓目錄下執(zhí)行

訪問地址:http://localhost:9200/

Spring Boot 集成

使用Spring Data Elasticsearch

增加POM文件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

Spring data elasticsearch 與 es 版本對照

spring data elasticsearch elasticsearch
3.2.x 6.5.0
3.1.x 6.2.2
3.0.x 5.5.0
2.1.x 2.4.0
2.0.x 2.2.0
1.3.x 1.5.2

增加配置

spring:
  data:
    elasticsearch:
      cluster-name: elasticsearch
      cluster-nodes: 172.0.0.1:9200
      repositories:
        enabled: true

使用

@Data
@AllArgsConstructor
@Document(indexName = "human", type = "student") ////indexName索引名稱,type類別
@Id
public class Student {
    private String name;
    private Integer age;
    private String sex;
}
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;

@Test
public void test() {
    Student student = new Student(1, "張三", 100, "女");

    //新增
    IndexQuery indexQuery = new IndexQueryBuilder()
                .withIndexName("human")
                .withType("student")
                .withId(student.getId()+"")
                .withObject(student) //對象或集合
                .build();
    elasticsearchTemplate.index(indexQuery);
}

也可通過創(chuàng)建接口實現(xiàn)ElasticsearchRepository<?,?>方法,通過方法注解@Query來實現(xiàn)查詢等操作,示例:

public interface StudentRepository extends ElasticsearchRepository<Student, String> {
    @Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")
    Page<Student> findByName(String name,Pageable pageable);
}

ES查詢示例

查詢相關(guān)轉(zhuǎn)到

http://note.youdao.com/noteshare?id=309b9ba17ed685e685fe3cd748432607&sub=7E0B4904374841159E1A2FDA7297FDB9

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容