Elasticsearch是什么
Elasticsearch是一個(gè)基于Apache Lucene(TM)的一個(gè)分布式的開源搜索和分析引擎
Elasticsearch實(shí)現(xiàn)的功能
-
分布式的搜索引擎
Elasticsearch自動(dòng)將海量數(shù)據(jù)分散到多臺(tái)服務(wù)器進(jìn)行存儲(chǔ)和檢索
-
全文檢索
Elasticsearch提供了模糊搜索等自動(dòng)度很高的查詢方式,并進(jìn)行相關(guān)排名,高亮等功能
-
數(shù)據(jù)分析
可以做分組聚合
-
對(duì)海量數(shù)據(jù)進(jìn)行實(shí)時(shí)處理
因?yàn)镋lasticsearch是分布式架構(gòu),可以采用大量的服務(wù)器進(jìn)行存儲(chǔ)和檢索數(shù)據(jù),可以實(shí)現(xiàn)秒級(jí)數(shù)據(jù)搜索和分析
使用場(chǎng)景
- 搜索類場(chǎng)景
- 日志分析 (經(jīng)典的ELK組合完成日志收集、存儲(chǔ)、分析、查詢功能)
- 數(shù)據(jù)預(yù)警、分析平臺(tái)(分析電商平臺(tái)評(píng)論數(shù)、訪問量、關(guān)注度等等)
- 商業(yè)BI系統(tǒng) (分析上一季度消費(fèi)金額、年齡段、訪問時(shí)間段的人數(shù)分布等等)
全文搜索方案對(duì)比
-
solr
Solr是一個(gè)有HTTP接口的基于Lucene的查詢服務(wù)器,封裝了很多Lucene細(xì)節(jié),自己的應(yīng)用可以直接利用諸如 .../solr?q=abc 這樣的HTTP GET/POST請(qǐng)求去查詢,維護(hù)修改索引。
-
Elasticsearch
Elasticsearch也是一個(gè)建立在全文搜索引擎 Apache Lucene基礎(chǔ)上的搜索引擎。采用的策略是分布式實(shí)時(shí)文件存儲(chǔ),并將每一個(gè)字段都編入索引,使其可以被搜索。
兩者者之間的一個(gè)聯(lián)系:solr和Elasticsearch都是基于Lucene實(shí)現(xiàn)的
區(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
核心概念
索引(index)
ElasticSearch將它的數(shù)據(jù)存儲(chǔ)在一個(gè)或多個(gè)索引(index)中。用SQL領(lǐng)域的術(shù)語(yǔ)來類比,索引就像數(shù)據(jù)庫(kù),可以向索引寫入文檔或者從索引中讀取文檔,并通過ElasticSearch內(nèi)部使用Lucene將數(shù)據(jù)寫入索引或從索引中檢索數(shù)據(jù)。
類型(type)
類型是模擬mysql中的table概念,一個(gè)索引庫(kù)下可以有不同類型的索引,比如商品索引,訂單索引,其數(shù)據(jù)格式不同。不過這會(huì)導(dǎo)致索引庫(kù)混亂,因此未來版本中會(huì)移除這個(gè)概念
ES中每個(gè)大版本的type類型有很大區(qū)別
ES 5.x 中index可以又多種type
ES 6.x 中一個(gè)index只能有一個(gè)type
ES 7.x以后要逐漸移除這個(gè)概念
文檔(document)
文檔(document)是ElasticSearch中的主要實(shí)體。對(duì)所有使用ElasticSearch的案例來說,他們最終都可以歸結(jié)為對(duì)文檔的搜索。文檔由字段構(gòu)成。
在一個(gè)index/type里面,你可以存儲(chǔ)任意多的文檔。注意,盡管一個(gè)文檔,物理上存在于一個(gè)索引之中,文檔必須被索引/賦予一個(gè)索引的type。
字段Field
相當(dāng)于是數(shù)據(jù)表的字段,對(duì)文檔數(shù)據(jù)根據(jù)不同屬性進(jìn)行的分類標(biāo)識(shí)
映射 mapping
mapping就相當(dāng)于我們關(guān)系型數(shù)據(jù)庫(kù)中的表結(jié)構(gòu),是處理數(shù)據(jù)的方式和規(guī)則方面做一些限制,如某個(gè)字段的數(shù)據(jù)類型、默認(rèn)值、分析器、是否被索引等等,這些都是映射里面可以設(shè)置的,其它就是處理es里面數(shù)據(jù)的一些使用規(guī)則設(shè)置也叫做映射,按著最優(yōu)規(guī)則處理數(shù)據(jù)對(duì)性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能對(duì)性能更好。
集群 cluster
一個(gè)集群就是由一個(gè)或多個(gè)節(jié)點(diǎn)組織在一起,它們共同持有整個(gè)的數(shù)據(jù),并一起提供索引和搜索功能。一個(gè)集群由一個(gè)唯一的名字標(biāo)識(shí),這個(gè)名字默認(rèn)就是“elasticsearch”。這個(gè)名字是重要的,因?yàn)橐粋€(gè)節(jié)點(diǎn)只能通過指定某個(gè)集群的名字,來加入這個(gè)集群
可以通過get請(qǐng)求查看集群狀態(tài):
http://es地址:9200/_cat/health?v
返回?cái)?shù)據(jù):
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1645155625 11:40:25 sxjyes green 3 3 252 126 0 0 0 0 - 100.0%
參數(shù)說明:
cluster:集群名稱
status:集群狀態(tài) green代表健康;yellow代表分配了所有主分片,但至少缺少一個(gè)副本,此時(shí)集群數(shù)據(jù)仍舊完整;red代表部分主分片不可用,可能已經(jīng)丟失數(shù)據(jù)。
node.total:代表在線的節(jié)點(diǎn)總數(shù)量
node.data:代表在線的數(shù)據(jù)節(jié)點(diǎn)的數(shù)量
shards, active_shards: 存活的分片數(shù)量
pri,active_primary_shards: 存活的主分片數(shù)量 正常情況下 shards的數(shù)量是pri的兩倍。
relo, relocating_shards :遷移中的分片數(shù)量,正常情況為 0
init, initializing_shards: 初始化中的分片數(shù)量 正常情況為 0
unassign, unassigned_shards: 未分配的分片 正常情況為 0
pending_tasks:準(zhǔn)備中的任務(wù),任務(wù)指遷移分片等 正常情況為 0
max_task_wait_time:任務(wù)最長(zhǎng)等待時(shí)間
active_shards_percent:正常分片百分比 正常情況為 100%
節(jié)點(diǎn) node
一個(gè)節(jié)點(diǎn)是集群中的一個(gè)服務(wù)器,作為集群的一部分,它存儲(chǔ)數(shù)據(jù),參與集群的索引和搜索功能。和集群類似,一個(gè)節(jié)點(diǎn)也是由一個(gè)名字來標(biāo)識(shí)的,默認(rèn)情況下,這個(gè)名字是一個(gè)隨機(jī)的漫威漫畫角色的名字,這個(gè)名字會(huì)在啟動(dòng)的時(shí)候賦予節(jié)點(diǎn)。這個(gè)名字對(duì)于管理工作來說挺重要的,因?yàn)樵谶@個(gè)管理過程中,你會(huì)去確定網(wǎng)絡(luò)中的哪些服務(wù)器對(duì)應(yīng)于Elasticsearch集群中的哪些節(jié)點(diǎn)。
一個(gè)節(jié)點(diǎn)可以通過配置集群名稱的方式來加入一個(gè)指定的集群。默認(rèn)情況下,每個(gè)節(jié)點(diǎn)都會(huì)被安排加入到一個(gè)叫做“elasticsearch”的集群中,這意味著,如果你在你的網(wǎng)絡(luò)中啟動(dòng)了若干個(gè)節(jié)點(diǎn),并假定它們能夠相互發(fā)現(xiàn)彼此,它們將會(huì)自動(dòng)地形成并加入到一個(gè)叫做“elasticsearch”的集群中。
在一個(gè)集群里,只要你想,可以擁有任意多個(gè)節(jié)點(diǎn)。而且,如果當(dāng)前你的網(wǎng)絡(luò)中沒有運(yùn)行任何Elasticsearch節(jié)點(diǎn),這時(shí)啟動(dòng)一個(gè)節(jié)點(diǎn),會(huì)默認(rèn)創(chuàng)建并加入一個(gè)叫做“elasticsearch”的集群。
分片和復(fù)制 shards&replicas
一個(gè)索引可以存儲(chǔ)超出單個(gè)結(jié)點(diǎn)硬件限制的大量數(shù)據(jù)。比如,一個(gè)具有10億文檔的索引占據(jù)1TB的磁盤空間,而任一節(jié)點(diǎn)都沒有這樣大的磁盤空間;或者單個(gè)節(jié)點(diǎn)處理搜索請(qǐng)求,響應(yīng)太慢。為了解決這個(gè)問題,Elasticsearch提供了將索引劃分成多份的能力,這些份就叫做分片。當(dāng)你創(chuàng)建一個(gè)索引的時(shí)候,你可以指定你想要的分片的數(shù)量。每個(gè)分片本身也是一個(gè)功能完善并且獨(dú)立的“索引”,這個(gè)“索引”可以被放置到集群中的任何節(jié)點(diǎn)上。分片很重要,主要有兩方面的原因:
1)允許你水平分割/擴(kuò)展你的內(nèi)容容量。
2)允許你在分片(潛在地,位于多個(gè)節(jié)點(diǎn)上)之上進(jìn)行分布式的、并行的操作,進(jìn)而提高性能/吞吐量。
至于一個(gè)分片怎樣分布,它的文檔怎樣聚合回搜索請(qǐng)求,是完全由Elasticsearch管理的,對(duì)于作為用戶的你來說,這些都是透明的。
在一個(gè)網(wǎng)絡(luò)/云的環(huán)境里,失敗隨時(shí)都可能發(fā)生,在某個(gè)分片/節(jié)點(diǎn)不知怎么的就處于離線狀態(tài),或者由于任何原因消失了,這種情況下,有一個(gè)故障轉(zhuǎn)移機(jī)制是非常有用并且是強(qiáng)烈推薦的。為此目的,Elasticsearch允許你創(chuàng)建分片的一份或多份拷貝,這些拷貝叫做復(fù)制分片,或者直接叫復(fù)制。
復(fù)制之所以重要,有兩個(gè)主要原因: 在分片/節(jié)點(diǎn)失敗的情況下,提供了高可用性。因?yàn)檫@個(gè)原因,注意到復(fù)制分片從不與原/主要(original/primary)分片置于同一節(jié)點(diǎn)上是非常重要的。擴(kuò)展你的搜索量/吞吐量,因?yàn)樗阉骺梢栽谒械膹?fù)制上并行運(yùn)行??傊總€(gè)索引可以被分成多個(gè)分片。一個(gè)索引也可以被復(fù)制0次(意思是沒有復(fù)制)或多次。一旦復(fù)制了,每個(gè)索引就有了主分片(作為復(fù)制源的原來的分片)和復(fù)制分片(主分片的拷貝)之別。分片和復(fù)制的數(shù)量可以在索引創(chuàng)建的時(shí)候指定。在索引創(chuàng)建之后,你可以在任何時(shí)候動(dòng)態(tài)地改變復(fù)制的數(shù)量,但是你事后不能改變分片的數(shù)量。
默認(rèn)情況下,Elasticsearch中的每個(gè)索引被分片5個(gè)主分片和1個(gè)復(fù)制,這意味著,如果你的集群中至少有兩個(gè)節(jié)點(diǎn),你的索引將會(huì)有5個(gè)主分片和另外5個(gè)復(fù)制分片(1個(gè)完全拷貝),這樣的話每個(gè)索引總共就有10個(gè)分片。
Elasticsearch概念和關(guān)系型數(shù)據(jù)庫(kù)的對(duì)比
| 關(guān)系型數(shù)據(jù)庫(kù)(如mysql) | Elasticsearch |
|---|---|
| 數(shù)據(jù)庫(kù) | 索引index |
| 表(table) | 索引index類型(原為type) |
| 數(shù)據(jù)行row | 文檔(document) |
| 數(shù)據(jù)列(column) | 字段Field |
| 約束 schema | 映射 mapping |
字段類型
字段類型分為基本類型和復(fù)合類型‘
基本類型
字符串類型
-
string
string類型在ElasticSearch 舊版本中使用較多,從ElasticSearch 5.x開始不再支持string,由text和keyword類型替代。
-
text
當(dāng)一個(gè)字段是要被全文搜索的,比如Email內(nèi)容、產(chǎn)品描述,應(yīng)該使用text類型。設(shè)置text類型以后,字段內(nèi)容會(huì)被分析,在生成倒排索引以前,字符串會(huì)被分析器分成一個(gè)一個(gè)詞項(xiàng)。text類型的字段不用于排序,很少用于聚合。
text會(huì)分詞,然后進(jìn)行索引,支持模糊、精確查詢,不支持聚合
-
keyword
這種類型適用于結(jié)構(gòu)化的字段,例如標(biāo)簽、email 地址、手機(jī)號(hào)碼等等,這種類型的字段可以用作過濾、排序、聚合等。這種字符串也稱之為 not-analyzed 字段。
keyword不進(jìn)行分詞,直接索引,支持模糊、精確查詢,支持聚合
數(shù)字類型
數(shù)字類型有l(wèi)ong、integer、short、byte、double、float、half_float、scaled_float。
- 在滿足需求的情況下,優(yōu)先使用范圍小的字段。字段長(zhǎng)度越短,索引和搜索的效率越高。比如,某個(gè)字段的取值最大值不會(huì)超過100,那么選擇byte類型即可。迄今為止吉尼斯記錄的人類的年齡的最大值為134歲,對(duì)于年齡字段,short足矣字段的長(zhǎng)度越短,索引和搜索的效率越高。
- 浮點(diǎn)數(shù),優(yōu)先考慮使用 scaled_float。
日期類型
由于 JSON 中沒有日期類型,所以 es 中的日期類型形式就比較多樣:2020-11-11 或者 2020-11-11 11:11:11,一個(gè)從 1970.1.1 零點(diǎn)到現(xiàn)在的一個(gè)秒數(shù)或者毫秒數(shù)。es 內(nèi)部將時(shí)間轉(zhuǎn)為 UTC,然后將時(shí)間按照 millseconds-since-the-epoch 的長(zhǎng)整型來存儲(chǔ)。
boolean類型
邏輯類型(布爾類型)可以接受true/false/”true”/”false”值
二進(jìn)制類型(binary)
二進(jìn)制字段是指用base64來表示索引中存儲(chǔ)的二進(jìn)制數(shù)據(jù),可用來存儲(chǔ)二進(jìn)制形式的數(shù)據(jù),例如圖像。默認(rèn)情況下,該類型的字段只存儲(chǔ)不索引。二進(jìn)制類型只支持index_name屬性。
范圍類型(range)
數(shù)據(jù)范圍類型,一個(gè)字段表示一個(gè)范圍,具體包含以下類型:
- integer_range
- float_range
- double_range
- date_range
- ip_range
所謂的范圍類型,就是一個(gè)值自身就表明一個(gè)范圍,如:
PUT range_index
{
"mappings": {
"_doc": {
"properties": {
"expected_attendees": {
"type": "integer_range"
}
}
}
}
}
復(fù)合類型
數(shù)組類型(array)
es 中沒有專門的數(shù)組類型。默認(rèn)情況下,任何字段都可以有一個(gè)或者多個(gè)值。需要注意的是,數(shù)組中的元素必須是同一種類型。添加數(shù)組是,數(shù)組中的第一個(gè)元素決定了整個(gè)數(shù)組的類型。
對(duì)象類型(object)
由于 JSON 本身具有層級(jí)關(guān)系,所以文檔包含內(nèi)部對(duì)象。內(nèi)部對(duì)象中,還可以再包含內(nèi)部對(duì)象。
IK分詞器
Elasticsearch自帶的標(biāo)準(zhǔn)分詞器是針對(duì)英文的,所以我們?cè)谌粘i_發(fā)中都是使用ik分詞器,它是一個(gè)針對(duì)中文的分詞器。
從2016年12月推出1.0版本開始,IKAnalyzer已經(jīng)推出了三個(gè)大版本,最初他是以開源項(xiàng)目Lucene為應(yīng)用主題的,結(jié)合詞典分詞和文法分析算法的中文分詞組件,新版的IKAnalyzer3.0則發(fā)展為面向java的公用分詞組件,獨(dú)立于Lucene項(xiàng)目,同時(shí)提供了對(duì)Lucene的默認(rèn)優(yōu)化實(shí)現(xiàn)
IKAnalyzer3.0版本特性如下:
- 采用了特有的“正向迭代最細(xì)粒度切分算法“,具有50萬(wàn)字/秒的高速處理能力。
- 采用了多子處理器分析模式,支持:英文字母(IP地址、Email、URL)、數(shù)字(日期,常用中文數(shù)量詞,羅馬數(shù)字,科學(xué)計(jì)數(shù)法),中文詞匯(姓名、地名處理)等分詞處理。
- 優(yōu)化的詞典存儲(chǔ),更小的內(nèi)存占用。支持用戶詞典擴(kuò)展定義
- 針對(duì)Lucene全文檢索優(yōu)化的查詢分析器IKQueryParser;采用歧義分析算法優(yōu)化查詢關(guān)鍵字的搜索排列組合,能極大的提高Lucene檢索的命中率。
IK分詞器有兩種分詞模式:ik_max_word和ik_smart模式。
ik_max_word
會(huì)將文本做最細(xì)粒度的拆分,比如會(huì)將“中華人民共和國(guó)人民大會(huì)堂”拆分為“中華人民共和國(guó)、中華人民、中華、華人、人民共和國(guó)、人民、共和國(guó)、大會(huì)堂、大會(huì)、會(huì)堂等詞語(yǔ)。
ik_smart
會(huì)做最粗粒度的拆分,比如會(huì)將“中華人民共和國(guó)人民大會(huì)堂”拆分為中華人民共和國(guó)、人民大會(huì)堂。
IK分詞器擴(kuò)展詞典
停用詞擴(kuò)展
- 1) 我們找到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 擴(kuò)展配置</comment>
<!--用戶可以在這里配置自己的擴(kuò)展字典 -->
<entry key="ext_dict">ext_dic.dic</entry>
<!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->
<entry key="ext_stopwords"></entry>
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展停止詞字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
- 2)在配置文件中增加配置的停用詞文件的節(jié)點(diǎn):
<entry key="ext_stopwords">my_ext_stopword.dic</entry>
3)在類目前下創(chuàng)建擴(kuò)展停用詞文件my_ext_stopword.dic
4) 在文件my_ext_stopword.dic中添加詞,一行一個(gè)
擴(kuò)展字典
- 1) 我們找到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 擴(kuò)展配置</comment>
<!--用戶可以在這里配置自己的擴(kuò)展字典 -->
<entry key="ext_dict">ext_dic.dic</entry>
<!--用戶可以在這里配置自己的擴(kuò)展停止詞字典-->
<entry key="ext_stopwords"></entry>
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用戶可以在這里配置遠(yuǎn)程擴(kuò)展停止詞字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
- 2)在配置文件中增加配置的停用詞文件的節(jié)點(diǎn):
<entry key="ext_dict">my_ext_dict.dic</entry>
3)在類目前下創(chuàng)建擴(kuò)展停用詞文件my_ext_dict.dic
4) 在文件my_ext_dict.dic中添加詞,一行一個(gè)
同義詞詞典
Elasticsearch 自帶一個(gè)名為 synonym 的同義詞 filter。為了能讓 IK 和 synonym 同時(shí)工作,我們需要定義新的 analyzer,用 IK 做 tokenizer,synonym 做 filter。
- 打開 /config/elasticsearch.yml 文件,加入以下配置:
index:
analysis:
analyzer:
ik_syno:
type: custom
tokenizer: ik_max_word
filter: [my_synonym_filter]
ik_syno_smart:
type: custom
tokenizer: ik_smart
filter: [my_synonym_filter]
filter:
my_synonym_filter:
type: synonym
synonyms_path: analysis/synonym.txt
以上配置定義了 ik_syno 和 ik_syno_smart 這兩個(gè)新的 analyzer,分別對(duì)應(yīng) IK 的 ik_max_word 和 ik_smart 兩種分詞策略
創(chuàng)建/config/analysis/synonym.txt 文件,輸入一些同義詞并存為 utf-8 格式。例如
重啟es即可