當前位置:編程學習大全網 - 編程語言 - 如何調用elasticsearch中的數據

如何調用elasticsearch中的數據

由於需要提升項目的搜索質量,最近研究了壹下Elasticsearch,壹款非常優秀的分布式搜索程序。最開始的壹些筆記放到github,這裏只是歸納總結壹下。

首先,為什麽要使用Elasticsearch?最開始的時候,我們的項目僅僅使用MySQL進行簡單的搜索,然後壹個不能索引的like語句,直接拉低MySQL的性能。後來,我們曾考慮過sphinx,並且sphinx也在之前的項目中成功實施過,但想想現在的數據量級,多臺MySQL,以及搜索服務本身HA,還有後續擴容的問題,我們覺得sphinx並不是壹個最優的選擇。於是自然將目光放到了Elasticsearch上面。

根據官網自己的介紹,Elasticsearch是壹個分布式搜索服務,提供Restful API,底層基於Lucene,采用多shard的方式保證數據安全,並且提供自動resharding的功能,加之github等大型的站點也采用 Elasticsearch作為其搜索服務,我們決定在項目中使用Elasticsearch。

對於Elasticsearch,如果要在項目中使用,需要解決如下問題:

索引,對於需要搜索的數據,如何建立合適的索引,還需要根據特定的語言使用不同的analyzer等。

搜索,Elasticsearch提供了非常強大的搜索功能,如何寫出高效的搜索語句?

數據源,我們所有的數據是存放到MySQL的,MySQL是唯壹數據源,如何將MySQL的數據導入到Elasticsearch?

對於1和2,因為我們的數據都是從MySQL生成,index的field是固定的,主要做的工作就是根據業務場景設計好對應的mapping以及search語句就可以了,當然實際不可能這麽簡單,需要我們不斷的調優。

而對於3,則是需要壹個工具將MySQL的數據導入Elasticsearch,因為我們對搜索實時性要求很高,所以需要將MySQL的增量數據實時導入,筆者唯壹能想到的就是通過row based binlog來完成。而近段時間的工作,也就是實現壹個MySQL增量同步到Elasticsearch的服務。

Lucene

Elasticsearch底層是基於Lucene的,Lucene是壹款優秀的搜索lib,當然,筆者以前仍然沒有接觸使用過。:-)

Lucene關鍵概念:

Document:用來索引和搜索的主要數據源,包含壹個或者多個Field,而這些Field則包含我們跟Lucene交互的數據。

Field:Document的壹個組成部分,有兩個部分組成,name和value。

Term:不可分割的單詞,搜索最小單元。

Token:壹個Term呈現方式,包含這個Term的內容,在文檔中的起始位置,以及類型。

Lucene使用Inverted index來存儲term在document中位置的映射關系。

譬如如下文檔:

Elasticsearch Server 1.0 (document 1)

Mastring Elasticsearch (document 2)

Apache Solr 4 Cookbook (document 3)

使用inverted index存儲,壹個簡單地映射關系:

Term

Count

Docuemnt

1.0 1 <1>

4 1 <3>

Apache 1 <3>

Cookbook 1 <3>

Elasticsearch 2 <1>.<2>

Mastering 1 <2>

Server 1 <1>

Solr 1 <3>

對於上面例子,我們首先通過分詞算法將壹個文檔切分成壹個壹個的token,再得到該token與document的映射關系,並記錄token出現的總次數。這樣就得到了壹個簡單的inverted index。

Elasticsearch關鍵概念

要使用Elasticsearch,筆者認為,只需要理解幾個基本概念就可以了。

在數據層面,主要有:

Index:Elasticsearch用來存儲數據的邏輯區域,它類似於關系型數據庫中的db概念。壹個index可以在壹個或者多個shard上面,同時壹個shard也可能會有多個replicas。

Document:Elasticsearch裏面存儲的實體數據,類似於關系數據中壹個table裏面的壹行數據。

document由多個field組成,不同的document裏面同名的field壹定具有相同的類型。document裏面field可以重復出現,也就是壹個field會有多個值,即multivalued。

Document type:為了查詢需要,壹個index可能會有多種document,也就是document type,但需要註意,不同document裏面同名的field壹定要是相同類型的。

Mapping:存儲field的相關映射信息,不同document type會有不同的mapping。

對於熟悉MySQL的童鞋,我們只需要大概認為Index就是壹個db,document就是壹行數據,field就是table的column,mapping就是table的定義,而document type就是壹個table就可以了。

Document type這個概念其實最開始也把筆者給弄糊塗了,其實它就是為了更好的查詢,舉個簡單的例子,壹個index,可能壹部分數據我們想使用壹種查詢方式,而另壹部分數據我們想使用另壹種查詢方式,於是就有了兩種type了。不過這種情況應該在我們的項目中不會出現,所以通常壹個index下面僅會有壹個 type。

在服務層面,主要有:

Node: 壹個server實例。

Cluster:多個node組成cluster。

Shard:數據分片,壹個index可能會存在於多個shards,不同shards可能在不同nodes。

Replica:shard的備份,有壹個primary shard,其余的叫做replica shards。

Elasticsearch之所以能動態resharding,主要在於它最開始就預先分配了多個shards(貌似是1024),然後以shard為單位進行數據遷移。這個做法其實在分布式領域非常的普遍,codis就是使用了1024個slot來進行數據遷移。

因為任意壹個index都可配置多個replica,通過冗余備份的方式保證了數據的安全性,同時replica也能分擔讀壓力,類似於MySQL中的slave。

Restful API

Elasticsearch提供了Restful API,使用json格式,這使得它非常利於與外部交互,雖然Elasticsearch的客戶端很多,但筆者仍然很容易的就寫出了壹個簡易客戶端用於項目中,再次印證了Elasticsearch的使用真心很容易。

Restful的接口很簡單,壹個url表示壹個特定的資源,譬如/blog/article/1,就表示壹個index為blog,type為aritcle,id為1的document。

而我們使用http標準method來操作這些資源,POST新增,PUT更新,GET獲取,DELETE刪除,HEAD判斷是否存在。

這裏,友情推薦httpie,壹個非常強大的http工具,個人感覺比curl還用,幾乎是命令行調試Elasticsearch的絕配。

壹些使用httpie的例子:

# create

http POST :9200/blog/article/1 title="hello elasticsearch" tags:='["elasticsearch"]'

# get

http GET :9200/blog/article/1

# update

http PUT :9200/blog/article/1 title="hello elasticsearch" tags:='["elasticsearch", "hello"]'

# delete

http DELETE :9200/blog/article/1

# exists

http HEAD :9200/blog/article/1

索引和搜索

雖然Elasticsearch能自動判斷field類型並建立合適的索引,但筆者仍然推薦自己設置相關索引規則,這樣才能更好為後續的搜索服務。

我們通過定制mapping的方式來設置不同field的索引規則。

而對於搜索,Elasticsearch提供了太多的搜索選項,就不壹壹概述了。

索引和搜索是Elasticsearch非常重要的兩個方面,直接關系到產品的搜索體驗,但筆者現階段也僅僅是大概了解了壹點,後續在詳細介紹。

同步MySQL數據

Elasticsearch是很強大,但要建立在有足量數據情況下面。我們的數據都在MySQL上面,所以如何將MySQL的數據導入Elasticsearch就是筆者最近研究的東西了。

雖然現在有壹些實現,譬如elasticsearch-river-jdbc,或者elasticsearch-river-mysql,但筆者並不打算使用。

elasticsearch-river-jdbc的功能是很強大,但並沒有很好的支持增量數據更新的問題,它需要對應的表只增不減,而這個幾乎在項目中是不可能辦到的。

elasticsearch-river-mysql倒是做的很不錯,采用了python-mysql-replication來通過binlog獲取變更的數據,進行增量更新,但它貌似處理MySQL dump數據導入的問題,不過這個筆者真的好好確認壹下?話說,python-mysql-replication筆者還提交過pull解決了minimal row image的問題,所以對elasticsearch-river-mysql這個項目很有好感。只是筆者決定自己寫壹個出來。

為什麽筆者決定自己寫壹個,不是因為筆者喜歡造輪子,主要原因在於對於這種MySQL syncer服務(增量獲取MySQL數據更新到相關系統),我們不光可以用到Elasticsearch上面,而且還能用到其他服務,譬如cache上面。所以筆者其實想實現的是壹個通用MySQL syncer組件,只是現在主要關註Elasticsearch罷了。

項目代碼在這裏go-mysql-elasticsearch,現已完成第壹階段開發,內部對接測試中。

go-mysql-elasticsearch的原理很簡單,首先使用mysqldump獲取當前MySQL的數據,然後在通過此時binlog的name和position獲取增量數據。

壹些限制:

binlog壹定要變成row-based format格式,其實我們並不需要擔心這種格式的binlog占用太多的硬盤空間,MySQL 5.6之後GTID模式都推薦使用row-based format了,而且通常我們都會把控SQL語句質量,不允許壹次性更改過多行數據的。

需要同步的table最好是innodb引擎,這樣mysqldump的時候才不會阻礙寫操作。

需要同步的table壹定要有主鍵,好吧,如果壹個table沒有主鍵,筆者真心會懷疑設計這個table的同學編程水平了。多列主鍵也是不推薦的,筆者現階段不打算支持。

壹定別動態更改需要同步的table結構,Elasticsearch只能支持動態增加field,並不支持動態刪除和更改field。通常來說,如果涉及到alter table,很多時候已經證明前期設計的不合理以及對於未來擴展的預估不足了。

更詳細的說明,等到筆者完成了go-mysql-elasticsearch的開發,並通過生產環境中測試了,再進行補充。

總結

最近壹周,筆者花了不少時間在Elasticsearch上面,現在算是基本入門了。其實筆者覺得,對於壹門不懂的技術,找壹份靠譜的資料(官方文檔或者入門書籍),蛋疼的對著資料敲壹遍代碼,不懂的再問google,最後在將其用到實際項目,這門技術就算是初步掌握了,當然精通還得在下點功夫。

現在筆者只是覺得Elasticsearch很美好,上線之後鐵定會有坑的,那時候只能慢慢填了。話說,筆者是不是要學習下java了,省的到時候看不懂代碼就慘了。:-)

  • 上一篇:油罐車的操作流程
  • 下一篇:51單片機匯編中SUBB帶借位指令的意思
  • copyright 2024編程學習大全網