基于Golang將MongoDB的數據同步到Elasticsearch
Elasticsearch是一個分布式可擴展的實時搜索和分析引擎。它能幫助你搜索、分析和瀏覽數據。Elasticsearch 是一個基于Lucene實現的搜索服務器,用Java開發實現。它提供了RESTful web接口,并作為Apache許可條款下的開放源碼發布,能夠達到實時搜索,穩定,可靠,快速,安裝使用方便。
Elasticsearch關鍵概念
Cluster集群有相同集群名稱的節點Node的集合。集群中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對于集群內部來說的。es的一個概念就是去中心化,字面上理解就是無中心節點,這是對于集群外部來說的,因為從外部來看es集群,在邏輯上是個整體,你與任何一個節點的通信和與整個es集群通信是等價的。Cluster集群
Node節點
一個elasticsearch運行的實例。其實就是一個java進程。一般情況下,一臺機器運行在一臺機器上。
Shards分片
代表索引分片,es可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分布到不同的節點上。構成分布式搜索。分片的數量只能在索引創建前指定,并且索引創建后不能更改。
Replicas副本
代表索引副本,es可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高es的查詢效率,es會自動對搜索請求進行負載均衡。
Recovery恢復
代表數據恢復或叫數據重新分布,es在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啟動時也會進行數據恢復。
River
代表es的一個數據源,也是其它存儲方式(如:數據庫)同步數據到es的一個方法。它是以插件方式存在的一個es服務,通過讀取river中的數據并把它索引到es中,官方的river有couchDB的,RabbitMQ的,推ter的,Wikipedia的。River在1.5中棄用了,2.0 中移除了。
Gateway
代表es索引快照的存儲方式,es默認是先把索引存放到內存中,當內存滿了時再持久化到本地硬盤。gateway對索引快照進行存儲,當這個es集群關閉再重新啟動時就會從gateway中讀取索引備份數據。es支持多種類型的gateway,有本地文件系統(默認),分布式文件系統,Hadoop的 HDFS和amazon的s3云存儲服務。
Discovery.zen
代表es的自動發現節點機制,es是一個基于p2p的系統,它先通過廣播尋找存在的節點,再通過多播協議來進行節點之間的通信,同時也支持點對點的交互。
Transport
代表es內部節點或集群與客戶端的交互方式,默認內部是使用tcp協議進行交互,同時它支持http協議(json格式)、thrift、servlet、memcached、zeroMQ等的傳輸協議(通過插件方式集成)。
Index索引
Elasticsearch用來存儲數據的邏輯區域,它類似于關系型數據庫中的table概念。一個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。
本文不是介紹Elasticsearch的安裝配置文檔,這些文檔你可以在本文的參考資料中獲得, 而是筆者在項目中的實踐筆記。
我最近在開發過程中需要將Mongo數據庫中的文章進行索引, 避免直接對Mongo數據庫進行搜索導致的性能降低。基于Elasticsearch的手冊的描述,以及在一些大公司如推ter的應用的經驗,我選用它作為現在的項目的索引服務器。
現在的項目是Golang語言實現的,所以我調研的目標放在了Golang + MongoDB + Elasticsearch上面。
elasticsearch-river-mongodb是一個針對Mongo的elasticsearch river的插件。它從Mongo oplog中讀取信息,將Mongo集群中的數據導入到 elasticsearch 中。考慮到river被棄用,暫時不考慮這個方案。
mandeepm91在文章How To Sync Transformed Data from MongoDB to Elasticsearch with Transporter on Ubuntu 14.04提到了另外一個工具Transporter,這是一個相當好的工具,可以抽取Mongo單例或者Mongo集群的數據,然后使用otto框架進行Javascript處理,而且處理是通道式的。在調研中很容易的將Mongo數據庫導入到Elasticsearch。
不過我也沒有采用這個方案。因為我的項目中,對文章的增刪改的動作比較少,可以直接調用Elasticsearch的API進行操作。而且這樣可以做到數據的實時索引和查詢。
上面的方案多少會影響服務器的性能,有可能會block在Elasticsearch的API調用上。 所以我在增刪改文章時,將操作命令的log放入到一個消息服務器中(nsq或者kafka),然后在單獨的一臺服務器上接收消息并調用Elasticsearch的API。
參考資料
- https://www.digitalocean.com/community/tutorials/how-to-sync-transformed-data-from-mongodb-to-elasticsearch-with-transporter-on-ubuntu-14-04
- https://github.com/compose/transporter
- Elasticsearch 權威指南
- elasticsearch中文指南
- https://www.elastic.co/guide/en/elasticsearch/guide/current/_empty_search.html
- https://github.com/mattbaird/elastigo
- https://github.com/olivere/elastic
- https://github.com/richardwilly98/elasticsearch-river-mongodb
- http://baike.baidu.com/item/elasticsearch
- https://www.elastic.co/blog/deprecating-rivers
原文鏈接: http://colobu.com/2015/10/27/Sync-Transformed-Data-from-MongoDB-to-Elasticsearch/