elastic search初步使用
ElasticSearch是一個(gè)基于Lucene的搜索引擎菇曲,是當(dāng)前世界上最受歡迎的全文搜索引擎,其主要特點(diǎn)如下:
- 橫向可拓展性: 往集群中增加機(jī)器時(shí)只需要更改一點(diǎn)配置就可以將新機(jī)器加入集群
- 分片機(jī)制: 同一個(gè)索引切分成不同的分片
- 高可用: 提供復(fù)制集機(jī)制改鲫,一個(gè)分片可以設(shè)置多個(gè)復(fù)制集,某臺(tái)機(jī)器如果宕機(jī)不至于使集群無法工作
- 使用簡(jiǎn)單,基于 REST api就可以完成搜索引擎的全部工作铭拧,所需學(xué)習(xí)成本低赃蛛。
如無特殊聲明,本文和后續(xù)文檔將 Elastic Search 簡(jiǎn)稱為ES
全文搜索
全文搜索是指搜索程序掃描整個(gè)文檔搀菩,通過一定的分詞方法呕臂,對(duì)每一個(gè)詞建立索引,并指明該詞在文檔中出現(xiàn)的位置和次數(shù)肪跋,最后搜索引擎再通過索引關(guān)鍵字搜索出文檔并返回給用戶的過程歧蒋。
Lucene
Lucene是Apache下的一個(gè)開源全文搜索引擎工具,提供了完整的查詢引擎和索引引擎和部分文本分析引擎州既。不過Lucene僅僅是一個(gè)工具包谜洽,其目的是為了讓研發(fā)人員能夠通過這些工具包快速的為自己的應(yīng)用搭建一個(gè)搜索引擎或者基于這些工具包開發(fā)出一個(gè)完整的搜索引擎。
倒排序索引
Lucene中的索引采用的是倒排序索引的模式吴叶。所謂的倒排序索引(Inverted Index)是通過屬性的值來確定整條紀(jì)錄的位置阐虚,而不是由紀(jì)錄來確定屬性的值。倒排索引把普通索引中的文檔編號(hào)和值的關(guān)系倒過來蚌卤,變成:“關(guān)鍵詞”對(duì)“擁有該關(guān)鍵詞的所有文章號(hào)”实束。帶有倒排索引的文件我們稱為倒排索引文件,簡(jiǎn)稱倒排文件(inverted file)逊彭。倒排索引主要就由索引關(guān)鍵字和倒排文件所組成磕洪。
建立搜索引擎的關(guān)鍵步驟就在于建立倒排索引,倒排索引一般以以下數(shù)據(jù)結(jié)構(gòu)出現(xiàn):
關(guān)鍵字 | 文章號(hào)[出現(xiàn)頻率] | 出現(xiàn)位置 |
---|---|---|
簡(jiǎn)單 | 1[3] | 2,9,89 |
美女 | 5[1] | 1 |
tip | 9[2] | 2,7,22 |
表1 倒排索引數(shù)據(jù)結(jié)構(gòu)示例
倒排索引在存儲(chǔ)上使用LSM樹诫龙,維護(hù)其索引方法是當(dāng)需要新增文檔進(jìn)入系統(tǒng)時(shí)析显,首先解析文檔,之后更新內(nèi)存中維護(hù)的臨時(shí)索引签赃,文檔中出現(xiàn)的每個(gè)單詞谷异,在其倒排表列表末尾追加倒排表列表項(xiàng);一旦臨時(shí)索引將指定內(nèi)存消耗光锦聊,即進(jìn)行一次索引合并歹嘹,這里需要倒排文件里的倒排列表存放順序已經(jīng)按照索引單詞字典順序由低到高排序,這樣直接順序掃描合并即可孔庭。
實(shí)現(xiàn)
lucene在實(shí)現(xiàn)倒排索引時(shí)將索引劃分為詞典文件(Term Dictionary)尺上、頻率文件(Frequencies)、位置文件(Positions)保存圆到。其中詞典文件不僅包含關(guān)鍵詞怎抛,還有該關(guān)鍵詞指向頻率文件和位置文件的指針。
為了節(jié)省存儲(chǔ)空間芽淡,提升索引效率马绝。Lucene還對(duì)索引進(jìn)行了壓縮。
安裝
ES使用JAVA語言開發(fā)挣菲,所以在安裝ES之前需要在系統(tǒng)中安裝有JDK富稻。
表2是本文中的示例所使用的軟件環(huán)境信息掷邦。
類型 | 名稱 | 版本 |
---|---|---|
操作系統(tǒng) | ubuntu server | 16.04.2 LTS |
內(nèi)核 | Kernel | 4.4.0-62-generic |
容器 | docker | 1.28 |
java | openjdk | 1.8.0_141 |
搜索引擎 | elasticsearch | 5.5.2 |
表2 本機(jī)軟件環(huán)境信息
docker鏡像安裝
為了方便部署,我直接采用docker鏡像的方式搭建ES椭赋。鏡像啟用命令為:
$ docker run -d -v "$PWD/esdata":/usr/share/elasticsearch/data --name elasticsearch -H elasticsearch elasticsearch -Etransport.host=0.0.0.0 -Ediscovery.zen.minimum_master_nodes=1 elasticsearch
系統(tǒng)內(nèi)核參數(shù)
由于elastic search需要用到nio和mmap(虛擬內(nèi)存映射)技術(shù)抚岗,在啟動(dòng)該鏡像之前首先需要檢查一下系統(tǒng)內(nèi)核對(duì)虛擬內(nèi)存映射數(shù)目的限制(vm.max_map_count參數(shù))是否大于262144,如果不滿足這個(gè)條件哪怔,elastic search鏡像將不會(huì)啟動(dòng)宣蔚。
我們可以通過以下兩種方式去設(shè)置系統(tǒng)內(nèi)核的vm.max_map_count參數(shù):
sysctl -w vm.max_map_count=262144
如果想永久修改此參數(shù),可以通過修改 /etc/sysctl.conf
文件的方式使其永久性的成為系統(tǒng)內(nèi)核參數(shù)蔓涧。
測(cè)試
在linux系統(tǒng)下件已,我們可以使用 curl
程序來完成REST接口的調(diào)用與測(cè)試,《Elasticsearch權(quán)威指南》對(duì) curl
調(diào)用REST接口的方式描述如圖1所示元暴。
圖一 curl命令示意圖
使用以下命令可以檢測(cè)elastic search是否啟動(dòng)成功篷扩。
curl -i -XGET 'localhost:9200/'
-i
參數(shù)是說明要打印http請(qǐng)求頭信息,GET
是請(qǐng)求方法茉盏,localhost:9200/
就是我們服務(wù)器的地址和端口鉴未,elastic search默認(rèn)與外部交互的端口就是9200.如果服務(wù)啟動(dòng)成功,你會(huì)收到類似蝦苗的響應(yīng)信息鸠姨。
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 331
{
"name" : "Franz Kafka",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "JP677C9kRNqjEWYnFae_gQ",
"version" : {
"number" : "5.5.2",
"build_hash" : "b2f0c09",
"build_date" : "2017-08-14T12:33:14.154Z",
"build_snapshot" : false,
"lucene_version" : "6.6.0"
},
"tagline" : "You Know, for Search"
}
使用
為了方便操作铜秆,本文與后續(xù)內(nèi)容都將使用chrome瀏覽器的 Restlet Client插件來模擬REST請(qǐng)求,在這里推薦一下讶迁,感謝該插件的作者將本插件開源连茧。
創(chuàng)建索引
Elastic Search就像是一個(gè)nosql數(shù)據(jù)庫一樣,存儲(chǔ)我們要進(jìn)行查詢的信息巍糯,在ES中啸驯,數(shù)據(jù)庫名就是索引名。一個(gè) Elastic Search 集群可以包含多個(gè)索引祟峦,相應(yīng)的每個(gè)索引可以包含多個(gè)類型 罚斗。這些不同的類型存儲(chǔ)著多個(gè)文檔 ,每個(gè)文檔又有多個(gè)屬性宅楞。
我們可以使用PUT方法創(chuàng)建blogs庫针姿,詳細(xì)請(qǐng)求信息如圖2所示。
圖二 創(chuàng)建blogs數(shù)據(jù)庫
如果收到以下回應(yīng)內(nèi)容厌衙,則說明blogs數(shù)據(jù)庫創(chuàng)建成功距淫。
圖3 創(chuàng)建blogs數(shù)據(jù)庫成功的回應(yīng)信息
使用GET地址 http://ubuntu:9200/_cat/indices?v可以查看庫的狀態(tài),返回結(jié)果如下:
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open blogs Y9hkRePSQmiAzjNQ_K_FSw 5 1 0 0 810b 810b
其中yellow代表健康度迅箩,狀態(tài)是活動(dòng)溉愁,索引為blogs,主分片數(shù)量5饲趋,復(fù)制集1拐揭,已存儲(chǔ)的文檔數(shù)為0.
新建文檔
ES是一個(gè)面向文檔的數(shù)據(jù)庫,每一個(gè)文檔都代表一條完整的實(shí)體記錄奕塑,本文實(shí)例中一個(gè)文檔就代表一篇文章堂污。存儲(chǔ)一個(gè)文檔到ES的行為就叫做索引,在索引一個(gè)文檔之前龄砰,首先應(yīng)該明確應(yīng)該將文檔存儲(chǔ)在哪里盟猖。
本文對(duì)于數(shù)據(jù)存儲(chǔ)使用以下設(shè)計(jì):
- 每一篇文章被定義為一個(gè)文檔,包含作者换棚,發(fā)布時(shí)間式镐,文章分類,正文等信息固蚤。
- 每個(gè)文檔都屬于articles類型
- articles類型保存在blogs索引里
- blogs索引在我們的ES集群中娘汞。
按照這個(gè)設(shè)計(jì)思路,我們向ES中索引一篇文章夕玩,其請(qǐng)求信息圖4所示你弦。
圖4 向blogs索引articles類型插入一篇新文檔
如果新建文檔成功,則會(huì)收到HTTP狀態(tài)碼為201的回應(yīng)燎孟,回應(yīng)信息如圖5所示禽作。
圖5 向blogs索引articles類型插入一篇新文檔回應(yīng)信息
接著我們?cè)偎饕龓灼挛臋n,如圖6揩页,圖7.
圖6 向blogs索引articles類型插入更多新文檔
圖7 向blogs索引articles類型插入更多新文檔旷偿。
如果你無法手動(dòng)對(duì)文檔進(jìn)行編號(hào),可以使用POST方法向ES中索引一個(gè)新文檔爆侣,其操作方法和鏈接規(guī)則如圖8所示萍程。
圖8 向blogs索引articles類型POST插入一篇新文檔
從其相應(yīng)結(jié)果中可以看出ES通過自己的規(guī)則為文檔增加了_id字段,相應(yīng)結(jié)果如圖9所示.
圖9 向blogs索引articles類型POST插入一篇新文檔響應(yīng)信息
檢索文檔
在ES中檢索已存在的文檔只需使用GET方法訪問剛剛新增文檔時(shí)的連接就可以了累提。
GET http://ubuntu:9200/blogs/articles/2
返回結(jié)果如圖10所示尘喝。
圖10 從blogs索引articles類型檢索文檔
_index屬性代表文檔所屬索引, _type是文檔所屬類型斋陪, _id是文檔編號(hào), _version是文檔的版本(每對(duì)文檔做一次修改朽褪, _version就會(huì)加1), _found代表是否查詢到指定文檔无虚, _source就是文檔中所存儲(chǔ)的內(nèi)容缔赠。
更新與刪除文檔
使用REST API對(duì)ES中的數(shù)據(jù)進(jìn)行修改或刪除也是極其方便的。如果我們要?jiǎng)h除某個(gè)文檔友题,只需使用DELETE方法訪問這個(gè)文檔的鏈接就可以了嗤堰。
DELETE http://ubuntu:9200/blogs/articles/2
我們先介紹一種全量更新文檔的方法,使用PUT方法訪問我們的文檔地址度宦,參數(shù)信息加上文檔的新內(nèi)容就可以全量更新文檔了踢匣。文檔更新后告匠,ES會(huì)犯規(guī)給我們新的文檔版本和操作結(jié)果。
示例离唬,對(duì)文檔2進(jìn)行全量更新后专,其請(qǐng)求與回應(yīng)信息如圖11,圖12所示输莺。
圖11 PUT文檔全量更新
圖12 PUT文檔全量更新響應(yīng)
ES的文檔不能被修改戚哎,只能被替換。但ES為我們提供了 update API嫂用。通過update API操作從整體來看型凳,我們可以對(duì)文檔的某個(gè)位置進(jìn)行部分更新。不過在底層實(shí)現(xiàn)上 update API 還是需要進(jìn)行完整的檢索-修改-重建索引 的處理過程嘱函。 區(qū)別在于這個(gè)過程發(fā)生在分片內(nèi)部甘畅,這樣就避免了多次請(qǐng)求的網(wǎng)絡(luò)開銷。因?yàn)闇p少了檢索和重建索引步驟之間的時(shí)間实夹,更新此文檔時(shí)與其他進(jìn)程的更新操作沖突的可能性也會(huì)減少橄浓。
update 請(qǐng)求最簡(jiǎn)單的一種形式將待更新的字段作為doc的參數(shù), 它只是與現(xiàn)有的文檔進(jìn)行合并亮航。對(duì)象被合并到一起荸实,覆蓋現(xiàn)有的字段或者新增字段。
示例缴淋,修改文檔2的author和tags屬性准给,其請(qǐng)求、新文檔內(nèi)容如圖13重抖、圖14所示露氮。
圖13 POST update文檔部分更新
圖14 POST update文檔部分更新后的結(jié)果
如果更新文檔是一個(gè)并發(fā)操作,當(dāng)前工作在更新文檔的檢索步驟會(huì)獲取當(dāng)前版本號(hào)钟沛,在重建索引之前會(huì)檢查文檔此時(shí)的版本號(hào)是否與檢索時(shí)的版本號(hào)一致畔规,如果版本號(hào)不一致,當(dāng)前線程就會(huì)發(fā)生操作失敗恨统,放棄文檔的修改叁扫。如果業(yè)務(wù)上允許重復(fù)更新的話,可以通過retry_on_conflict屬性畜埋,來設(shè)置失敗重試莫绣。該屬性用法如下面代碼所示。對(duì)于不能重試的業(yè)務(wù)場(chǎng)景悠鞍,update API提供了version屬性進(jìn)行樂觀并發(fā)控制对室。
PUT http://ubuntu:9200/blogs/articles/2/_update?retry_on_conflict=5
搜索文檔
搜索是ES的核心,不過鑒于篇幅原因,關(guān)于搜索功能的使用將放到下篇文章中掩宜。
引用
本文是我在學(xué)習(xí)使用ES時(shí)的筆記蔫骂,在本文的寫過過程中參考了大量其它資料,有些材料來源于網(wǎng)絡(luò)锭亏,我由衷的表示感謝纠吴,但由于原作者不明硬鞍,恕不能一一記述慧瘤。
- Elasticsearch 權(quán)威指南.——https://www.elastic.co/
- Elasticsearch技術(shù)解析與實(shí)戰(zhàn)/朱林編著.——北京:機(jī)械工業(yè)出版社,2016.12(數(shù)據(jù)分析與決策技術(shù)叢書)
關(guān)于
本項(xiàng)目和文檔中所用的內(nèi)容僅供學(xué)習(xí)和研究之用固该,轉(zhuǎn)載或引用時(shí)請(qǐng)指明出處锅减。如果你對(duì)文檔有疑問或問題,請(qǐng)?jiān)陧?xiàng)目中給我留言或發(fā)email到
weiwei02@vip.qq.com 我的github:
https://github.com/weiwei02/ 我相信技術(shù)能夠改變世界 伐坏。
鏈接
- 上篇文章(無)
- 下篇文章勾勒一個(gè)自己的搜索引擎ES2輕量級(jí)搜索