Solr Replication
此文档描述Java实现的索引复制(备份),其基于HTTP工作并且包含在Solr1.4中。关于自Solr1.1以来基于ssh/rsync的备份功能的信息请参考CollectionDistribution.注意对于Solr4.0中的SolrCloud,复制将以推送模式(push-style)完成,这种索引复制将不再需要。
特性
备份无需外部脚本;
只在solrconfig.xml中配置;
也可备份文件;
跨平台使用相同的配置;
不依赖于OS相关的硬链接;
与Solr紧密整合,一个管理页面提供了对备份各方面的精细管理。
配置
此新的基于Java的备份功能实现为一个RequestHandler. 配置备份因此相似于任何普通的RequestHandler.
Master
<requestHandlername="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<!--Replicate on 'startup' and 'commit'. 'optimize' is also a validvalue for replicateAfter. -->
<str name="replicateAfter">startup</str>
<str name="replicateAfter">commit</str>
<!--Create a backup after 'optimize'. Other values can be 'commit','startup'. It is possible to have multiple entries of this config string. Note that this is just for backup,replication does not require this. -->
<!-- <str name="backupAfter">optimize</str>-->
<!--If configuration files need to be replicated give the names here,separated by comma -->
<str name="confFiles">schema.xml,stopwords.txt,elevate.xml</str>
<!--The default value of reservation is 10 secs.See the documentationbelow . Normally , you should not need to specify this -->
<str name="commitReserveDuration">00:00:10</str>
</lst>
<!-- keep only 1 backup. Usingthis parameter precludes using the "numberToKeep" request parameter.(Solr3.6 / Solr4.0)-->
<!-- (For this to work in conjunction with "backupAfter"with Solr 3.6.0, see bug fix https://issues.apache.org/jira/browse/SOLR-3361)-->
<str name="maxNumberOfBackups">1</str>
</requestHandler>
注意:
·如果你的commits非常频繁并且网络很慢,你可以调节一个额外的属性
<str name="commitReserveDuration">00:00:10</str>.
这大约是从master到slave下载5MB所花费的时间。默认是10秒。
·即便你使用replicateAfter的startup选项,如果你想在未来commits/optimizes时触发复制,也必须要有commit/optimize存在。如果只给出startup选项,在开始的第一次后,接下来的commits/optimizes完成后复制将不会被触发。
复制solrconfig.xml
在master服务上的solrconfig.xml中,在replication request handler里,包含如下的一行:
<str name="confFiles">solrconfig_slave.xml:solrconfig.xml,x.xml,y.xml</str>
这确保了本地的配置’solrconfig_slave.xml’在slave上将以’solrconfig.xml’存储。所有其他文件将以原始名存储。
Slave
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="slave">
<!--fully qualified url to the master core. It is possible to pass on this as a request param for the fetchindex command-->
<str name="masterUrl">http://master_host:port/solr/corename</str>
<!--Interval in which the slave should poll master .Format is HH:mm:ss . If this is absent slave does not poll automatically.
But a fetchindex can be triggered from the admin or the http API -->
<str name="pollInterval">00:00:20</str>
<!-- THE FOLLOWING PARAMETERS ARE USUALLY NOT REQUIRED-->
<!--to use compression while transferring the index files. The possible values are internal|external
if the value is 'external' make sure that your master Solr has the settings to honour the accept-encoding header.
see here for details http://wiki.apache.org/solr/SolrHttpCompression
If it is 'internal' everything will be taken care of automatically.
USE THIS ONLY IF YOUR BANDWIDTH IS LOW . THIS CAN ACTUALLY SLOWDOWN REPLICATION IN A LAN-->
<str name="compression">internal</str>
<!--The following values are used when the slave connects to the master to download the index files.
Default values implicitly set as 5000ms and 10000ms respectively. The user DOES NOT need to specify
these unless the bandwidth is extremely low or if there is an extremely high latency-->
<str name="httpConnTimeout">5000</str>
<str name="httpReadTimeout">10000</str>
<!-- If HTTP Basic authentication is enabled on the master, then the slave can be configured with the following -->
<str name="httpBasicAuthUser">username</str>
<str name="httpBasicAuthPassword">password</str>
</lst>
</requestHandler>
注意:如果你不使用cores,你只要简单地在上面的masterUrl中忽略”corename”参数。为确保url是正确的,只要将url在浏览器中打开,你必须得到一个OK的回应。
建立一个复制器(Setting up aRepeater)
不影响性能,一个Master也只能支持这么多Slaves.一些机构已经跨多数据中心部署slave服务器了。如果每个slave都从一个远程数据中心下载索引,可能会消耗太多的网络带宽。为了避免在类此情形下的性能下降,你可以配置一个或多个slaves为repeaters.一个Repeater就是一个既作为master也作为slaver的节点。
。将一个服务配置为repeater,需要在solrconfig.xml文件中的ReplicationHandler请求处理内包含master和slave的配置lists.
。确保在repeater内有replicateAfter 'commit'设置,即便在主master中replicateAfter被设置为optimize.这是因为在repeater(或任何slave)上,只有在索引下载完成后commit才被调用。而Optimize在slaves上从来不会被调用。
。可选的,你可以通过’compression’参数(见slave小节)来配置repeater从master取得压缩的文件,以减少索引下载时间。
一个repeater的示例配置:
<requestHandler name="/replication" class="solr.ReplicationHandler">
<lst name="master">
<str name="replicateAfter">commit</str>
<str name="confFiles">schema.xml,stopwords.txt,synonyms.txt</str>
</lst>
<lst name="slave">
<str name="masterUrl">http://master.solr.company.com:8080/solr</str>
<str name="pollInterval">00:00:60</str>
</lst>
</requestHandler>
在一个节点使master/slave生效或失效 (enable/disable master/slave in a node)
如果一个服务需要从slave转变成master,或你希望在master和slave使用相同的solrconfig.xml, 如下做,
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<str name="enable">${enable.master:false}</str>
<str name="replicateAfter">commit</str>
<str name="confFiles">schema.xml,stopwords.txt</str>
</lst>
<lst name="slave">
<str name="enable">${enable.slave:false}</str>
<str name="masterUrl">http://master_host:8983/solr</str>
<str name="pollInterval">00:00:60</str>
</lst>
</requestHandler>
注意:确保为enable.master和enable.slave添加一个’false’默认值,否则部署会失败,并且日志将显示Solr得到’.’而非正确的core实例目录。在Solr管理主界面,你将不会看到包含core名称的链接(点击唯一的链接,你将得到错误’missing core in path’)。
注意:如果部署OK但你仍看不到包含core名称的链接,可能会是权限问题(permission problem)。这通常发生在当你在APserver的默认webapps文件夹下设置实例目录。工作区需要要创建另外一个有良好权限的目录,并且将solr.xml放在那个目录的根目录中。编辑环境配置文件使solr/home指向那个目录。现在清除之前部署的webapp并重新部署。
当master启动了,传入-Denable.master=true并且在slave传入-Denable.slave=true. 代替的,这些值可以存储在solrcore.properties文件中,如下:
#solrcore.properties in master
enable.master=true
enable.slave=false
在slave中
#solrcore.properties in slave
enable.master=false
enable.slave=true
注意:每个core有它自己的solrcore.properties,位于它的实例目录中的conf目录下。
MultiCore的复制 (Replication with MultiCore)
添加replication requesthandler到每个core的solrconfig.xml (如,/usr/share/tomcat6/solr/CORENAME/conf/solrconfig.xml). 你可以使用${solr.core.name}以避免在你的配置中硬编码core的名称。
Master配置保持不变:
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<str name="replicateAfter">commit</str>
<str name="confFiles"> schema.xml,mapping-ISOLatin1Accent.txt,protwords.txt,stopwords.txt,synonyms.txt,elevate.xml</str>
</lst>
</requestHandler>
Slave只需要增加core.name
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="slave">
<str name="masterUrl">http://${MASTER_CORE_URL}/${solr.core.name}</str>
<str name="pollInterval">${POLL_TIME}</str>
</lst>
</requestHandler>
变量(如$POLL_TIME,$MASTER_CORE_URL)可以在每个core的solrcore.properties中定义。
复制仪表台 (Replication Dashboard)
显示如下信息
. 当前replication的状态
。百分比/已下载大小/将下载
。当前正在下载的文件
。已花时间/剩余时间
从dashboard可以进行下面的操作
. 使polling生效/失效
. 强制开始replication
. 终止正在进行的replication
它如何工作?
这项功能(Replication)依赖于Lucene的IndexDeletionPolicy特性。通过这个API,Lucene在每个commit/optimize将IndexCommits暴露为回调(callbacks)。一个IndexCommit暴露每次commit的文件。这使我们能确定需要被复制的文件。
对于传统的Solr,所有操作都通过RESTAPI. ReplicationHandler为它支持的所有操作暴露一个REST API。
当我commit或optimize时发生了什么?
当在master上完成commit/optimize时,ReplicationHandler读取每次commit的文件列表。这取决于配置中的’replicateAfter’参数,来决定这些文件何时从Lucene取得和存储。
Slave如何复制的?
master是完全不知道slaves的,slave持续轮询master(依赖’pollInterval’参数)来检查当前master的索引版本。如果slave发现master有一个更新的索引版本,便发起一个replication处理。步骤如下,
。Slave发起一个filelist命令获取文件列表。这个命令返回文件名列表,以及一些元数据(大小,最近修改,别名等)。
。slave检查自己的本地索引是否有那些文件。然后获取缺失的文件(命令名为’filecontent’)。这使用了一定制格式(于HTTP块编码同源)来下载文件的全部内容或部分。如果连接中间断开,下载会从失败的点重新开始。在任何点,在放弃replication前都会进行5次尝试。
。文件被下载到一个temp目录。因此如果slave或master在之间崩溃,不会损坏任何东西。只会中断当前的replication.
。在下载完成后,所有新文件被移动(‘mov’)到slave的活动索引目录,并且文件的时间戳与master的时间戳匹配。
。由slave的ReplicationHandler发起一个’commit’命令,然后新索引被加载了。
配置文件时如何复制的?
。将要复制的文件需要在’confFiles’参数中被显示提及。
。只有solr实例的’conf’目录中的文件被复制。
。文件仅同一个新的索引一起被复制。这意味着即便master中的一个(配置)文件被修改了,也只有在master有一个新的commit/optimize后才被同步。
。不像索引文件,时间戳足以判断它们是否一致,conf文件被以校验和(checksum)比较。如果校验和一致,那么(master和slave)上的schema.xml文件是相同的。
。Conf文件在被移动到原位置前也被下载到一个临时目录。老的文件被重命名并保持在同一个目录中。ReplicationHandler不会自动清除这些老的文件。
。如果一个replication下载了至少一个conf文件,一个core的重新加载被发起,而不是’commit’命令。
如果添加文档到slave或slave索引崩溃了会怎样?
如果文档被加到slave,那么slave不再与master保持同步。但是,在master有一个新的索引之前,它不会做任何事情来保持与master同步。当master上发生一次commit,master上的索引版本将变得与slave不同。Slave取得文件列表,并发现本地索引的一些文件(同名)有不同的大小/时间戳。这意味着master和slave有不兼容的索引。Slave将拷贝master的所有文件(这可能有优化空间,但这很少发生并可能不值得优化)到一个新的索引文件夹,并要求core从这个新的文件夹加载新的索引。
HTTP API
这些命令可以通过HTTP调用Replicationhandler
。获取master上最近的可复制索引:http://master_host:port/solr/replication?command=indexversion
。终止从master到slave的复制:http://slave_host:port/solr/replication?command=abortfetch
。如果服务上有提交的索引数据,则在master上创建一个备份,否则不做事。这在周期性备份时很有用。命令:http://master_host:port/solr/replication?command=backup
。也可以提供一个位置参数(如,&location=/foo/bar),表示备份写入的磁盘目录。
。指定参数”numberToKeep”来表示保留多少备份(包括这一个)。旧的备份将被自动删除。(i.e. &numberToKeep=2). (注意: 在Solr3.6,Solr4.0中,如果配置中指定了”maxNumberOfBackups”那么不能再指定这个参数)
。在slave上强制从master获取索引:http://slave_host:port/solr/replication?command=fetchindex
。可以传一个额外的属性’masterUrl’或其他属性如’compression’(或任何其他在<lstname=”slave”> 标签中指定的参数)来做从master的一次复制。这消除了在slave硬编码master的需求。
。关闭slave对修改的轮询:http://slave_host:port/solr/replication?command=disablepoll
。打开slave对修改的轮询:http://slave_host:port/solr/replication?command=enablepoll
。获得配置的所有细节和当前状态:http://slave_host:port/solr/replication?command=details
。获得索引的版本号:http://host:port/solr/replication?command=indexversion
。获得索引的lucene文件列表:http://host:port/solr/replication?command=filelist&indexversion=<index-version-number>
version number可以通过indexversion命令得到。
。关闭master对所有slave的备份:http://master_host:port/solr/replication?command=disablereplication
。打开master对所有slave的备份:http://master_host:port/solr/replication?command=enablereplication
。从master传输一个文件:http://master_host:port/solr/replication?command=filecontent&wt=filestream&indexversion=<index-version-number>
- 索引文件使用一个附加的参数file=<index-filename>,配置文件使用附加参数cf=<config-filename>.
- 文件内容被以定制流格式传输。
问题处理(Troubleshooting)
没有进行复制(replicating).管理界面显示索引版本但/replication?command=indexversion返回0.
尝试配置replicateAfter选项 startup.
<requestHandler name="/replication" class="solr.ReplicationHandler" >
<lst name="master">
<str name="replicateAfter">commit</str>
<str name="replicateAfter">startup</str>
<str name="replicateAfter">optimize</str>
<str name="confFiles">schema.xml,mapping-ISOLatin1Accent.txt,protwords.txt,stopwords.txt,synonyms.txt,elevate.xml</str>
</lst>