背景
原來的樓盤庫的搜索時采用lucene為索引,并且每天定時重建索引,這樣編輯經常反映:修改和新增樓盤必須等到lucene定時重建后才能對外發布其搜索,并且無論樓盤有無修改,lucene都必須定時重建.經過小組討論決定使用mongodb代替現有的lucene作為樓盤庫的搜索,理由有以下幾點
1)mongodb可以自由的同步mysql的數據,不必受定時重建的影響
2)樓盤庫的搜索并沒有復雜的檢索分詞,查詢的語句和特點很適用mongodb
3)mongodb屬于分布式文檔存儲數據庫,有很好的擴展性,適用于以后的發展
4)經過壓力測試與lucene對比,mongodb在簡單查詢的性能表現上比lucene略有優勢
應用的工具及服務器
工具
1)MongoDB
2)Morphia,一個實現Java對象到MongoDB雙向映射的類庫
3)httpsqs,基于HTTP GET/POST協議的輕量級開源簡單消息隊列服務
必須用到的jar分別為:httpsqs4j.jar,mongo-2.2.jar,morphia-0.97.jar
服務器
正式服務器,ip外網220.181.333.333,內網192.168.86.333,端口27017,只支持內網連接
測試服務器,ip外網220.181.333.333
1)Spring整合Morphia

com.netease.product.mongodb.base.MorphiaBean 繼承 com.google.code.morphia.Morphia ,并重載createDatastore()
mapPackage為指定需要注解的domain包
isMongo為自定義的標志位

創建db的命名為product_house_ +city 對應樓盤的城市
(注:詳見MorphiaBean.java,mongodb.xml)
2)domain的設計
morphia的所有注解domain類全部存放于com.netease.product.mongodb.domain下
其中ProductInfo為@Entity實體類,其余都為@Embedded嵌入類,嵌入類需要再實體類中聲明,如

這樣我們在應用中只需對ProductInfo這個實體類進行操作即可.
(注:其他注解 @Id指定為主鍵,@Indexed為該字段創建索引,@Transient忽略該字段)
3)創建MongoDB記錄
對外提供創建的接口為com.netease.product.mongodb.index.ProductIndex.createProduct(Product product)

內部類DataMovement主要提供對ProductInfo接口字段進行整合特別處理的功能,如別名,網友打分,銷售狀態排序,這
些需要特別處理的字段都在此定義
4)查詢MongoDB接口
對外統一提供的查詢接口為com.netease.product.mongodb.search.ProductSearch
public RowSet getResults(Row param,String[] sort, boolean isOR, int beginNum, int size)
參數:
param為一組key value查詢條件,如
并且param的各種字段特殊處理寫在ProductSearch.paramHandle(Row param)
sort為排序條件,其中desc需加"-"符號,asc則不用,如 new String[]{"-price"} ,按價格降序排列
isOR為是否或條件查詢,目前只提供樓盤名和樓盤拼音的or查詢,這部分將在下一階段進一步完善
(注:詳見com.netease.product.mongodb.search.ProductSearch)
5)切換MongoDB和lucene
在SearchAction中保持原來的接口,并新建SearchMongoAction,在每個SearchAction接口前部都新加
通過狀態位進行判斷,如mongodb出現問題,可以將狀態位切換回lucene的狀態位,減少mongodb初步上線時對系統的影
響
5)使用隊列同步Mysql和MongoDB
(注:httpsqs和spring的整合見httpsqs.html和HttpSQSBean.java)
對ProductDao中的更新樓盤的method進行攔擊,將其更新的productid插入httpsqs隊列中,調用
QueueBean.pushQueueByCity(String id)放入隊列
配置定時器TimeService.getQueue()取出隊列,并根據隊里的productid進行mysql和mongodb的同步
原來的樓盤庫的搜索時采用lucene為索引,并且每天定時重建索引,這樣編輯經常反映:修改和新增樓盤必須等到lucene定時重建后才能對外發布其搜索,并且無論樓盤有無修改,lucene都必須定時重建.經過小組討論決定使用mongodb代替現有的lucene作為樓盤庫的搜索,理由有以下幾點
1)mongodb可以自由的同步mysql的數據,不必受定時重建的影響
2)樓盤庫的搜索并沒有復雜的檢索分詞,查詢的語句和特點很適用mongodb
3)mongodb屬于分布式文檔存儲數據庫,有很好的擴展性,適用于以后的發展
4)經過壓力測試與lucene對比,mongodb在簡單查詢的性能表現上比lucene略有優勢
應用的工具及服務器
工具
1)MongoDB
2)Morphia,一個實現Java對象到MongoDB雙向映射的類庫
3)httpsqs,基于HTTP GET/POST協議的輕量級開源簡單消息隊列服務
必須用到的jar分別為:httpsqs4j.jar,mongo-2.2.jar,morphia-0.97.jar
服務器
正式服務器,ip外網220.181.333.333,內網192.168.86.333,端口27017,只支持內網連接
測試服務器,ip外網220.181.333.333
1)Spring整合Morphia

com.netease.product.mongodb.base.MorphiaBean 繼承 com.google.code.morphia.Morphia ,并重載createDatastore()
mapPackage為指定需要注解的domain包
isMongo為自定義的標志位

創建db的命名為product_house_ +city 對應樓盤的城市
(注:詳見MorphiaBean.java,mongodb.xml)
2)domain的設計
morphia的所有注解domain類全部存放于com.netease.product.mongodb.domain下
其中ProductInfo為@Entity實體類,其余都為@Embedded嵌入類,嵌入類需要再實體類中聲明,如

這樣我們在應用中只需對ProductInfo這個實體類進行操作即可.
(注:其他注解 @Id指定為主鍵,@Indexed為該字段創建索引,@Transient忽略該字段)
3)創建MongoDB記錄
對外提供創建的接口為com.netease.product.mongodb.index.ProductIndex.createProduct(Product product)

內部類DataMovement主要提供對ProductInfo接口字段進行整合特別處理的功能,如別名,網友打分,銷售狀態排序,這
些需要特別處理的字段都在此定義
4)查詢MongoDB接口
對外統一提供的查詢接口為com.netease.product.mongodb.search.ProductSearch
public RowSet getResults(Row param,String[] sort, boolean isOR, int beginNum, int size)
參數:
param為一組key value查詢條件,如
row.put("district !=", district);不等于關系,將符號連接在key后面
并且param的各種字段特殊處理寫在ProductSearch.paramHandle(Row param)
sort為排序條件,其中desc需加"-"符號,asc則不用,如 new String[]{"-price"} ,按價格降序排列
isOR為是否或條件查詢,目前只提供樓盤名和樓盤拼音的or查詢,這部分將在下一階段進一步完善
(注:詳見com.netease.product.mongodb.search.ProductSearch)
5)切換MongoDB和lucene
在SearchAction中保持原來的接口,并新建SearchMongoAction,在每個SearchAction接口前部都新加
if(Constant.FACADE.getMorphiaBean().getIsMongo()==1){ //是否使用mongo進行查詢
return new SearchMongoAction().xfs(this.getRequest(), this.getResponse());
}
return new SearchMongoAction().xfs(this.getRequest(), this.getResponse());
}
通過狀態位進行判斷,如mongodb出現問題,可以將狀態位切換回lucene的狀態位,減少mongodb初步上線時對系統的影
響
5)使用隊列同步Mysql和MongoDB
(注:httpsqs和spring的整合見httpsqs.html和HttpSQSBean.java)
對ProductDao中的更新樓盤的method進行攔擊,將其更新的productid插入httpsqs隊列中,調用
QueueBean.pushQueueByCity(String id)放入隊列
配置定時器TimeService.getQueue()取出隊列,并根據隊里的productid進行mysql和mongodb的同步