1 Elasticsearch 簡(jiǎn)介
1.1 什么是 Elasticsearch铸史?
Elasticsearch是一個(gè)基于 Apache Lucene 的開(kāi)源搜索引擎度陆。無(wú)論在開(kāi)源還是專有領(lǐng)域袖外,Lucene 可以被認(rèn)為是迄今為止最先進(jìn)、性能最好的、功能最全的搜索引擎庫(kù)鲤脏。
特點(diǎn):
- 分布式的實(shí)時(shí)文件存儲(chǔ)秸歧,每個(gè)字段都被索引并可被搜索
- 分布式的實(shí)時(shí)分析搜索引擎--做不規(guī)則查詢
- 可以擴(kuò)展到上百臺(tái)服務(wù)器厨姚,處理PB級(jí)結(jié)構(gòu)化或非結(jié)構(gòu)化數(shù)據(jù)
Elasticsearch 也使用 Java 開(kāi)發(fā)并使用 Lucene 作為其核心來(lái)實(shí)現(xiàn)所有索引和搜索的功能,但是它的目的是通過(guò)簡(jiǎn)單的 RESTful API 來(lái)隱藏 Lucene 的復(fù)雜性键菱,從而讓全文搜索變得簡(jiǎn)單谬墙。
1.2 Elasticsearch 應(yīng)用場(chǎng)景
- 全文檢索(全部字段)
- 模糊查詢(搜索)
- 數(shù)據(jù)分析(提供分析語(yǔ)法,例如聚合)
1.3 Elasticsearch 使用案例
- 2013 年初经备,GitHub 拋棄了 Solr拭抬,采取 ElasticSearch 來(lái)做 PB 級(jí)的搜索:GitHub 使用 ElasticSearch 搜索 20TB 的數(shù)據(jù),包括 13億文件和 1300 億行代碼
- 維基百科啟動(dòng)以 Elasticsearch 為基礎(chǔ)的核心搜索架構(gòu) SoundCloud:SoundCloud 使用 ElasticSearch 為 1.8 億用戶提供即時(shí)而精準(zhǔn)的音樂(lè)搜索服務(wù)
- 百度目前廣泛使用 ElasticSearch 作為文本數(shù)據(jù)分析侵蒙,采集百度所有服務(wù)器上的各類指標(biāo)數(shù)據(jù)及用戶自定義數(shù)據(jù)玖喘,通過(guò)對(duì)各種數(shù)據(jù)進(jìn)行多維分析展示,輔助定位分析實(shí)例異衬⒅荆或業(yè)務(wù)層面異常:目前覆蓋百度內(nèi)部 20 多個(gè)業(yè)務(wù)線(包括 casio累奈、云分析、網(wǎng)盟急但、預(yù)測(cè)澎媒、文庫(kù)、直達(dá)號(hào)波桩、錢(qián)包戒努、風(fēng)控等),單集群最大 100 臺(tái)機(jī)器,200 個(gè) ES 節(jié)點(diǎn)储玫,每天導(dǎo)入 30TB+ 數(shù)據(jù)
- 新浪使用 ES 分析處理 32 億條實(shí)時(shí)日志
- 阿里使用 ES 構(gòu)建挖財(cái)自己的日志采集和分析體系
1.4 同類產(chǎn)品
Solr侍筛、ElasticSearch、Hermes:
- Solr撒穷、ES
- 源自搜索引擎富雅,側(cè)重搜索與全文檢索
- 數(shù)據(jù)規(guī)模從幾百萬(wàn)到千萬(wàn)不等望几,數(shù)據(jù)量過(guò)億的集群特別少
- 有可能存在個(gè)別系統(tǒng)數(shù)據(jù)量過(guò)億必指,但這并不是普遍現(xiàn)象
- Hermes
- 一個(gè)基于大索引技術(shù)的海量數(shù)據(jù)實(shí)時(shí)檢索分析平臺(tái)冯乘,側(cè)重?cái)?shù)據(jù)分析
- 數(shù)據(jù)規(guī)模從幾億到萬(wàn)億不等,最小的表也是千萬(wàn)級(jí)別
- 在 騰訊 17 臺(tái) TS5 機(jī)器蛤奥,就可以處理每天 450 億的數(shù)據(jù)(每條數(shù)據(jù) 1kb 左右)佳镜,數(shù)據(jù)可以保存一個(gè)月之久
Solr、ES 區(qū)別:
- Solr 利用 Zookeeper 進(jìn)行分布式管理凡桥,而 Elasticsearch 自身帶有分布式協(xié)調(diào)管理功能
- Solr 支持更多格式的數(shù)據(jù)蟀伸,而 Elasticsearch 僅支持 JSON 文件格式
- Solr 官方提供的功能更多,而 Elasticsearch 本身更注重于核心功能缅刽,高級(jí)功能多有第三方插件提供
- Solr 在傳統(tǒng)的搜索應(yīng)用中表現(xiàn)好于 Elasticsearch啊掏,但在處理實(shí)時(shí)搜索應(yīng)用時(shí)效率明顯低于 Elasticsearch-----附近的人
2 Elasticsearch 安裝部署
2.1 單機(jī)部署
解壓
[djm@hadoop102 software]$ tar -vzxf elasticsearch-6.3.1.tar.gz -C /opt/module/
設(shè)置訪問(wèn) IP
vim config/elasticsearch.yml
network.host: 0.0.0.0
[max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
sysctl -w vm.max_map_count=262144
啟動(dòng)和停止
# 前臺(tái)啟動(dòng)
[djm@hadoop102 bin]$ ./elasticsearch
# 后臺(tái)啟動(dòng)
[djm@hadoop102 bin]$ ./elasticsearch -d
2.2 集群部署
修改 elasticserach.yml 文件
#集群名稱
cluster.name: my-application
#節(jié)點(diǎn)名稱(不能重復(fù))
node.name: node-2
#指定了該節(jié)點(diǎn)可能成為 master 節(jié)點(diǎn),還可以是數(shù)據(jù)節(jié)點(diǎn)
node.master: true
node.data: true
#數(shù)據(jù)的默認(rèn)存放路徑(自定義)
path.data: /opt/module/elasticsearch-6.3.1/data
#日志的默認(rèn)存放路徑
path.logs: /opt/module/elasticsearch-6.3.1/logs
#允許外網(wǎng)訪問(wèn)
network.host: 0.0.0.0
#對(duì)外提供服務(wù)的端口
http.port: 9200
#9300為集群服務(wù)的端口
transport.tcp.port: 9300
#集群個(gè)節(jié)點(diǎn)IP地址拷恨,也可以使用域名脖律,需要各節(jié)點(diǎn)能夠解析
discovery.zen.ping.unicast.hosts: ["hadoop102", "hadoop103", "hadoop104"]
#為了避免腦裂,集群節(jié)點(diǎn)數(shù)最少為 半數(shù)+1
discovery.zen.minimum_master_nodes: 2
解壓 head腕侄、node
[djm@hadoop102 ~]$ tar -zxvf node-v9.9.0-linux-x64.tar.gz
[djm@hadoop102 ~]$ unzip elasticsearch-head-master.zip
配置 Node 環(huán)境變量
#NODE_HOME
export NODE_HOME=/opt/module/node-v9.9.0
export PATH=$PATH:$NODE_HOME/bin
測(cè)試環(huán)境變量
[djm@hadoop102 ~]$ node -v
[djm@hadoop102 ~]$ npm -v
安裝 grunt小泉,進(jìn)入到 head 目錄
[djm@hadoop102 elasticsearch-head-master]$ npm install -g grunt-cli
[djm@hadoop102 elasticsearch-head-master]$ npm install
修改 elasticsearch.yml 文件,添加如下內(nèi)容:
http.cors.enabled: true
http.cors.allow-origin: "*"
修改 Gruntfile.js冕杠,找到 connect 屬性微姊,新增 hostname: ’*’
connect: {
server: {
options: {
hostname: '*',
port: 9100,
base: '.',
keepalive: true
}
}
}
啟動(dòng)
# 前臺(tái)啟動(dòng)
[djm@hadoop102 elasticsearch-head-master]$ grunt server
# 后臺(tái)啟動(dòng)
[djm@hadoop102 elasticsearch-head-master]$ nohup grunt server &exit
2.3 Elasticsearch 操作工具
- PostMan
- Linux 命令行
- Kibana 的 Dev Tools
- Cerebro 插件
3 Elasticsearch API
3.1 Mapping
定義數(shù)據(jù)庫(kù)中的表的結(jié)構(gòu)的定義,通過(guò) mapping 來(lái)控制索引存儲(chǔ)數(shù)據(jù)的設(shè)置
- 定義Index下的字段名(Field Name)
- 定義字段的類型分预,比如數(shù)值型兢交、字符串型、布爾型等
- 定義倒排索引相關(guān)的配置笼痹,比如 documentId配喳、記錄 position、打分等
獲取 mapping
GET /djm/_mapping
Dynamic Mapping
JSON類型 | es 類型 |
---|---|
null | 忽略 |
boolean | boolean |
浮點(diǎn)類型 | float |
整數(shù) | long |
object | object |
array | 由第一個(gè)非 null 值的類型決定 |
string | 匹配為日期設(shè)為 date 類型(默認(rèn)開(kāi)啟)凳干,數(shù)字設(shè)為 float 或 long 類型(默認(rèn)關(guān)閉)晴裹,設(shè)為 text 類型,并附帶keyword的子字段 |
mapping 中的字段類型一旦設(shè)定后救赐,禁止修改
dynamic設(shè)置
- true:允許自動(dòng)新增字段(默認(rèn)的配置)
- False:不允許自動(dòng)新增字段涧团,但是文檔可以正常寫(xiě)入,無(wú)法對(duì)字段進(jìn)行查詢操作
- strict:文檔不能寫(xiě)入(如果寫(xiě)入會(huì)報(bào)錯(cuò))
PUT my_index
{
"mappings": {
"doc": {
"dynamic": false,
"properties": {
"user": {
"properties": {
"name": {
"type": "text"
},
"social_networks": {
"dynamic": true,
"properties": {}
}
}
}
}
}
}
}
copy_to 將該字段的值復(fù)制到目標(biāo)字段,實(shí)現(xiàn) _all 的作用泌绣,不會(huì)出現(xiàn)在 _source 中钮追,只用來(lái)搜索
PUT my_index
{
"mappings": {
"doc": {
"properties": {
"frist_name": {
"type": "text",
"copy_to": "full_name"
},
"last_name": {
"type": "text",
"copy_to": "full_name"
},
"full_name": {
"type": "text"
}
}
}
}
}
Index 屬性,控制當(dāng)前字段是否可以被索引阿迈,默認(rèn)為 true
PUT my_index
{
"mappings": {
"doc": {
"properties": {
"cookie": {
"type": "text",
"index": false
}
}
}
}
}
Index_options 用于控制倒排索引記錄的內(nèi)容
- docs:只記錄 docid
- freqs:記錄 docid 和 term frequencies(詞頻)
- position:記錄 docid元媚、term frequencies、term position
- Offsets:記錄 docid仿滔、term frequencies惠毁、term position犹芹、character offsets
3.2 Document
索引一個(gè)文檔
PUT {index}/{type}/{id}
{
"": ""
}
使用自己的 ID
PUT /{index}/{type}/{id}
{
"field": "value",
...
}
例如我們的索引叫做 website崎页,類型叫做 blog,我們選擇的 ID 是123腰埂,那么這個(gè)索引請(qǐng)求就像這樣:
PUT /website/blog/123
{
"title": "My first blog entry",
"text": "Just trying this out...",
"date": "2014/01/01"
}
響應(yīng)指出請(qǐng)求的索引已經(jīng)被成功創(chuàng)建飒焦,這個(gè)索引中包含_index、_type和_id元數(shù)據(jù)屿笼,以及一個(gè)新元素:_version
每個(gè)文檔都有版本號(hào)牺荠,每當(dāng)文檔發(fā)生變化時(shí)都會(huì)使_version發(fā)生變化
自增 ID
POST /website/blog/
{
"title": "My second blog entry",
"text": "Still trying this out...",
"date": "2014/01/01"
}
檢索文檔
GET /website/blog/123?pretty
- pretty:表示美化 json
檢索文檔的一部分
#_source只包含title、text字段
GET /website/blog/123?_source=title,text
#僅返回_source
GET /website/blog/123/_source
檢索多個(gè)文檔
POST /_mget
{
"docs": [
{
"_index": "website",
"_type": "blog",
"_id": 2
},
{
"_index": "website",
"_type": "pageviews",
"_id": 1,
"_source": "views"
}
]
}
如果檢索的文檔在同一個(gè) _index 中(甚至在同一個(gè) _type 中)驴一,可以在 URL 中定義一個(gè)默認(rèn)的 _index 或者_(dá)index/_type
POST /website/blog/_mget
{
"ids": [
"2",
"1"
]
}
更新文檔
POST /website/blog/123
{
"title": "My first blog entry",
"text": "I am starting to get the hang of this...",
"date": "2014/01/02"
}
局部更新
POST /website/blog/123/_update
{
"doc": {
"tags": [
"testing"
],
"views": 0
}
}
刪除文檔
DELETE /website/blog/123
批量插入
POST test_search_index/doc/_bulk
{
"index": {
"_id": 1
}
}
{
"username": "alfred way",
"job": "java engineer",
"age": 18,
"birth": "1991-12-15",
"isMarried": false
}
{
"index": {
"_id": 2
}
}
{
"username": "alfred",
"job": "java senior engineer and java specialist",
"age": 28,
"birth": "1980-05-07",
"isMarried": true
}
{
"index": {
"_id": 3
}
}
{
"username": "lee",
"job": "java and ruby engineer",
"age": 22,
"birth": "1985-08-07",
"isMarried": false
}
{
"index": {
"_id": 4
}
}
{
"username": "lee junior way",
"job": "ruby engineer",
"age": 23,
"birth": "1986-08-07",
"isMarried": false
}
3.3 Search API(URI)
GET /_search #查詢所有索引文檔
GET /my_index/_search #查詢指定索引文檔
GET /my_index1,my_index2/_search #多索引查詢
GET /my_index/_search?q=user:alfred #指定字段查詢
GET /my_index/_search?q=keyword&df=user&sort=age:asc&from=4&size=10&timeout=1s
- q:指定查詢的語(yǔ)句
- df:指定默認(rèn)查詢的字段休雌,如果不指定,查詢?nèi)孔侄?/li>
- sort:排序
- timeout:指定超時(shí)時(shí)間肝断,默認(rèn)不超時(shí)
- form杈曲、size:用于分頁(yè)
term 與 phrase
- term 相當(dāng)于單詞查詢
- phrase 相當(dāng)于詞語(yǔ)查詢
泛查詢
- 即不指定默認(rèn)查詢字段的查詢
指定字段
- name:alfread
Group
- 使用括號(hào)指定匹配的規(guī)則
布爾操作符
- AND(&&)、OR(||)胸懈、NOT(!)担扑,例如 name:(tom NOT lee) 表示 name 字段中可以包含 tom 但一定不包含 lee
- +、-分別對(duì)應(yīng) must 和 must_not趣钱,例如 name:(tom +lee -alfred) 表示 name 字段中涌献,一定包含 lee,一定不包含 alfred首有,可以包含 tom
范圍查詢
- age:[1 TO 10] #1<=age<=10
- age:[1 TO 10} #1<=age<10
- age:[1 TO ] #1<=age
- age:[* TO 10] #age<=10
- gae:>=1 #age>=1
- age:(>=1&&<=10) #1<=age<=10
- age:(+>=1 +<=10) #1<=age<=10
通配符查詢
- ?:1 個(gè)字符燕垃,例如 name:t?m
- *:0 或多個(gè)字符,例如 name:tom*
正則表達(dá)式
- name:/[mb]oat/
模糊匹配 fuzzy query
- name:roam~1 匹配與 roam 差一個(gè)字母的詞井联,比如 from卜壕、roams
近似度查詢 proximity search
- “fox quick”~5 以 term 為單位進(jìn)行差異比較,比如 qucik fox低矮、qucik brown for
3.4 Search API(Request Body Search)
Match Query 對(duì)字段作全文檢索印叁,最基本和常用的查詢類型
GET test_search_index/_search
{
"profile": true,
"query": {
"match": {
"username": "alfred way"
}
}
}
通過(guò) operator 參數(shù)可以控制單詞間的匹配關(guān)系,可選項(xiàng)為 or 和 and
GET test_search_index/_search
{
"query": {
"match": {
"username": {
"query": "alfred way",
"operator": "and"
}
}
}
}
4 Elasticsearch 數(shù)據(jù)結(jié)構(gòu)
核心數(shù)據(jù)類型
- 字符串型:text、keyword
- 數(shù)值型:long轮蜕、integer昨悼、short、byte跃洛、double率触、float、half_float汇竭、scaled_float
- 日期類型:date
- 布爾類型:boolean
- 二進(jìn)制類型:binary
- 范圍類型:integer_range葱蝗、float_range、long_range细燎、double_range两曼、date_range
復(fù)雜數(shù)據(jù)類型
- 數(shù)組類型:array
- 對(duì)象類型:object
- 嵌套類型:nested object
地理位置數(shù)據(jù)類型
- geo_point(點(diǎn))
- geo_shape(形狀)
專用類型
- 記錄IP地址:ip
- 實(shí)現(xiàn)自動(dòng)補(bǔ)全 completion
- 記錄分詞數(shù):token_count
1、創(chuàng)建 mapping
PUT my_index
{
"mappings": {
"doc": {
"properties": {
"username": {
"type": "text",
"fields": {
"pinyin": {
"type": "text"
}
}
}
}
}
}
}
2玻驻、創(chuàng)建文檔
PUT my_index1/doc/1
{
"username": "haha heihei"
}
3悼凑、查詢
GET my_index/_search
{
"query": {
"match": {
"username.pinyin": "haha"
}
}
}
Dynamic Mapping
PUT /test_index/doc/1
{
"username": "alfred",
"age": 1
}
age自動(dòng)識(shí)別為long類型,username識(shí)別為text類型
PUT test_index/doc/1
{
"username": "samualz",
"age": 14,
"birth": "1991-12-15",
"year": 18,
"tags": [
"boy",
"fashion"
],
"money": "100.1"
}
birth自動(dòng)識(shí)別為日期璧瞬。户辫。。嗤锉。
自定義日期識(shí)別格式
PUT my_index
{
"mappings": {
"doc": {
"dynamic_date_formats": [
"yyyy-MM-dd",
"yyyy/MM/dd"
]
}
}
}
關(guān)閉日期自動(dòng)識(shí)別
PUT my_index
{
"mappings": {
"doc": {
"date_detection": false
}
}
}
字符串是數(shù)字時(shí)渔欢,默認(rèn)不會(huì)自動(dòng)識(shí)別為整形,因?yàn)樽址谐霈F(xiàn)數(shù)字時(shí)完全合理的瘟忱,Numeric_datection 可以開(kāi)啟字符串中數(shù)字的自動(dòng)識(shí)別
PUT my_index
{
"mappings": {
"doc": {
"numeric_datection": true
}
}
}
5 Elasticsearch 原理
5.1 Elasticsearch 數(shù)據(jù)存儲(chǔ)
5.1.1 Elasticsearch 存儲(chǔ)方式
面向文檔:
Elasticsearch 是面向文檔的奥额,這意味著它可以存儲(chǔ)整個(gè)對(duì)象或文檔,它在存儲(chǔ)的時(shí)候還會(huì)對(duì)文檔進(jìn)行索引酷誓,使文檔的內(nèi)容可以被搜索披坏,在 Elasticsearch 中,可以對(duì)文檔進(jìn)行索引盐数、搜索棒拂、排序、過(guò)濾玫氢,這就是 Elasticsearch 能夠執(zhí)行復(fù)雜的全文檢索的原因帚屉。
JSON:
Elasticsearch 使用 JSON,作為文檔序列化格式漾峡,JSON 目前已成為 NoSQL 領(lǐng)域的標(biāo)準(zhǔn)格式攻旦,簡(jiǎn)潔容易閱讀,并且對(duì) JSON 做索引比在表結(jié)構(gòu)中做索引容易的多生逸。
5.1.2 Elasticsearch 存儲(chǔ)結(jié)構(gòu)
[圖片上傳失敗...(image-575404-1572113601393)]
POST djm/doc
{
"name": "zhangsan",
"age": 10
}
- _index:文檔所在索引名稱
- _type:文檔所在類型名稱
- _id:文檔唯一id
- _uid:組合id牢屋,由_type和_id組成(6.x后且预,_type不再起作用,同-_id)
- _source:文檔的原始Json數(shù)據(jù)烙无,包括每個(gè)字段的內(nèi)容
- _all:將所有字段內(nèi)容整合起來(lái)锋谐,默認(rèn)禁用(用于對(duì)所有字段內(nèi)容檢索)
名稱解釋:
1、索引 Index
- 一個(gè) Index 就是一個(gè)擁有幾分相似特征的 document 的集合
- 一個(gè) Index 包含很多文檔截酷,一個(gè) Index 就代表了一類 document
- 比如說(shuō)建立一個(gè) productIndex涮拗,里面可能存放了所有的商品數(shù)據(jù),所有的 productDocument
2迂苛、類型 type
- 相當(dāng)于數(shù)據(jù)表
3三热、字段 field
- 相當(dāng)于數(shù)據(jù)表的字段
4、文檔 document
- 一個(gè)文檔是一個(gè)可被索引的基本信息單元
5.2 Elasticsearch 搜索原理
5.2.1 正排索引和倒排索引
正排索引:記錄文檔Id到文檔內(nèi)容三幻、單詞的關(guān)聯(lián)關(guān)系
倒排索引:記錄單詞到文檔id的關(guān)聯(lián)關(guān)系
5.2.2 分詞
分詞是指將文本轉(zhuǎn)換成一系列單詞(term or token)的過(guò)程就漾,也可以叫做文本分析
Elasticsearch 自帶的分詞器
分詞器(Analyzer) | 特點(diǎn) |
---|---|
Standard(es默認(rèn)) | 支持多語(yǔ)言,按詞切分并做小寫(xiě)處理 |
Simple | 按照非字母切分赌髓,小寫(xiě)處理 |
Whitespace | 按照空格來(lái)切分 |
Stop | 去除語(yǔ)氣助詞从藤,如the催跪、an锁蠕、的、這等 |
Keyword | 不分詞 |
Pattern | 正則分詞懊蒸,默認(rèn)\w+,即非字詞符號(hào)做分割符 |
Language | 常見(jiàn)語(yǔ)言的分詞器(30+) |
5.2.3 IK 分詞器
將 ik 解壓到 elasticsearch-6.3.1\plugins 并重命名為 analysis-ik荣倾,即可加載 ik 分詞器
IK 提供了兩個(gè)分詞算法 ik_smart 、ik_max_word骑丸,其中 ik_smart 為最少切分舌仍,ik_max_word 為最細(xì)粒度劃分
#Request
POST _analyze
{
"tokenizer": "ik_smart",
"text": "我是程序員"
}
#Response
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "是",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 1
},
{
"token": "程序員",
"start_offset": 2,
"end_offset": 5,
"type": "CN_WORD",
"position": 2
}
]
}
#Request
POST _analyze
{
"tokenizer": "ik_max_word",
"text": "我是程序員"
}
#Response
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "是",
"start_offset": 1,
"end_offset": 2,
"type": "CN_CHAR",
"position": 1
},
{
"token": "程序員",
"start_offset": 2,
"end_offset": 5,
"type": "CN_WORD",
"position": 2
},
{
"token": "程序",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 3
},
{
"token": "員",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 4
}
]
}
5.3 集群操作原理
一個(gè)節(jié)點(diǎn)就是一個(gè) Elasticsearch 實(shí)例,而一個(gè)集群是由多個(gè)節(jié)點(diǎn)組成通危,它們具有相同的集群名稱铸豁,它們協(xié)同工作,分享數(shù)據(jù)和負(fù)載菊碟,當(dāng)加入新的節(jié)點(diǎn)或者刪除一個(gè)節(jié)點(diǎn)時(shí)节芥,集群就會(huì)感知到,并平衡數(shù)據(jù)
5.3.1 屬于介紹
節(jié)點(diǎn) node
- 一個(gè)節(jié)點(diǎn)是集群中的一個(gè)服務(wù)器逆害,作為集群的一部分头镊,它存儲(chǔ)數(shù)據(jù),參與集群的索引和搜索
- 一個(gè)節(jié)點(diǎn)也有一個(gè)名字標(biāo)識(shí)魄幕,默認(rèn)是一個(gè)隨機(jī)的漫威角色的名字相艇,在啟動(dòng)的時(shí)候被確定
- 一個(gè)節(jié)點(diǎn)可以通過(guò)配置集群名字的方式加入集群,默認(rèn)所有節(jié)點(diǎn)都會(huì)被加入到 ElasticSearch 集群
分片和復(fù)制 shards & replias
- 一個(gè)索引可以存儲(chǔ)超出單個(gè)結(jié)點(diǎn)硬件限制的大量數(shù)據(jù)纯陨;比如坛芽,一個(gè)具有 10 億文檔的索引占據(jù) 1TB 的磁盤(pán)空間留储,而任一節(jié)點(diǎn)都沒(méi)有這樣大的磁盤(pán)空間,或者單個(gè)節(jié)點(diǎn)處理搜索請(qǐng)求咙轩,響應(yīng)太慢欲鹏, 為了解決這個(gè)問(wèn)題,es 提供了將索引劃分成多份的能力臭墨,這些份就叫做分片
- 在一個(gè)網(wǎng)絡(luò)/云的環(huán)境里赔嚎,失敗隨時(shí)都可能發(fā)生,在某個(gè)分片/節(jié)點(diǎn)不知怎么的就處于離線狀態(tài)胧弛,或者由于任何原因消失了尤误,這種情況下,有一個(gè)故障轉(zhuǎn)移機(jī)制是非常有用并且是強(qiáng)烈推薦的结缚,為此损晤,es 允許你創(chuàng)建分片的一份或多份拷貝,這些拷貝叫做復(fù)制分片红竭,或者直接叫復(fù)制
集群健康有三種狀態(tài):
顏色 | 意義 |
---|---|
green | 所有主要分片和復(fù)制分片都可用 |
yellow | 所有主要分片可用尤勋,但不是所有復(fù)制分片都可用 |
red | 不是所有的主要分片都可用 |
故障轉(zhuǎn)移
- 在單一節(jié)點(diǎn)上運(yùn)行意味著有單點(diǎn)故障的風(fēng)險(xiǎn)——沒(méi)有數(shù)據(jù)備份,幸運(yùn)的是茵宪,要防止單點(diǎn)故障最冰,我們唯一需要做的就是啟動(dòng)另一個(gè)節(jié)點(diǎn)
- 第二個(gè)節(jié)點(diǎn)已經(jīng)加入集群,三個(gè)復(fù)制分片也已經(jīng)被分配了——分別對(duì)應(yīng)三個(gè)主分片稀火,這意味著在丟失任意一個(gè)節(jié)點(diǎn)的情況下依舊可以保證數(shù)據(jù)的完整性
- 文檔的索引將首先被存儲(chǔ)在主分片中暖哨,然后并發(fā)復(fù)制到對(duì)應(yīng)的復(fù)制節(jié)點(diǎn)上,這可以確保我們的數(shù)據(jù)在主節(jié)點(diǎn)和復(fù)制節(jié)點(diǎn)上都可以被檢索
5.3.2 路由
當(dāng)你索引一個(gè)文檔凰狞,它被存儲(chǔ)在單獨(dú)一個(gè)主分片上篇裁,Elasticsearch 是如何知道文檔屬于哪個(gè)分片的呢?當(dāng)你創(chuàng)建一個(gè)新文檔赡若,它是如何知道是應(yīng)該存儲(chǔ)在分片 1 還是分片 2 上的呢达布?
進(jìn)程不能是隨機(jī)的,因?yàn)槲覀儗?lái)要檢索文檔
算法決定:
shard = hash(routing) % number_of_primary_shards
routing 值是一個(gè)任意字符串逾冬,它默認(rèn)是 _id 但也可以自定義
為什么主分片的數(shù)量只能在創(chuàng)建索引時(shí)定義且不能修改黍聂?
如果主分片的數(shù)量在未來(lái)改變了,所有先前的路由值就失效了粉渠,文檔也就永遠(yuǎn)找不到了
所有的文檔 API(get分冈、index、delete霸株、bulk雕沉、update、mget)都接收一個(gè) routing 參數(shù)去件,它用來(lái)自定義文檔到分片的映射坡椒,自定義路由值可以確保所有相關(guān)文檔——例如屬于同一個(gè)人的文檔——被保存在同一分片上
5.3.3 操作數(shù)據(jù)節(jié)點(diǎn)工作流程
[圖片上傳失敗...(image-4aef1e-1572113601393)]
- 客戶端給 Node1 發(fā)送新建扰路、索引或刪除請(qǐng)求
- 節(jié)點(diǎn)使用文檔的 _id 確定文檔屬于分片 0,它轉(zhuǎn)發(fā)請(qǐng)求到Node3倔叼,分片 0 位于這個(gè)節(jié)點(diǎn)上
- Node3 在主分片上執(zhí)行請(qǐng)求汗唱,如果成功,它轉(zhuǎn)發(fā)請(qǐng)求到相應(yīng)的位于 Node1 和 Node2 的復(fù)制節(jié)點(diǎn)上丈攒,當(dāng)所有的復(fù)制節(jié)點(diǎn)報(bào)告成功哩罪,Node3 報(bào)告成功到請(qǐng)求的節(jié)點(diǎn),請(qǐng)求的節(jié)點(diǎn)再報(bào)告給客戶端
5.3.4 檢索流程
[圖片上傳失敗...(image-f07c-1572113601393)]
- 客戶端給 Node1 發(fā)送 GET 請(qǐng)求
- 節(jié)點(diǎn)使用文檔的 _id 確定文檔屬于分片 0巡验,分片 0 對(duì)應(yīng)的復(fù)制分片在三個(gè)節(jié)點(diǎn)上都有际插,此時(shí),它轉(zhuǎn)發(fā)請(qǐng)求到 Node 2
- Node2 返回文檔給 Node 1 然后返回給客戶端
對(duì)于讀請(qǐng)求显设,為了平衡負(fù)載框弛,請(qǐng)求節(jié)點(diǎn)會(huì)為每個(gè)請(qǐng)求選擇不同的分片——它會(huì)循環(huán)所有分片副本
可能的情況是,一個(gè)被索引的文檔已經(jīng)存在于主分片上卻還沒(méi)來(lái)得及同步到復(fù)制分片上捕捂,這時(shí)復(fù)制分片會(huì)報(bào)告文檔未找到瑟枫,主分片會(huì)成功返回文檔,一旦索引請(qǐng)求成功返回給用戶指攒,文檔則在主分片和復(fù)制分片都是可用的