首先,為什麽要使用Elasticsearch?壹開始,我們的項目只使用MySQL進行簡單的搜索,然後壹個無法索引的like語句直接降低了MySQL的性能。後來,我們考慮了sphinx,sphinx在之前的項目中得到了成功實現,但考慮到當前的數據水平、多個MySQL、搜索服務本身的HA以及後續的擴展,我們認為sphinx並不是壹個最優的選擇。所以我自然而然地把目光投向了Elasticsearch。
根據官網自己的介紹,Elasticsearch是壹個分布式搜索服務,它提供Restful API,底層基於Lucene,通過使用多個shard來確保數據安全,並提供自動重共享功能。此外,github等大型網站也使用Elasticsearch作為其搜索服務,因此我們決定在項目中使用Elasticsearch。
對於Elasticsearch,如果您想在項目中使用它,您需要解決以下問題:
索引,如何為要搜索的數據建立合適的索引,以及如何根據具體語言使用不同的分析器。
搜索方面,Elasticsearch提供了非常強大的搜索功能,如何編寫高效的搜索語句?
數據源,我們所有的數據都存儲在MySQL中,而MySQL是唯壹的數據源。如何將MySQL數據導入Elasticsearch?
對於1和2,由於我們的數據是從MySQL中生成的,因此索引的字段是固定的,主要工作是根據業務場景設計相應的映射和搜索語句。當然,它並沒有那麽簡單,我們需要不斷地調整它。
對於3,我們需要壹個將MySQL數據導入Elasticsearch的工具,因為我們對實時搜索的要求很高,所以我們需要實時導入MySQL增量數據,而我唯壹能想到的是通過基於行的binlog來實現。最近的工作是實現MySQL增量同步到Elasticsearch的服務。
全文搜索引擎
Elasticsearch的底層基於Lucene,這是壹個優秀的搜索庫。當然,作者以前從未使用過。:-)
Lucene關鍵概念:
文檔:用於索引和搜索的主要數據源,包含壹個或多個字段,這些字段包含我們與Lucene交互的數據。
字段:文檔的組成部分,由名稱和值兩部分組成。
$ Term:不可分割的單詞,搜索最小單元。
token:$ Term的表示形式,包括這個$ Term的內容、文檔中的起始位置和類型。
Lucene使用倒排索引來存儲文檔中$ term位置的映射關系。
例如,以下文檔:
Elasticsearch Server 1.0(文檔1)
Mastring Elasticsearch(文檔2)
Apache Solr 4指南(文檔3)
使用倒排索引存儲,壹個簡單的映射關系:
學期
數數
文件
1.0 1 <1》
4 1 & lt;3 & gt
Apache 1 & lt;3 & gt
食譜1 & lt;3 & gt
Elasticsearch 2 & lt1》。& lt2 & gt
掌握1 & lt;2 & gt
服務器1 & lt;1》
Solr 1 & lt;3 & gt
對於上面的例子,我們首先通過分詞算法將壹個文檔切割成token,然後得到token與文檔之間的映射關系,並記錄token的總數。這樣,就獲得了壹個簡單的倒排索引。
彈性搜索的關鍵概念
要使用Elasticsearch,作者認為只需要理解幾個基本概念。
在數據層面,主要有:
索引:elastic search用來存儲數據的邏輯區域,類似於關系數據庫中db的概念。壹個索引可以在壹個或多個分片上,壹個分片也可以有多個副本。
存儲在Document:Elasticsearch中的實體數據類似於關系數據中表中的壹行數據。
壹個文檔由多個字段組成,不同文檔中的同名字段必須具有相同的類型。文檔中的字段可以重復,即壹個字段將有多個值,即多值。
文檔類型:出於查詢目的,壹個索引可以有多個文檔,即文檔類型,但需要註意的是不同文檔中的同名字段必須是同壹類型。
映射:存儲字段的相關映射信息,不同的單據類型會有不同的映射。
對於熟悉MySQL的童鞋來說,我們只需要認為索引是壹個db,文檔是壹行數據,字段是表的列,映射是表的定義,文檔類型是表。
事實上,文檔類型的概念最初使作者感到困惑。其實是為了更好的查詢。舉個簡單的例子,壹個索引,也許我們想對某些數據使用壹種查詢方法,對其他數據使用另壹種查詢方法,所以有兩種類型。然而,這種情況不應該發生在我們的項目中,因此壹個索引下通常只有壹個類型。
在服務層面,主要有:
節點:服務器實例。
集群:多個節點組成壹個集群。
分片:數據分片,壹個索引可能存在於多個分片中,不同的分片可能在不同的節點中。
副本:碎片的備份有壹個主碎片,其他的稱為副本:碎片。
Elasticsearch之所以能動態重分,是因為它壹開始就預分配了多個分片(好像是1024),然後分片遷移數據。這種做法在分布式領域實際上非常常見。codis使用1024插槽進行數據遷移。
由於任何索引都可以配置多個副本,因此通過冗余備份來確保數據安全,副本也可以分擔讀取壓力,類似於MySQL中的slave。
Restful API
Elasticsearch提供Restful API並使用json格式,這使得與外界的交互非常方便。盡管Elasticsearch的客戶端很多,但作者仍然輕松地為項目編寫了壹個簡單的客戶端,這再次證明了Elasticsearch的使用確實很容易。
Restful界面非常簡單。url代表壹個特定的資源,例如/blog/article/1,這意味著壹個索引為blog、類型為article、id為1的文檔。
並且我們使用http標準方法來操作這些資源,如POST添加、PUT更新、GET獲取、DELETE刪除和HEAD來判斷它們是否存在。
在這裏,我推薦httpie,這是壹個非常強大的http工具。個人認為它比curl更有用,幾乎是命令行調試Elasticsearch的完美搭配。
使用httpie的壹些示例:
#創建
http POST:9200/blog/article/1 title =“hello elastic search“tags:=‘【“elastic search“】‘。
#獲得
http GET:9200/blog/article/1
#更新
http PUT:9200/blog/article/1 title =“hello elastic search“tags:=‘【“elastic search“,“hello“】‘。
#刪除
http DELETE:9200/blog/article/1
#存在
http HEAD:9200/blog/article/1
索引和搜索
盡管Elasticsearch可以自動確定字段的類型並建立適當的索引,但作者仍然建議設置相關的索引規則,以便更好地服務於後續的搜索。
我們通過自定義映射來設置不同字段的索引規則。
對於搜索,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解決了最小行圖像的問題,因此我對elasticsearch-river-mysql的項目有很好的印象。我剛決定自己寫壹篇。
為什麽我決定自己寫壹本呢?不是因為我喜歡做輪子。主要原因是我們不僅可以在Elasticsearch上使用這個MySQL syncer服務(增量獲取MySQL數據並將其更新到相關系統),還可以在其他服務上使用它,例如緩存。所以我實際上想實現的是壹個通用的MySQL syncer組件,但現在我主要關註Elasticsearch。
項目代碼為here go-mysql-elasticsearch,第壹階段開發已經完成,正在進行內部對接測試。
go-mysql-elasticsearch的原理非常簡單。首先使用mysqldump獲取當前MySQL數據,然後通過此時binlog的名稱和位置獲取增量數據。
壹些限制:
Binlog必須采用基於行的格式。事實上,我們不需要擔心這種格式的binlog占用太多硬盤空間。在MySQL 5.6之後,GTID模式推薦使用基於行的格式,並且通常我們控制SQL語句的質量,並且不允許我們壹次更改太多行數據。
需要同步的表最好是innodb引擎,這樣mysqldump就不會妨礙寫操作。
需要同步的表必須有主鍵。好吧,如果壹個表沒有主鍵,作者真的會懷疑設計這個表的學生的編程水平。也不建議使用多列主鍵,作者也不打算在現階段支持它們。
不要動態更改需要同步的表結構。Elasticsearch只能支持動態添加字段,不支持動態刪除和更改字段。壹般來說,如果涉及alter table,則證明之前的設計不合理,對未來擴展的預測不足。
更詳細的解釋,等到作者完成go-mysql-elasticsearch的開發並在生產環境中通過測試後再補充。
摘要
最近壹周,作者花了很多時間在Elasticsearch上,現在是壹個基本的介紹。其實筆者認為對於壹個自己不懂的技術,找壹個靠譜的資料(官方文檔或者入門書籍),在資料上痛苦地敲代碼,不懂就問谷歌,最後在實際項目中使用。即使這項技術是初步掌握的,當然,妳也必須努力才能掌握它。
現在只是覺得Elasticsearch很美,上線後肯定會有漏洞。那時候,我只能慢慢填。換句話說,我是否有必要學習java,這樣我就不會在那時閱讀代碼。:-)