一. 概述 大量的資料存放區在MongoDB上,需要快速搜尋出目標內容,於是搭建Solr服務。 另外一點,用Solr索引資料後,可以把資料用在不同的項目當中,直接向Solr服務發送請求,返回xml、json等形式的內容,使得對資料的使用更靈活。 對於MongoDB與Solr的描述不在這裡闡釋了,本文旨在給大家提供整個Solr與MongoDB接合的方法,實現即時的增量索引。 MongoDB的官網:http://www.mongodb.org/ Solr項目的首頁:http://lucene.apache.org/solr/ 二. 尋找解決方案 既然有了目標是講Solr跟MongoDB接到一起,那麼就開始想想解決的方案。 網上搜了一些資料之後,匯總了下面三個方案: 1. 使用Solr的DataImport功能(Data Import) 我們先來看看Solr Wiki上對於DataImport功能的描述http://wiki.apache.org/solr/DataImportHandler Most applications store data in relational databases or XML files and searching over such data is a common use-case.The DataImportHandler is a Solr contrib that provides a configuration driven way to import this data into Solr in both "full builds" and using incremental delta imports. 對於儲存在關係型資料庫及XML上的資料,Solr提供了DataImportHandler去實現全量和增量索引。 啥。人家沒說支援NoSQL啊,不信,我看清楚一點。 Wiki中的內容只給出了Usage with RDBMS 和 Usage with XML/HTTP Datasource,貌似Solr目前是不支援對於NoSQL的DataImport的。 有興趣的朋友可以嘗試給Solr添加一個Mongo的DataImportHandler,可能還要寫底層的Mongo驅動,工程量可能很大。 關鍵是這個方案不可控,成本可能會很大,因此我就不採取這種方式了。 在這裡給大家分享一篇文章,Solr與MySQL整合指南 確實DataImport這個功能還是比較強大的,而且對MySQL也支援得很好,本人嘗試一下將Solr跟MySQL整合起來,配置過程也很簡單。 不過MySQL不是本文的重點,跑題了,因此只是嘗試了一下,沒有深入。 2. 使用指令碼語言讀取MongoDB中的資料(Script Update) 說白了就是讀取整個Collection中的資料,遍曆。 這種方案是最直觀的,但不優雅,複用性、可維護性低, 最嚴重的問題在於效能,當數量級在百萬以下,那還是可以接受的,一旦資料繼續增長,那效能問題就凸顯出來了。 然而要是你還想用這種方案,那這裡還有一個需要考慮的問題,你是打算每次遍曆的時候對Solr進行全量還是增量索引呢。 全量的話就直接overwrite,事情也好辦;增量的話,Mongo中刪除了的資料你咋整呢。 總而言之,不推薦這種方案,它的複雜度問題很明顯,無論是時間上還是空間上。 3. 使用MongoDB的oplog功能(Oplog Update) MongoDB支援叢集,叢集中的執行個體進行通訊,很自然地想到它們會記錄log,在MongoDB中稱之為oplog(operation log),類似與MySQL的binlog。 我們可以看看MongoDB官網上對oplog的描述 http://docs.mongodb.org/manual/reference/program/mongooplog/ 如果現在你還想用上面方案2的話,那oplog的存在必然是對你的工作帶來極大便利的。 其一,oplog是即時記錄的,配合tailable cursor,可以實現即時的更新Solr索引,見http://derickrethans.nl/mongodb-and-solr.html 其二,實現優雅,增量的新增刪除的判斷時間複雜度變為O(1) 看到這裡,你想用oplog來實現Solr與MongoDB的整合,那需要理清下面幾個問題: (1)mongooplog如何開啟,怎麼配置才適合 (2)Mongo Tailable Cursor是怎麼一回事 (3)使用什麼語言,選擇合適的Solr Client (4)伺服器宕機恢複後的處理 三. 最終方案,mongo-connector 當我性高彩烈地動手實現方案3的時候,我看到了這個http://blog.mongodb.org/post/29127828146/introducing-mongo-connector 竟然找到了一個mongo-solr的connector,當時那個心情真叫欣喜若狂啊。 它完全就是方案3的實現啊。提到的問題它都解決了,而且使用Python正好適合這個項目,一切來得太突然。 Git地址:https://github.com/10gen-labs/mongo-connector 但是配置的過程都搞了我很久,後文將整個過程記錄下來 四. 項目環境及工具版本 在本地測試,伺服器:Windows7 32-bit MongoDB:mongodb-win32-i386-2.4.5 Tomcat 6 Python:2.7.4 Solr:4.5.1 mongo-connector:沒有提供版本號碼 Python pysolr模組 Python pymongo模組 Python lxml模組:lxml-3.2.3.win32-py2.7 可能還需要一些模組,但由於我在之前已經安裝了,沒有列舉出來。如果啟動並執行過程中報module not found,就去安裝吧~ 五. Solr端準備 這裡預設你已經部署Solr成功,詳細的部署過程自行Google。 這裡主要是講述與本次測試相關的配置。 使用的是solr example中的multicore例子,以其中的core0為例子 schema.xml檔案如下:修改_id與Mongo對應,只留下一個name欄位,為String類型 其它的配置不需要修改 把它放到Tomcat中運行吧,檢查是否已經配置成功 六. MongoDB端準備 看到mongo-connector項目中的說明, Since the connector does real time syncing, it is necessary to have MongoDB running, although the connector will work with both sharded and non sharded configurations. It requires a replica set setup. 就算我們開啟了oplog也不行,還需要在Mongo中啟動一個replica set 1. 配置replica set (1) 我的MONGO_HOME為 D:\mongodb 分類樹如下: -rs (d) |----db (d) mongo資料檔案檔案存放的目錄 |----rs1 (d) rs1執行個體資料檔案存放的目錄 |----rs2 (d) rs2執行個體資料檔案存放的目錄 |----log (d) log檔案存放的目錄 |----rs1.log (f) rs1執行個體的log檔案 |----rs2.log (f) rs2執行個體的log檔案 |----mongod-rs1.bat rs1執行個體的啟動指令碼 |----mongod-rs2.bat rs2執行個體的啟動指令碼 mongod-rs1.bat內容如下: D:\mongodb\bin\mongod --port 27001 --oplogSize 100 --dbpath db\rs1 --logpath log\rs1.log --replSet rs/127.0.0.1:27002 --journal pause mongod-rs2.bat內容如下: D:\mongodb\bin\mongod --port 27002 --oplogSize 100 --dbpath db\rs2 --logpath log\rs2.log --replSet rs/127.0.0.1:27001 --journal pause (2)執行兩個指令碼,啟動兩個mongod執行個體 (3)但這時它們還沒組成一個replica set,還需要進行配置,開啟mongo,連上localhost:27001,也就是執行個體rs1 至此,配置完成。 七. mongo-connector準備 如果是在mongo example中的multicore預設的配置上修改的話,訪問http://localhost:8080/solr/core0/admin/luke?show=Schema&wt=json 應該是能看到JSON形式的core0的schema 開啟mongo_connector/doc_managers/solr_doc_manager.py 進行如下修改:1.從util引入verify_url;2. ADMIN_URL修改為擷取Solr核core0的JSON形式schema的URL的後半部分,因為要根據schema中的fields進行索引 在Solr多核的情況下啟動mongo-connector,會報出Solr URL訪問錯誤,它期望你傳入http://localhost:8080/solr, 但http://localhost:8080/solr/core0才是實際起作用的,因此我們需要傳入這個作為BASE_URL 解決辦法如下:屏蔽掉url檢查就行了 接下來就是啟動mongo-connector了,啟動命令如下: C:\Users\gmuser\Desktop\mongo_connector>python mongo_connector.py -m localhost:2 7001 -t http://localhost:8080/solr/core0 -o oplog_progress.txt -n test.test -u _id -d ./doc_managers/solr_doc_manager.py -m Mongod執行個體的訪問路徑 -t Solr的BASE_URL -o 記錄oplog處理時間戳記的檔案 -n mongo命名空間,是監聽哪個database哪個collection的設定,以逗號分隔多個命名空間,這裡是監聽test庫中的test集合 -d 就是處理doc的py檔案 啟動結果如下:說明你的配置已經成功了 八. 測試增量索引 先看看Solr中core0的狀態:現在是沒有記錄的,Num Docs為0 往MongoDB中插入一條資料:需要包含name欄位,還記得我們上面的schema.xml嗎。 查看mongo-connector的輸出:update了一條記錄 看看Solr現在的狀態:我們看到了剛才插入的 |