注:本篇的es基於7.5.1版本
目錄
Elasticsearch是什麼?
Elasticsearch是一個基於Lucene庫的搜索引擎。它提供了一個分佈式、支持多租戶的全文搜索引擎,Restful接口和無模式JSON文檔。Elasticsearch是用Java開發的,並在Apache許可證下作爲開源軟件發佈。 -------維基百科
說白了就是一個分佈式的高性能全文搜索引擎,提供非常牛逼的模糊搜索。
ElasticSearch的環境搭建
知道幹啥的了,就先跑起來。
先說一下ES是需要JDK環境的。低版本的ES需要我們下載JDK然後運行,高版本直接內置了JDK 可以直接設置成環境變量不用單獨下載了。
但是!!!我下面是用docker 跑的哈哈哈 不需要考慮這些東西。
docker pull elasticsearch:7.5.1
docker run --name esSingle -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -v /home/zy/docker/es/node1/config:/usr/share/elasticsearch/config -v /home/zy/docker/es/node1/data:/usr/share/elasticsearch/data -v /home/zy/docker/es/node1/logs:/usr/share/elasticsearch/logs elasticsearch:7.5.1
curl 127.0.0.1:9200 有ES的結果就安裝成功了。 參數discovery.type是發現模塊的參數,設置一下ES爲單節點。 上面映射了三個目錄,看名就知道是幹啥的了。
ElasticSearch的名詞
索引(index):相當於關係型數據庫中的一個庫。
類型(type):相當於關係型數據庫的一個表。
文檔:相當於一條數據。一個文檔被一個index+type+id唯一標識。
分片(shard):一個index分成物理分片存儲在集羣中的不同節點(一個節點可以包括多個分片),分片分爲主分片和副本分片。
節點(node):一個ES實例、
倒排索引:是ES快速搜索到一個文檔的數據結構。
分析:將全文轉化成術語(詞)的過程 FoO ---> foo
集羣:多個node節點組成。node節點的cluster.name 必須相同。每個集羣自動選擇一個master節點。master節點down掉重新選
Translog: 提供所有還沒有被刷到磁盤的操作的一個持久化記錄(CRUD)。
Segment: lucene把每次生成的倒排索引叫做一個 segment
ElasticSearch查詢出的數據格式
ES是分佈式的。當文檔創建、更新、刪除等寫操作時,新版本的文檔必須複製到集羣中的其他節點。ES是異步和併發的,ES使用_seq_no和_primary_term來確保舊版本不會覆蓋新版本,唯一標識一個版本。進行樂觀鎖併發控制。
version用於計算文檔更新的請求(bulk批操作的文檔的_version相同)
seq_no用於計算索引上發生的操作數(bulk批操作的文檔seq遞增)
每當Primary Shard發生重新分配時,比如重啓,Primary選舉等,_primary_term會遞增1
可以使用bulk操作來驗證version與seq_no
ElasticSearch中9200&9300端口
9200作爲Http協議,主要用於外部通訊
9300作爲Tcp協議,client之間就是通過tcp協議通訊,es集羣之間是通過9300進行通訊。
ElasticSearch的架構
Gateway是ES用來存儲索引的文件系統,支持多種類型。
Gateway的上層是一個分佈式的lucene框架。
Lucene之上是ES的模塊,包括:索引模塊、搜索模塊、映射解析模塊等ES模塊之上是 Discovery、Scripting和第三方插件。
Discovery是ES的節點發現模塊,不同機器上的ES節點要組成集羣需要進行消息通信,集羣內部需要選舉master節點,這些工作都是由Discovery模塊完成。支持多種發現機制,如 Zen 、EC2、gce、Azure。
Scripting用來支持在查詢語句中插入javascript、python等腳本語言,scripting模塊負責解析這些腳本,使用腳本語句性能稍低。
ES也支持多種第三方插件。
再上層是ES的傳輸模塊和JMX.傳輸模塊支持多種傳輸協議,如 Thrift、memecached、http,默認使用http。
JMX是java的管理框架,用來管理ES應用。
最上層是ES提供給用戶的接口,可以通過RESTful接口和ES集羣進行交互。
ElasticSearch基本操作就不再描述了。去官網上學吧。那最全!
ElasticSearch索引模板
索引模板是一個比較有用的東西。他能讓你創建索引省去很多重複性的勞動,比如日誌索引,可以複用一個索引模板。這樣可以配合filebeat/logstash自動創建好你的日誌索引的格式。
索引模板主要拆分成如下幾個部分
{
"order": 0, // 模板優先級order數字越大, 模板優先級越高。
"template": "logs-*", // 模板匹配的名稱方式
"settings": {...}, // 索引設置, 字段拆分
"mappings": {...}, // 索引中各字段的映射定義
"aliases": {...} // 索引的別名.零停機的情況下從舊索引遷移到新索引。
}
其中settings 部分設置一些解析相關。
"settings": {
"index": {
"analysis": {
“char_filter”: { ... }, // 用戶自定義字符過濾器,字符串替換
“tokenizer”: { ... }, // 用戶自定義分詞器,字符串拆分
“filter”: { ... }, // 用戶自定義標記過濾器,字符串去除
"analyzer": { ... } // 用戶自定義分析器
},
"number_of_shards": "32", // 主分片的個數
"number_of_replicas": "1", // 主分片的拷貝分片個數
"refresh_interval": "5s" // 刷新時間 往文件系統緩存中刷segment
}
}
mapping設置字段相關的,分爲動態映射以及自定義字段。
"mappings": {
"my_type": {
"dynamic_templates": [
{
"string_fields": { // 字段映射模板的名稱,一般爲"類型_fields"的命名方式
"match": "*", // 匹配的字段名爲所有
"match_mapping_type": "string", // 限制匹配的字段類型,只能是 string 類型
"mapping": {
"fielddata": { "format": "disabled" }, // fielddata 不可用,對於分析字段,其默認值是可用
"analyzer": "only_words_analyzer", // 字段採用的分析器名,默認值爲 standard 分析器
"index": "analyzed", // 索引方式定義爲索引,默認值是分析
"omit_norms": true, // omit_norms 爲真表示考慮字段的加權,可分析字段默認值 false
"type": "string", // 字段類型限定爲 string
"fields": { // 定義一個嵌套字段,將該字段應用於不分析的場景
"raw": {
"ignore_above": 256, // 忽略字段對應的值長度大於256的字段
"index": "not_analyzed", // 索引方式爲不分析
"type": "string", // 字段的類型爲 string
"doc_values": true // 對於不分析字段,doc_values 對應的是一種列式存儲結構,默認false
}
}
}
}
}
],
"properties": {
"user_city": { // 字段名
"analyzer": "lowercase_analyzer", // 字段分析器
"index": "analyzed", // 字段索引方式定義索引
"type": "string", // 字段數據類型定義爲 string
"fields": { // 定義一個名爲 user_city.raw 的嵌入的不分析字段
"raw": {
"ignore_above": 512,
"index": "not_analyzed",
"type": "string"
}
}
}
}
}
}
ElasticSearch數據持久化到磁盤的過程
1、Refresh: 將segment刷到文件系統緩存的步驟叫做refresh 刷到文件系統緩存之後可供用戶搜索。
2、參數refresh_interval:1s 設置刷segment的頻率。每個索引的settings中設置。可以主動調用refresh的API刷、
3、Flush: Segment持久化到磁盤的步驟叫flush
4、當segment被刷到磁盤中後commit提交點會更新,對應的translog文件會被清空、
5、Translog文件每5秒或每次請求操作接收前會強制刷到磁盤。防止translog文件丟失。
6、Segment是單個的倒排索引,這麼維護特別費勁,因此segment會進行合併。
7、當歸並segment完成,commit文件會刪除小的segment,改成大的segment
8、segment合並可以通過自定義策略。還可以通過forcemergeAPI強制合併
9、合併結束,老segment會被刪除
ElasticSearch的倒排索引
倒排索引是ES比較厲害的一個數據結構。每個字段有自己的倒排索引。
Term index: 一棵字典樹Trie tree,用來存儲前綴來幫助快速搜索詞。(女/男) 減少磁盤的隨機讀取操作。
Term dictionary: 排序的詞序列。排序之後時間複雜度就從O(n)àO(logn)存儲籃球,足球這種詞。
Posting List: 按照字段劃分。比如play 籃球[1,2] 排球[3] 會記錄每個字段相關的id
ElasticSearch集羣相關
如圖所示是一個集羣的分佈。 圖中有三個node節點也就是三個ES實例。P代表Primary shard 主分片,R代表replica副本分片。一個索引創建時可以主動指定分片的數量且主分片指定後不允許改變。
帶有master字樣的node是整個集羣的主節點。它有權限控制整個集羣,比如資源的分配、節點的修改等等
ES路由&副本分片
shard = hash(routing) % number_of_primary_shards
routing是一個可變值。默認是文檔的 _id,路由依賴索引分片的數量,所以創建索引時要確定好主分片的數量。並且不修改這個數量、如果數量變化了,所有之前的值都丟失了。
1.請求打到node1的主分片P1,node1節點通過路由計算得到數據存儲在P0分片上,通過cluster state 發現P0在node3節點node1將請求轉發給node3
2.node3完成請求後,存入P0,然後並行轉發數據給有P0的副本分片R0的node1和node2
3.當收到任一節點返回副本分片寫入成功,node3返回給node1結果,node1返回給客戶端。
ElasticSearch中的節點種類
Elasticsearch.yml文件中可以配置node.master、node.data、node.ingest、以及tribe.*
1.Master節點、主節點。當一個節點配置node.master: true(默認)的時候他就有資格被選作主節點,控制整個集羣。
2.Data節點、數據節點。node.data: true(默認) 該節點保存數據和執行數據相關的操作。CRUD,聚合等等
3.Ingest節點、提取節點。node.ingest: true(默認) 該節點可以通過ingest pipeline 對文檔執行預處理操作,以便在索引文檔之前對文檔進行轉換。filebeat等都是可以配置管道將文件發送到指定管道來執行預處理操作。
4.Tribe節點、部落節點。當一個節點配置tribe.* 的時候。可以連多個集羣,在所有集羣上執行搜索和操作。
5.Client節點、當主節點和數據節點的配置都是false時,該節點只能處理路由請求,處理搜索分發索引操作等。
ElasticSearch集羣搭建
下面是基於docker-compose.yml文件搭建的兩個節點的ES集羣。啥也沒映射。創建一個docker-compose.yml文件。內容把下面複製進去,然後docker-compose up -d 等會就起來了、
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.1
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms256m -Xmx256m"
ulimits:
memlock:
soft: -1
hard: -1
ports:
- 9200:9200
networks:
- elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.1
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms256m -Xmx256m"
ulimits:
memlock:
soft: -1
hard: -1
networks:
- elastic
networks:
elastic:
driver: bridge
參考: