Solr 1.4 以后,可以使用基于 http 的同步方式。之前基于 ssh/rsync 的同步方式已经停止维护。还有一种基于 SolrCloud 的方式:https://cwiki.apache.org/confluence/display/solr/SolrCloud
这里只介绍 ReplicationHandler 基于 http 的方式。
官方文档:
该方式的优点
- 不需要其它脚本
- 只需要在 solrconfig.xml 中进行配置
- Master / Slave 配置都较小
- 同样的配置可跨平台使用
- 不依赖操作系统的硬链接
- 提供WEB页面对结构进行查看及管理
配置方式
主从结构的配置和其它的 RequestHandler 一样。
Master 配置
编辑 solrconfig.xml
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler name="/replication" class="solr.ReplicationHandler" >
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="master">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="replicateAfter">startup</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="replicateAfter">commit</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="confFiles">schema.xml,stopwords.txt,elevate.xml</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="commitReserveDuration">00:00:10</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="maxNumberOfBackups">1</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler>
注意事项
- 如果当前的 Master 执行 commit 之类的操作很频繁, 或者网络带宽不是很好,建议把 commitReserveDuration 的值调大一点。
- 如果想在启动后,每次 commit / optimize 时都进行同步,则必须要在 replicateAfter 配置中加上 startup, 以及 commit / optimize. 如果只加了 startup, 同步操作在后续的 commit / optimize 都不会触发,只有在启动的时候才会发生.
Slave 配置
文件同步
在 Master 的配置文件中有一个 confFiles 项,可以进行文件的同步。这里可以按如下方式使用:
"confFiles"
>solrconfig_slave.xml:solrconfig.xml,x.xml,y.xml
这样,Master 上面的 solrconfig_slave.xml 会被保存为 Slave 机器上的 solrconfig.xml, 其它文件:x.xml, y.xml 保持自己原文件名不变。
因为 confFiles 可以通过 “:” 进行分隔,冒号前面是 Master 上的文件, 即复制的源文件,冒号后面的是复制到 Slave 后的文件。
配置 solrconfig.xml
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler name="/replication" class="solr.ReplicationHandler" >
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="slave">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="masterUrl">http://60.124.214.234:8983/solr/main</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="pollInterval">00:00:20</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="compression">internal</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="httpConnTimeout">5000</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="httpReadTimeout">10000</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="httpBasicAuthUser">username</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="httpBasicAuthPassword">password</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler>
注意事项
如果当前的 Master 使用了 cores, Slave 配置的 url 必须加上 corename, 判断的标准就是:上面的 url 在浏览器中访问要是正常的。
中继服务器
一个 Master 可以对应多个 Slave, 但如果太多的时候,各个 Slave 同时同步 Master 会造成压力过大,而且 Master 带宽的压力也会增大。所以为了保证整个集群的使用, 可以使用 “中继服务器”,就是把其中一台或多台 Slave 做为其它 Slave 的 Master。和 MySQL 集群的里的原理一样。
注意事项
- 当一个服务器要配置中中继服务器时, 它的 solrconfig.xml 的 ReplicationHandler 里又要配置 Master 的内容,又要配置 Slave 的内容。(参照上面的配置)
- 确保在 replicateAfter 中有 ‘commit’ 配置。哪怕在 Master (中继服务器的 Master )中已经配置了 replicateAfter 的 optimize 选项。这是因为在 Slave (中继服务器也是 Slave) 上,commit 操作只会在从 Master 上下载完 index 后才会触发。Optimize 是永远不会在 Slave 机上执行的。
配置示例
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler name="/replication" class="solr.ReplicationHandler">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="master">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="replicateAfter">commit</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="confFiles">schema.xml,stopwords.txt,synonyms.txt</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="slave">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="masterUrl">http://60.124.214.234:8983/solr/main</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="pollInterval">00:00:60</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler>
启用/禁用
如果要把一个 Slave 转换成 Master。或者想在 Master 和 Slave 上使用同一个配置文件,然后可方便的配置成某个角色,可以如下:
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler name="/replication" class="solr.ReplicationHandler" >
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="master">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="enable">${enable.master:false}</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="replicateAfter">commit</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="confFiles">schema.xml,stopwords.txt</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="slave">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="enable">${enable.slave:false}</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="masterUrl">http://master_host:8983/solr</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="pollInterval">00:00:60</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler>
注意事项
- 一定要给 enable.master 和 enable.slave 默认设置为 false. 否则启动的时候会失败.
- 在启动 Solr 的时候可以通过传递参数去控制当前是作为 Master 还是 Slave, 如:-Denable.master=true 或 -Denable.slave=true
- 也可以将参数保存在启动的文件中, 如 solrcore.properties:
Master:
#solrcore.properties in master
enable.master=true
enable.slave=false
Slave:
#solrcore.properties in slave
enable.master=false
enable.slave=true
多核心的同步
一个 Master 可以有多个 core, 就类似一个 MySQL 服务器可以有多个库一样。
上面的主从配置中已经介绍了 Slave 配置中要写上 Master 的地址,如果是多核心,要写具体的核心名称。也就是说,一个 replication 的 requestHandler 只能同步一个核心。
另外,上面的配置中是在 Slave 的 solrconfig.xml 中写死了 Master 的 url, 其实这个值也可以写在外部文件中,类似上面的启动/禁用:
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler name="/replication" class="solr.ReplicationHandler" >
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="slave">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="masterUrl">http://${MASTER_CORE_URL}/${solr.core.name}</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="pollInterval">${POLL_TIME}</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">requestHandler>
变量
查看状态
由于上面配置的是 requestHandler, 所以也可以和其它的 requestHandler 一样,通过 url 去请求,如:
http://113.216.115.7:8983/solr/replication
返回结果可能如下:
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">response>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst name="responseHeader">
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">int name="status">0</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">int>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">int name="QTime">0</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">int>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">lst>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="status">OK</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
<<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str name="message">No command</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">str>
</<span class="hljs-title" style="box-sizing: border-box; font-weight: bold;">response>
同步原理
索引同步
- 当 Master 执行 commit / optimize 时,ReplicationHandler 得到相关的一些文件。从 Lucene 中读取数据,更新到文件中。
- Master 是不知道 Slave 的存在的,而 Slave 会不断去探测 Master(根据 pollInterval 配置的值),带上自己的版本号。当探测到 Master 的版本号要更新时,会触发同步事件。动作的步骤是:
- Slave 得到一份要下载的文件列表。包括文件名,大小,更新时间等。
- Slave 会检查该文件列表,并下载本机没有的文件。如果失败会重试 5 次。
- 文件下载到 Slave 后存放在临时目录中。所以,在传输过程中如果任意一方崩溃,都不会对它方造成影响。只会中断此次同步,下次同步会照旧进行。
- 下载完成后,所有的文件被移到 Slave 的索引目录。
- Slave 会执行一个 commit 命令。新的索引会被加载进去。
文件同步
- 只有在 Master 配置文件中 confFiles 配置里的文件才会被同步
- 只有 solr 实例的 conf 目录下的文件才会被同步
- 文件同步是伴随着索引同步完成的,也就是说文件变更后,不会马上同步到 Slave,而是承受着下次索引的同步。要想马上同步文件,可以人为触发一次索引同步,如:commit 或 optimize 一次 Master。
- 索引文件是通过 timestramp 比较的,和索引文件不同 confFiles 里的文件是通过它的 checksum 判断的。
- 配置文件会先被保存到临时目录中。如果同步的文件有原文件,原文件会被重全名,保存在原目录中。该目录不会自动清理老文件。
- 如果成功下载文件,Slave 会重新加载,而不是执行 commit 命令。