閱讀46 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Solr集群架構概述及delta-import詳細配置

背景

由於項目原因,重新熟悉了下Solr,版本為3.6,搭建了主從Solr服務,並使用DIH從RDBMS數據源增量更新索引。

其實也沒什麼技術含量,就是簡單做個總結,分別從部署架構增量更新兩個方麵說明下。


Solr Replication

solr的主從其實是他的replication集群,從本質上說是通過ReplicationHandler來實現的,除了solr server之間可以互相同步之外,每個solr實例內部的core之間也是可以實現同步的,而能自身同步自身的實例稱為Repeater,它的存在是為了分擔master的同步開銷,即由它來同步master裏需要向外同步的core,然後所有的slave都從Repeater處同步相應的core。


具體配置方麵,master的solrconfig.xml裏的requestHandler配置為:

<requestHandler name="/replication" >
	<lst name="master">
		<str name="replicateAfter">startup</str>
		<str name="replicateAfter">commit</str>
		<str name="backupAfter">optimize</str>
		<str name="confFiles">schema.xml,stopword.dic,db-data-config.xml,dataimport.properties</str>
		<str name="commitReserveDuration">00:01:00</str>
	</lst>
</requestHandler>
在confFiles裏可以指定在同步過程中,slave需要一並同步過去的文件。slave端 solrconfig.xml裏的配置為:

<requestHandler name="/replication" >
	<lst name="slave">
		<str name="masterUrl">https://yf-rd-crm-cdc-db06.yf01.baidu.com:8888/solr/core0/replication</str>
		<str name="pollInterval">00:00:20</str>
		<str name="compression">internal</str>
		<str name="httpConnTimeout">5000</str>
		<str name="httpReadTimeout">10000</str>
	</lst>
</requestHandler>
其中pollInterval是發出同步請求的間隔時間,上述配置為每20s會去sync一次。後麵的http參數都是默認值。對slave和master來說,主要的配置不同就在這個handler裏,其他部分可以一致。我的solr主從比較簡單,大致如下。


如果對solr的搜索還有分片和負載均衡的要求,可以參考下solr4.0之後支持的SolrCloud,適合 high scale, fault tolerant, distributed indexing and search capabilities。我沒有選擇SolrCloud,主要原因是數據量也不是很大,不需要分片。本來想參考SolrCloud,看能不能為請求的負載均衡提供些什麼優勢,後來還是放棄了,負載這塊在solrj的搜索服務裏簡單做了下輪訓。網上看到也有人用Nginx為多個Tomcat容器做負載均衡,不過這個出發點和架構上的層次又有些不一樣。


Solr DataImportHandler

DataImportHandler可以為solr的索引配置數據源,我的數據源是mysql,基本配置可以參考SolrDoc裏的內容。不重複。

主要的坑在需要在web.xml裏添加下麵這個配置

<listener>
   <listener-class>org.apache.solr.handler.dataimport.scheduler.ApplicationListener</listener-class>
</listener>
但是這個類並不存在於solr的主要幾個包裏,需要額外導入,包下載鏈接在這裏。需要在webapps/solr.war下的WEB-INF/lib裏添加這個包,還要添加下dist下的兩個dataimporthandler有關的兩個jar。此外把上麵的listener配置添加到WEB-INF/web.xml內。特別注意的是,需要jdk7才能正常啟動,否則會報錯。

具體DIH相關的配置再詳細列一下,首先在solrconfig.xml裏配置Handler:

<requestHandler name="/dataimport" >
	<lst name="defaults">
		<str name="config">db-data-config.xml</str>
	</lst>
</requestHandler>
具體db-data-config.xml裏是sql邏輯和映射field,放在core/conf內,

<dataConfig>
	<dataSource type="JdbcDataSource" driver="com.mysql.jdbc.Driver"
		url="jdbc:mysql://ip:port/db_name"
		user="root" password="root" />
	<document name="tb_core">
		<entity name="tb_core_table" pk="table_id"
			query="select table_id, code, name, description, freq_id, bytes, first_date, owner, secret_level, charset_id, field_term, 
                            line_term, null_format, subj_id, gmt_modify from tb_core_table"
			deltaQuery="select table_id, code, name, description, freq_id, bytes, first_date, owner, secret_level, charset_id, field_term, 
                            line_term, null_format, subj_id, gmt_modify from tb_core_table where gmt_modify > '${dataimporter.last_index_time}'">
			<field column="table_id" name="table_id" />
			<field column="code" name="code" />
			<field column="name" name="name" />
			<field column="description" name="description" />
			<field column="description" name="subject_path" />
			<field column="freq_id" name="freq_id" />
			<field column="bytes" name="bytes" />
			<field column="first_date" name="first_date" />
			<field column="owner" name="owner" />
			<field column="secret_level" name="secret_level" />
			<field column="charset_id" name="charset_id" />
			<field column="field_term" name="field_term" />
			<field column="line_term" name="line_term" />
			<field column="null_format" name="null_format" />
			<field column="subj_id" name="subj_id" />
			<field column="gmt_modify" name="entity_modify" />
			<entity name="tb_core_column" pk="col_id"
				query="select col_id, table_id, code, name, description, gmt_modify from tb_core_column where table_id='${tb_core_table.table_id}'"
				deltaQuery="select col_id, table_id, code, name, description, gmt_modify from tb_core_column where gmt_modify > '${dataimporter.last_index_time}'"
				parentDeltaQuery="select table_id, code, name, description, freq_id, bytes, first_date, owner, secret_level, charset_id, field_term, 
                                    line_term, null_format, subj_id, gmt_modify from tb_core_table where table_id = ${tb_core_column.table_id}">
				<field column="col_id" name="column_id" />
				<field column="code" name="column_code" />
				<field column="name" name="column_name" />
				<field column="description" name="column_description" />
				<field column="gmt_modify" name="column_modify" />
			</entity>
		</entity>
	</document>
</dataConfig>
上麵的邏輯裏,table和column是一對多的關係,而兩個table內都有最近更新時間字段(gmt_modify),任何一方的更新都要觸發整個索引的增量更新,所以這是一個嵌套的例子。在SolrDoc裏也有類似的嵌套寫法,相對而言屬於delta-import稍微高級些的寫法。大家可以參考下。

<dataConfig>
    <dataSource driver="org.hsqldb.jdbcDriver" url="jdbc:hsqldb:/temp/example/ex" user="sa" />
    <document>
            <entity name="item" pk="ID" query="select * from item"
                deltaImportQuery="select * from item where ID=='${dih.delta.id}'"
                deltaQuery="select id from item where last_modified > '${dih.last_index_time}'">
                <entity name="feature" pk="ITEM_ID"
                    query="select DESCRIPTION as features from FEATURE where ITEM_ID='${item.ID}'"
                    deltaQuery="select ITEM_ID from FEATURE where last_modified > '${dih.last_index_time}'"
                    parentDeltaQuery="select ID from item where ID=${feature.ITEM_ID}"/>
            <entity name="item_category" pk="ITEM_ID, CATEGORY_ID"
                    query="select CATEGORY_ID from item_category where ITEM_ID='${item.ID}'"
                    deltaQuery="select ITEM_ID, CATEGORY_ID from item_category where last_modified > '${dih.last_index_time}'"
                    parentDeltaQuery="select ID from item where ID=${item_category.ITEM_ID}">
                <entity name="category" pk="ID"
                        query="select DESCRIPTION as cat from category where ID = '${item_category.CATEGORY_ID}'"
                        deltaQuery="select ID from category where last_modified > '${dih.last_index_time}'"
                        parentDeltaQuery="select ITEM_ID, CATEGORY_ID from item_category where CATEGORY_ID=${category.ID}"/>
            </entity>
        </entity>
    </document>
</dataConfig>
最重要的是,在solr_home/conf內需要一個負責調度的文件:dataimport.properties(不同於core/conf下的dataimport.properties,那個dataimport.properties會自動生成,記錄的是最近一次更新的時間)

#################################################
#                                               #
#       dataimport scheduler properties         #
#                                               #
#################################################

#  是否同步功能
#  1 - 開啟 ; 否則不開啟
syncEnabled=1

# 需要同步的solr core
syncCores=core0

#  solr server名稱或ip地址
#  默認為localhost
server=localhost

#  solr server端口
#  默認80
port=8888

# webapp name
webapp=solr

#  application context
# webapp=metadata-search

#  同步URL參數 
params=/dataimport?command=delta-import&clean=false&commit=true

#  調度區間
#  默認30分鍾
interval=1
這部分就需要開頭講的
org.apache.solr.handler.dataimport.scheduler.ApplicationListener
的配置,否則啟動後,之前的xml是不生效的。


Solr Server服務架構

結合Solr更新、主從和內部的一些主要模塊,畫了一個服務架構圖如下。



(全文完)


最後更新:2017-04-03 12:53:49

  上一篇:go svn插件安裝
  下一篇:go javap淺析-書籍第3章的手寫稿樣稿