基本概念
Near Realtime(NRT進(jìn)實(shí)時(shí))
Elasticsearch是一個(gè)進(jìn)實(shí)時(shí)的搜索平臺(tái),這意味著您從索引一個(gè)文檔開始知道它可以被查詢時(shí)會(huì)有輕微的延遲時(shí)間(通常為一秒)衩婚。
Cluster(集群)
cluster是一個(gè)或者多個(gè)節(jié)點(diǎn)的集合蓝仲,他們一起保存數(shù)據(jù)并且提供所有的節(jié)點(diǎn)聯(lián)合索引以及搜索功能搀暑。集群存在一個(gè)唯一的名字身份且默認(rèn)為“elasticsearch”。這個(gè)名字非常重要根灯,因?yàn)槿绻?jié)點(diǎn)安裝時(shí)通過(guò)他自己的名字加入到一個(gè)集群中的話,那么一個(gè)節(jié)點(diǎn)只能是一個(gè)集群中的一部分。
Node(節(jié)點(diǎn))
node(節(jié)點(diǎn))是一個(gè)單獨(dú)的服務(wù)器醇疼,他是集群中的一部分,存儲(chǔ)數(shù)據(jù)法焰,參與集群中的索引和搜索的功能秧荆。想一個(gè)集群一樣,一個(gè)節(jié)點(diǎn)通過(guò)一個(gè)在他啟動(dòng)是默認(rèn)分配的uuid(通用唯一標(biāo)識(shí)符)名稱來(lái)識(shí)別埃仪。如果不想使用默認(rèn)的名稱乙濒,您也可以自定義任務(wù)節(jié)點(diǎn)的名稱。這個(gè)名字是要識(shí)別網(wǎng)絡(luò)中的服務(wù)器對(duì)應(yīng)卵蛉,這在集群的節(jié)點(diǎn)管理的目的是很重要的颁股。
Index(索引)
動(dòng)詞,相當(dāng)于MySQL中的insert毙玻;
名詞豌蟋,相當(dāng)于MySQL中的Database
Type(類型)
在 Index(索引)中,可以定義一個(gè)或多個(gè)類型桑滩。
類似于MySQL中的Table梧疲;每一種類型的數(shù)據(jù)放在一起;
Document(文檔)
保存在某個(gè)索引(Index)下运准,某種類型(Type)的一個(gè)數(shù)據(jù)(Document)幌氮,文檔是JSON格式的,Document就像是MySQL中的某個(gè)Table里面的內(nèi)容
Shards&Replicas(分片&副本)
索引可以存儲(chǔ)大量數(shù)據(jù)胁澳,可以超過(guò)單個(gè)節(jié)點(diǎn)的硬件限制该互。例如,十億個(gè)文檔占用了 1TB 的磁盤空間的單個(gè)索引可能不適合放在單個(gè)節(jié)點(diǎn)的磁盤上韭畸,并且從單個(gè)節(jié)點(diǎn)服務(wù)請(qǐng)求會(huì)變得很慢宇智。
為了解決這個(gè)問(wèn)題蔓搞,Elasticsearch 提供了把 Index(索引)拆分到多個(gè) Shard(分片)中的能力。在創(chuàng)建索引時(shí)随橘,您可以簡(jiǎn)單的定義 Shard(分片)的數(shù)量喂分。每個(gè) Shard本身就是一個(gè) fully-functional(全功能的)和獨(dú)立的 “Index(索引)”,(Shard)它可以存儲(chǔ)在集群中的任何節(jié)點(diǎn)上机蔗。
Sharding(分片)非常重要兩個(gè)理由是 :
1)水平的拆分/擴(kuò)展蒲祈。
2)分布式和并行跨 Shard 操作(可能在多個(gè)節(jié)點(diǎn)),從而提高了性能/吞吐量萝嘁。
每個(gè)索引可以被拆分成多個(gè)分片梆掸,一個(gè)索引可以設(shè)置 0 個(gè)(沒(méi)有副本)或多個(gè)副本。開啟副本后牙言,每個(gè)索引將有主分片(被復(fù)制的原始分片)和副本分片(主分片的副本)酸钦。分片和副本的數(shù)量在索引被創(chuàng)建時(shí)都能夠被指定。在創(chuàng)建索引后嬉挡,您也可以在任何時(shí)候動(dòng)態(tài)的改變副本的數(shù)量钝鸽,但是不能夠改變分片數(shù)量汇恤。
初步檢索
_cat
GET /_cat/nodes: 查看所有的節(jié)點(diǎn)
GET /_cat/health:查看es健康狀況
GET /_cat/master:查看主節(jié)點(diǎn)
GET /_cat/indeices:查看所有的索引
索引一個(gè)文檔
PUT customer/external/1
{
"name":"John Doe"
}
PUT和POST都可以
POST只是新增
PUT可以新增可以修改
查詢文檔
GET customer/external/1
更新文檔
POST customer/external/1/_update
{
"doc":{
"name": "John Doew"
}
}
或者
PUT customer/external/1
{
"name": "John Doe"
}
或者
POST customer/external/1
{
"name": "John Doe2"
}
POST | PUT | |
---|---|---|
不同點(diǎn) | post操作會(huì)對(duì)比源文檔,如果相同不會(huì)有什么操作,文檔的version不會(huì)增加 | PUT操作不會(huì)對(duì)比源文檔,總是會(huì)將數(shù)據(jù)重新保存并增加version版本 |
更新的同時(shí)增加屬性
POST customer/external/1/_update
{
"doc": { "name": "Jane Doe", "age": 20 }
}
簡(jiǎn)單腳本更新
POST customer/external/1/_update
{
"script" : "ctx._source.age += 5"
}
刪除文檔&索引
DELETE customer/external/1
DELETE customer
bulk批量API
POST customer/external/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
語(yǔ)法格式:
{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
bulk API以此順序執(zhí)行所有的action(動(dòng)作)如果一個(gè)單個(gè)的動(dòng)作因?yàn)槿魏卧蚴∨痈郑鼘⒗^續(xù)處理他后面的剩余的動(dòng)作。當(dāng)bulk API返回時(shí)因谎,它將提供每個(gè)動(dòng)作的狀態(tài)(與放松的順序相同)基括,所以您可以檢查是否一個(gè)指定的動(dòng)作是不是失敗了。
樣本測(cè)試數(shù)據(jù)
POST bank/account/_bulk
測(cè)試數(shù)據(jù)
進(jìn)階檢索
檢索信息
一切檢索從_search開始
響應(yīng)結(jié)果解釋
名詞 | 解釋 |
---|---|
took- Elasticsearch | 執(zhí)行搜索的時(shí)間(毫秒) |
time-out | 搜索是否超時(shí) |
_shards | 多少個(gè)分片被搜索了,以及統(tǒng)計(jì)了成功/失敗的搜索分片 |
hits | 搜索的結(jié)果 |
hits.total | 搜索的結(jié)果 |
hits.hits | 實(shí)際的搜索結(jié)果數(shù)組(默認(rèn)為前10的文檔) |
sort | 結(jié)果的排序key(鍵) |
score和max_score | 相關(guān)性得分和最高得分(全文檢索的時(shí)候使用) |
uri+請(qǐng)求體進(jìn)行搜索
GET bank/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"account_number": {
"order": "desc"
}
}
]
}
我們post一個(gè)json風(fēng)格的查詢到_search API财岔。需要了解风皿,一旦搜索結(jié)果被返回,es就完成了這次請(qǐng)求匠璧,并且不會(huì)維護(hù)任何服務(wù)端的資源或者結(jié)果的cursor(游標(biāo))
Query DSL
基本語(yǔ)法結(jié)構(gòu)
es提供了一個(gè)可以執(zhí)行查詢的JSON分割的DSL(domain-specific language領(lǐng)域特定語(yǔ)言)桐款。這個(gè)被稱為Query DSL。該查詢語(yǔ)句非常全面夷恍,并且剛開始的時(shí)候會(huì)感覺(jué)有點(diǎn)復(fù)雜魔眨,真正學(xué)好他的方法是從一些基礎(chǔ)的示例開始的。
- 一個(gè)查詢語(yǔ)句的典型結(jié)構(gòu)
{
QUERY_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
- 如果是針對(duì)某個(gè)字段,那么他的結(jié)構(gòu)如下
{
QUERY_NAME: {
FIELD_NAME: {
ARGUMENT: VALUE,
ARGUMENT: VALUE,...
}
}
}
GET bank/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"sort": [
{
"account_number": {
"order": "desc"
}
}
]
}
- query定義如何查詢
- match_all查詢類型[代表查詢所有],es中可以在query中組合非常多的查詢類型完成復(fù)雜的查詢
- 除了query參數(shù)之外,我們也可以傳遞其他的參數(shù)以改變查詢的結(jié)果,如sort,size
- from+size限定,完成分頁(yè)功能
- sort排序,多字段排序,會(huì)在前序字段相等時(shí)后續(xù)字段內(nèi)部排序,否則以前序?yàn)闇?zhǔn)酿雪。
返回部分字段
GET bank/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"_source": ["age","balance"]
}
match【匹配查詢】
- 基本類型(非字符串),精確匹配
GET bank/_search
{
"query": {
"match": {
"account_number": "20"
}
}
}
match返回account_number=20的
- 字符串,全文檢索
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
}
}
最終查詢出address中包含mill單詞的所有記錄
match當(dāng)搜索字符串類型的時(shí)候,會(huì)進(jìn)行全文檢索,并且每條記錄都有相關(guān)性得分
- 字符串,多個(gè)單詞(分詞+全文檢索)
GET bank/_search
{
"query": {
"match": {
"address": "mill road"
}
}
}
最終查詢出address中包含mill或者road或者mill road的所有記錄遏暴,并給出相關(guān)性得分
match_phrase【短語(yǔ)匹配】
將需要匹配的值當(dāng)成一個(gè)整體單詞(不分詞)進(jìn)行檢索
GET bank/_search
{
"query": {
"match_phrase": {
"address": "mill road"
}
}
}
查出address中包含mill road的所有記錄,并給出相關(guān)性得分
multi_match【多字段匹配】
GET bank/_search
{
"query": {
"multi_match": {
"query": "mill",
"fields": ["state","address"]
}
}
}
state或者address包含mill
bool【復(fù)合查詢】
bool用來(lái)做復(fù)合查詢:
復(fù)合語(yǔ)句可以合并任何的查詢語(yǔ)句,包括復(fù)合語(yǔ)句,這意味著復(fù)合語(yǔ)句可以嵌套,可以表達(dá)非常復(fù)雜的邏輯。
must: 必須達(dá)到must列舉的所有的條件
GET bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "gender": "M" } }
]
}
}
}
should:應(yīng)該達(dá)到should列舉的條件指黎,如果達(dá)到會(huì)增加評(píng)分朋凉,不會(huì)改變查詢的結(jié)果。如果query中只有should且只有一種匹配規(guī)則醋安,那么should的條件就會(huì)被作為默認(rèn)的匹配條件而去改變查詢的結(jié)果杂彭。
GET bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "gender": "M" } }
],
"should": [
{"match": { "address": "lane" }}
]
}
}
}
must_not必須不是指定的情況
GET bank/_search
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "gender": "M" } }
],
"should": [
{"match": { "address": "lane" }}
],
"must_not": [
{"match": { "email": "baluba.com" }}
]
}
}
}
address包含mill,并且gender是M,如果address里面有l(wèi)ane最好不過(guò),但是email必須不包含baluba.com
filter【結(jié)果過(guò)濾】
并不是所有的查詢都需要產(chǎn)生分?jǐn)?shù),特別是哪些僅僅用于"filtering"(過(guò)濾)的文檔墓毒。為了不計(jì)算分?jǐn)?shù),es會(huì)自動(dòng)檢查場(chǎng)景并且優(yōu)化查詢的執(zhí)行亲怠。
GET bank/_search
{
"query": {
"bool": {
"must": [
{"match": { "address": "mill"}}
],
"filter": {
"range": {
"balance": {
"gte": 10000,
"lte": 20000
}
}
}
}
}
}
aggregations(執(zhí)行聚合)
聚合提供了從數(shù)據(jù)中分組和提取數(shù)據(jù)的能力蚁鳖。最簡(jiǎn)單的聚合方法大致等于SQL中的分組和sql中的聚合函數(shù)。
- 在es中赁炎,您有執(zhí)行搜索返回命中結(jié)果醉箕,并且同時(shí)返回聚合的結(jié)果,把一個(gè)響應(yīng)中所有命中結(jié)果分隔開的能力徙垫。
- 這是非常強(qiáng)大且有效的讥裤,您可以執(zhí)行查詢和多個(gè)聚合,并且在一次使用中得到各自的返回結(jié)果姻报,使用一次簡(jiǎn)介和簡(jiǎn)化的API來(lái)避免網(wǎng)絡(luò)往返己英。
搜索address中包含mill的所有人的年齡分布以及平均年齡,但不顯示這些人的詳情
GET bank/_search
{
"query": {
"match": {
"address": "mill"
}
},
"aggs": {
"group_by_state": {
"terms": {
"field": "age"
}
},
"avg_age": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
size:0 不顯示搜索數(shù)據(jù)
aggs:執(zhí)行聚合吴旋。聚合語(yǔ)法如下
"aggs": {
"aggs_name這次聚合的名字损肛,方便展示在結(jié)果集中": {
"AGG_TYPE聚合的類型(avg,term,terms)": {}
}
}
復(fù)雜:
按照年齡聚合,并且請(qǐng)求這些年齡段的這些人的平均薪資
GET bank/account/_search
{
"query": {
"match_all": {}
},
"aggs": {
"age_avg": {
"terms": {
"field": "age",
"size": 1000
},
"aggs": {
"banlances_avg": {
"avg": {
"field": "balance"
}
}
}
}
}
,
"size": 1000
}
Mapping
字段類型
核心類型
-
字符串(String)
- text
- keyword
-
數(shù)字類型
- long
- Integer
- short
- byte
- double
- float
- ...
-
日期類型
- date
-
布爾類型
- boolean
-
二進(jìn)制類型
- binary
-
復(fù)合類型
- 數(shù)組類型
- Array支持不針對(duì)特定的類型
- 對(duì)象類型
- Object用于單JSON對(duì)象
- 嵌套類型
- nested 用于JSON對(duì)象數(shù)組
- 數(shù)組類型
-
地理類型
- 地理坐標(biāo)
- geo_point用于描述經(jīng)緯度坐標(biāo)
- 地理圖形
- geo_shape用于描述復(fù)雜形狀
- 地理坐標(biāo)
-
特定類型
- IP類型
- ip用于描述ipv4和ipv6地址
- 補(bǔ)全類型
- completion提供自動(dòng)完成提示
- 令牌計(jì)數(shù)類型
- token_count用于統(tǒng)計(jì)字符串中的詞條數(shù)量
- 附件類型
- 支持附件如office
- 抽取類型
- 支持特定領(lǐng)域語(yǔ)言的查詢
- IP類型
映射
Mapping是用來(lái)定義一個(gè)文檔,以及他所包含的屬性如何存儲(chǔ)和索引的
哪些字符串應(yīng)該被看做全文本屬性
哪些屬性包含數(shù)字,日期或者地理位置
文檔中的所有屬性是否都能被索引
日期的格式
自定義映射規(guī)則來(lái)執(zhí)行動(dòng)態(tài)添加屬性
查詢mapping信息
GET bank/_mapping
修改mapping信息
需要在創(chuàng)建索引的時(shí)候指定映射
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html
PUT my_index
{
"mappings": {
"user": {
"_all": { "enabled": false },
"properties": {
"title": { "type": "text" },
"name": { "type": "text" },
"age": { "type": "integer" }
}
},
"blogpost": {
"_all": { "enabled": false },
"properties": {
"title": { "type": "text" },
"body": { "type": "text" },
"user_id": {
"type": "keyword"
},
"created": {
"type": "date",
"format": "strict_date_optional_time||epoch_millis"
}
}
}
}
}
分詞
一個(gè) tokenizer(分詞器)接收一個(gè)字符流,將之分割為獨(dú)立的 tokens(詞元荣瑟,通常是獨(dú)立的單詞)治拿,然后輸出 tokens 流。
倒排索引
安裝ik分詞器
測(cè)試分詞器
集群原理
集群安裝
es1配置文件
# 開啟跨域笆焰,為了讓es-head可以訪問(wèn)
http.cors.enabled: true
http.cors.allow-origin: "*"
# 集群的名稱
cluster.name: elasticsearch
# 節(jié)點(diǎn)的名稱
node.name: es1
# 指定該節(jié)點(diǎn)是否有資格被選舉成為master節(jié)點(diǎn)劫谅,默認(rèn)是true,es是默認(rèn)集群中的第一臺(tái)機(jī)器為master嚷掠,如果這臺(tái)機(jī)掛了就會(huì)重新選舉master
node.master: true
# 允許該節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù)(默認(rèn)開啟)
node.data: true
# 允許任何ip訪問(wèn)
network.host: 0.0.0.0
# 通過(guò)這個(gè)ip列表進(jìn)行節(jié)點(diǎn)發(fā)現(xiàn)捏检,我這里配置的是各個(gè)容器的ip
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300","192.168.192.133:9301","192.168.192.133:9302","192.168.192.133:9301"]
#如果沒(méi)有這種設(shè)置,遭受網(wǎng)絡(luò)故障的集群就有可能將集群分成兩個(gè)獨(dú)立的集群 – 導(dǎo)致腦裂 - 這將導(dǎo)致數(shù)據(jù)丟失
discovery.zen.minimum_master_nodes: 2
es2-es3配置文件
-----------------------es2-----------------------
http.cors.enabled: true
http.cors.allow-origin: "*"
cluster.name: elasticsearch
node.name: es2
network.host: 0.0.0.0
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["127.0.0.1","172.17.0.2","172.17.0.4","172.17.0.5"]
discovery.zen.minimum_master_nodes: 2
-----------------------es3-----------------------
http.cors.enabled: true
http.cors.allow-origin: "*"
cluster.name: elasticsearch
node.name: es3
network.host: 0.0.0.0
node.master: true
node.data: true
discovery.zen.ping.unicast.hosts: ["127.0.0.1","172.17.0.2","172.17.0.4","172.17.0.5"]
discovery.zen.minimum_master_nodes: 2
集群化實(shí)例啟動(dòng)
實(shí)例一:
docker run --name es1 -p 9200:9200 -p 9300:9300 \
-e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data -d elasticsearch:5.6.11
實(shí)例二:
docker run --name es2 -p 9201:9200 -p 9301:9300 \
-e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
-v /mydata/elasticsearch2/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch2/data:/usr/share/elasticsearch/data -d elasticsearch:5.6.11
實(shí)例三:
docker run --name es3 -p 9202:9200 -p 9302:9300 \
-e ES_JAVA_OPTS="-Xms256m -Xmx256m" \
-v /mydata/elasticsearch3/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch3/data:/usr/share/elasticsearch/data -d elasticsearch:5.6.11
需要修改linux的進(jìn)程數(shù)限制
vi /etc/sysctl.conf
vm.max_map_count=655360
sysctl -p
集群、分片原理
單節(jié)點(diǎn)
一個(gè)運(yùn)行中的 Elasticsearch 實(shí)例稱為一個(gè) 節(jié)點(diǎn)
集群
由一個(gè)或者多個(gè)擁有相同 cluster.name 配置的節(jié)點(diǎn)組成不皆, 它們共同承擔(dān)數(shù)據(jù)和負(fù)載的壓力
- 有節(jié)點(diǎn)加入集群中或者從集群中移除節(jié)點(diǎn)時(shí)贯城,集群將會(huì)重新平均分布所有的數(shù)據(jù)。
- 當(dāng)一個(gè)節(jié)點(diǎn)被選舉成為 主 節(jié)點(diǎn)時(shí)霹娄, 它將負(fù)責(zé)管理集群范圍內(nèi)的所有變更能犯,例如增加、刪除索引项棠,或者增加悲雳、刪除節(jié)點(diǎn)等。
- 而主節(jié)點(diǎn)并不需要涉及到文檔級(jí)別的變更和搜索等操作香追,所以當(dāng)集群只擁有一個(gè)主節(jié)點(diǎn)的情況下合瓢,即使流量的增加它也不會(huì)成為瓶頸。
- 任何節(jié)點(diǎn)都可以成為主節(jié)點(diǎn)透典。
- 作為用戶晴楔,我們可以將請(qǐng)求發(fā)送到 集群中的任何節(jié)點(diǎn) 顿苇,包括主節(jié)點(diǎn)。 每個(gè)節(jié)點(diǎn)都知道任意文檔所處的位置税弃,并且能夠?qū)⑽覀兊恼?qǐng)求直接轉(zhuǎn)發(fā)到存儲(chǔ)我們所需文檔的節(jié)點(diǎn)纪岁。
集群健康
- green(所有的主分片和副本分片都正常運(yùn)行)
- yellow(所有的主分片都正常運(yùn)行,單不是所有的副本分片都正常運(yùn)行)
- red(有主分片沒(méi)有能正常運(yùn)行)
添加故障轉(zhuǎn)移
- 當(dāng)集群中只有一個(gè)節(jié)點(diǎn)在運(yùn)行時(shí),意味著會(huì)有一個(gè)單點(diǎn)故障問(wèn)題--沒(méi)有冗余则果。只需要再啟動(dòng)一個(gè)節(jié)點(diǎn)即可防止數(shù)據(jù)丟失幔翰。
- 當(dāng)?shù)诙€(gè)節(jié)點(diǎn)加入到集群后,3個(gè)副本分片將會(huì)分配到這個(gè)節(jié)點(diǎn)上西壮,當(dāng)集群中的任何一個(gè)節(jié)點(diǎn)出現(xiàn)問(wèn)題的時(shí)候遗增,數(shù)據(jù)都完好無(wú)損。
- 所有新近被索引的文檔都將會(huì)保存到主分片上款青,然后被并行復(fù)制到對(duì)應(yīng)的副本分片上做修,這就保證了我們既可以從主分片又可以從副本分片獲得文檔。
水平擴(kuò)容
擁有三個(gè)節(jié)點(diǎn)的集群--為了分散負(fù)載而對(duì)分片進(jìn)行重新分配
- 讀操作,可以同時(shí)被主分片或者副本分片所處理,所有當(dāng)你擁有越多的副本分片時(shí),也將擁有越高的吞吐量
- 運(yùn)行中的集群上是可以動(dòng)態(tài)調(diào)整副本分片的數(shù)目的,我們可以按需伸縮集群抡草∈渭埃可以把副本數(shù)從默認(rèn)的1增加到2
PUT /blogs/_settings
{
"number_of_replicas" : 2
}
應(yīng)對(duì)故障
- 我們關(guān)閉的節(jié)點(diǎn)是一個(gè)主節(jié)點(diǎn)。而集群必須擁有一個(gè)主節(jié)點(diǎn)來(lái)保證正常工作康震,所以發(fā)生的第一件事情就是選舉一個(gè)新的主節(jié)點(diǎn)
- 在我們關(guān)閉Node1的同時(shí)也失去了主分片1和2,并且在缺失主分片的時(shí)候索引頁(yè)不能正常工作
- 幸運(yùn)的是,在其他節(jié)點(diǎn)上存在著這兩個(gè)主分片的完整副本,所以新的主節(jié)點(diǎn)立即將其他節(jié)點(diǎn)上對(duì)應(yīng)的副本分片提升為主分片,這個(gè)提升的過(guò)程是瞬間發(fā)生的
腦裂問(wèn)題
腦裂問(wèn)題是什么?
同一個(gè)集群中的不同節(jié)點(diǎn)燎含,對(duì)于集群的狀態(tài),有了不一樣的理解签杈。集群中不同的節(jié)點(diǎn)對(duì)于master的選擇出現(xiàn)了分歧瘫镇,出現(xiàn)了多個(gè)master競(jìng)爭(zhēng)鼎兽,導(dǎo)致主分片和副本的識(shí)別也發(fā)生了分歧答姥,對(duì)一些分歧中的分片標(biāo)識(shí)為了壞片。
可能的原因
- 網(wǎng)絡(luò)問(wèn)題:集群間的網(wǎng)絡(luò)延遲導(dǎo)致一些節(jié)點(diǎn)訪問(wèn)不到master谚咬,認(rèn)為master掛掉了從而選舉出新的master鹦付,并對(duì)master上的分片和副本標(biāo)紅,分配新的主分片
- 節(jié)點(diǎn)負(fù)載:主節(jié)點(diǎn)的角色既為master又為data择卦,訪問(wèn)量較大時(shí)可能會(huì)導(dǎo)致ES停止響應(yīng)造成大面積延遲敲长,此時(shí)其他節(jié)點(diǎn)得不到主節(jié)點(diǎn)的響應(yīng)認(rèn)為主節(jié)點(diǎn)掛掉了,會(huì)重新選取主節(jié)點(diǎn)秉继。
- 內(nèi)存回收:data節(jié)點(diǎn)上的ES進(jìn)程占用的內(nèi)存較大祈噪,引發(fā)JVM的大規(guī)模內(nèi)存回收,造成ES進(jìn)程失去響應(yīng)尚辑。
解決方案
減少誤判 :調(diào)大節(jié)點(diǎn)的響應(yīng)時(shí)間,默認(rèn)為3秒,調(diào)至6秒
-
選舉觸發(fā) discovery.zen.minimum_master_nodes:(默認(rèn)是1)
這個(gè)參數(shù)控制的是辑鲤,一個(gè)節(jié)點(diǎn)需要看到的具有master節(jié)點(diǎn)資格的最小數(shù)量,然后才能在集群中做操作杠茬。官方的推薦值是(N/2)+1月褥,其中N是具有master資格的節(jié)點(diǎn)的數(shù)量(我們的情況是3弛随,因此這個(gè)參數(shù)設(shè)置為2,但對(duì)于只有2個(gè)節(jié)點(diǎn)的情況宁赤,設(shè)置為2就有些問(wèn)題了舀透,一個(gè)節(jié)點(diǎn)DOWN掉后,你肯定連不上2臺(tái)服務(wù)器了决左,這點(diǎn)需要注意)愕够。
增大該參數(shù),當(dāng)該值為2時(shí)佛猛,我們可以設(shè)置master的數(shù)量為3链烈,這樣,掛掉一臺(tái)挚躯,其他兩臺(tái)都認(rèn)為主節(jié)點(diǎn)掛掉了强衡,才進(jìn)行主節(jié)點(diǎn)選舉。
角色分離:即master節(jié)點(diǎn)與data節(jié)點(diǎn)分離码荔,限制角色
主節(jié)點(diǎn)配置
node.master: true ##作為master節(jié)點(diǎn)
node.data: false ##不作為存儲(chǔ)數(shù)據(jù)節(jié)點(diǎn)
從節(jié)點(diǎn)配置為:
node.master: false
node.data: true
實(shí)際的解決方案
三臺(tái)物理機(jī)上搭建六個(gè)ES節(jié)點(diǎn),三個(gè)data節(jié)點(diǎn),三個(gè)master節(jié)點(diǎn)
分析
- 角色分離后漩勤,當(dāng)集群中某一臺(tái)節(jié)點(diǎn)的master進(jìn)程意外掛掉了,或者因負(fù)載過(guò)高停止響應(yīng)缩搅,終止掉的master進(jìn)程很大程度上不會(huì)影響到同一臺(tái)機(jī)器上的data進(jìn)程越败,即減小了數(shù)據(jù)丟失的可能性。
- discovery.zen.minimum_master_nodes設(shè)置成了2(3/2+1)當(dāng)集群中兩臺(tái)機(jī)器都掛了或者并沒(méi)有掛掉而是處于高負(fù)載的假死狀態(tài)時(shí)硼瓣,僅剩一臺(tái)備選master節(jié)點(diǎn)究飞,小于2無(wú)法觸發(fā)選舉行為,集群無(wú)法使用堂鲤,不會(huì)造成分片混亂的情況亿傅。
以上的解決方法只能是減緩這種現(xiàn)象的發(fā)生,并沒(méi)有從根本上杜絕瘟栖,但是畢竟是有幫助的
JestClient
SpringBoot整合
<!-- https://mvnrepository.com/artifact/io.searchbox/jest -->
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>5.3.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.11</version>
</dependency>
配置
spring:
elasticsearch:
jest:
uris: http://192.168.159.130:9200, http://192.168.159.130:9201
username: elastic
password: 123456
read-timeout: 20000 #讀取超時(shí)
connection-timeout: 20000 #連接超時(shí)
使用
@Autowired
JestClient jestClient;
public void search(){
//先定義一個(gè)action(增刪改查)葵擎,例如search
Search search = new Search.Builder(query).addIndex(index).build();
//執(zhí)行action,返回結(jié)果
SearchResult result = jestClient.execute(search);
//處理結(jié)果集
...........省略
}