SolrCloud 通过 ZooKeeper 集群来进行协调,使一个索引进行分片,各个分片可以分布在不同的物理节点上,多个物理分片组成一个完成的索引 Collection。SolrCloud 自动支持 Solr Replication,可以同时对分片进行复制,冗余存储。下面,我们基于 Solr 最新的 4.4.0 版本进行安装配置 SolrCloud 集群。
1. 安装环境
我使用的安装程序各版本如下:
- Solr: Apache Solr-4.4.0
- Tomcat: Apache Tomcat 6.0.36
- ZooKeeper: Apache ZooKeeper 3.4.5
各个目录说明:
- 所有的程序安装在
/opt
目录下,你可以依照你的实际情况下修改安装目录。 - ZooKeeper的数据目录在:
/data/zookeeper/data
- solrhome设置在:
/usr/local/solrhome
2. 规划SolrCloud
- 单一SolrCloud数据集合: primary
- ZooKeeper集群: 3台
- SolrCloud实例: 3节点
- 索引分片: 3
- 复制因子: 2
手动将3个索引分片(Shard)的复本(Replica)分布在3个 SolrCloud 节点上
三个节点:
- 192.168.56.121
- 192.168.56.122
- 192.168.56.123
3. 安装ZooKeeper集群
由于需要用到 ZooKeeper,故我们先安装好 ZooKeeper 集群。
安装 ZooKeeper 集群之前,请确保每台机器上配置 /etc/hosts
文件,使每个节点都能通过机器名访问。
首先,在第一个节点上将 zookeeper-3.4.5.tar.gz 解压到 /opt
目录:
$ tar zxvf zookeeper-3.4.5.tar.gz -C /opt/
创建 ZooKeeper 配置文件 zookeeper-3.4.5/conf/zoo.cfg,内容如下:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/data/zookeeper/data
clientPort=2181
server.1=192.168.56.121:2888:3888
server.2=192.168.56.122:2888:3888
server.3=192.168.56.123:2888:3888
ZooKeeper 的数据目录指定在 /data/zookeeper/data
,你也可以使用其他目录,通过下面命令进行创建该目录:
$ mkdir /data/zookeeper/data -p
然后,初始化 myid ,三个节点编号依次为 1,2,3
,在其余节点上分别执行命令(注意修改编号)。
$ echo "1" >/data/zookeeper/data/myid
然后,在第二个和第三个节点上依次重复上面的操作。这样第一个节点中 myid 内容为1,第二个节点为2,第三个节点为3。
最后,启动 ZooKeeper 集群,在每个节点上分别启动 ZooKeeper 服务:
$ cd /opt
$ sh zookeeper-3.4.5/bin/zkServer.sh start
可以查看 ZooKeeper 集群的状态,保证集群启动没有问题:
[root@192.168.56.121 opt]# sh zookeeper-3.4.5/bin/zkServer.sh status
JMX enabled by default
Using config: /opt/zookeeper-3.4.5/bin/../conf/zoo.cfg
Mode: follower
4. 安装Solr
你可以参考《Apache Solr介绍及安装》
简单来说,执行以下命令:
$ unzip apache-tomcat-6.0.36.zip -d /opt
$ unzip solr-4.4.0.zip -d /opt
$ cd /opt
$ chmod +x apache-tomcat-6.0.36/bin/*.sh
$ cp solr-4.4.0/example/webapps/solr.war apache-tomcat-6.0.36/webapps/
$ cp solr-4.4.0/example/lib/ext/* apache-tomcat-6.0.36/webapps/solr/WEB-INF/lib/
$ cp solr-4.4.0/example/resources/log4j.properties apache-tomcat-6.0.36/lib/
在其他节点上重复以上操作完成所有节点的 solr 的安装。
5. 设置 SolrCloud 配置文件
1、 创建一个 SolrCloud 目录,并将 solr 的 lib 文件拷贝到这个目录:
$ mkdir -p /usr/local/solrcloud/solr-lib/
$ cp apache-tomcat-6.0.36/webapps/solr/WEB-INF/lib/* /usr/local/solrcloud/solr-lib/
2、 通过 bootstrap 设置 solrhome :
这里设置 solrhome 为 /usr/local/solrhome,创建该目录:
mkdir -p /usr/local/solrhome
然后,运行下面命令将 solrhome 下面的配置上传到 zookeeper:
$ java -classpath .:/usr/local/solrcloud/solr-lib/* org.apache.solr.cloud.ZkCLI -zkhost 192.168.56.121:2181,192.168.56.122:2181,192.168.56.123:2181 -cmd bootstrap -solrhome
SolrCloud 集群的所有的配置存储在 ZooKeeper。 一旦 SolrCloud 节点启动时配置了 -Dbootstrap_confdir
参数, 该节点的配置信息将发送到 ZooKeeper 上存储。基它节点启动时会应用 ZooKeeper 上的配置信息,这样当我们改动配置时就不用一个个机子去更改了。
3、SolrCloud 是通过 ZooKeeper 集群来保证配置文件的变更及时同步到各个节点上,所以,需要将我们自己的配置文件(在 /usr/local/solrcloud/conf/primary/conf 目录下)上传到 ZooKeeper 集群中,配置名称设为 primaryconf:
$ java -classpath .:/usr/local/solrcloud/solr-lib/* org.apache.solr.cloud.ZkCLI -zkhost 192.168.56.121:2181,192.168.56.122:2181,192.168.56.123:2181 -cmd upconfig -confdir /usr/local/solrcloud/conf/primary/conf -confname primaryconf
说明:
-
zkhost
指定 ZooKeeper 地址,逗号分割 -
/usr/local/solrcloud/conf/
目录下存在名称为 primary 的目录,该目录下的配置是后面需要用到的。 -
primaryconf
为在 ZooKeeper 上的配置文件名称。
/usr/local/solrcloud/conf 结构如下:
$ tree /usr/local/solrcloud/conf
/usr/local/solrcloud/conf
├── primary
│ └── conf
│ ├── schema.xml
│ └── solrconfig.xml
└── solr.xml
2 directories, 3 files
schema.xml 内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
<fields>
<field name="namespace" type="string" indexed="true" stored="true" />
<field name="id" type="string" indexed="true" stored="true" />
<field name="productId" type="long" indexed="true" stored="true" />
<field name="category" type="long" indexed="true" stored="true" multiValued="true" />
<field name="explicitCategory" type="long" indexed="true" stored="true" multiValued="true" />
<field name="searchable" type="text_general" indexed="true" stored="false" />
<field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/>
<dynamicField name="*_searchable" type="text_general" indexed="true" stored="true" />
<dynamicField name="*_i" type="int" indexed="true" stored="true" />
<dynamicField name="*_is" type="int" indexed="true" stored="true" multiValued="true" />
<dynamicField name="*_s" type="string" indexed="true" stored="true" />
<dynamicField name="*_ss" type="string" indexed="true" stored="true" multiValued="true" />
<dynamicField name="*_l" type="long" indexed="true" stored="true" />
<dynamicField name="*_ls" type="long" indexed="true" stored="true" multiValued="true" />
<dynamicField name="*_t" type="text_general" indexed="true" stored="true" />
<dynamicField name="*_txt" type="text_general" indexed="true" stored="true" multiValued="true" />
<dynamicField name="*_b" type="boolean" indexed="true" stored="true" />
<dynamicField name="*_bs" type="boolean" indexed="true" stored="true" multiValued="true" />
<dynamicField name="*_d" type="double" indexed="true" stored="true" />
<dynamicField name="*_ds" type="double" indexed="true" stored="true" multiValued="true" />
<dynamicField name="*_p" type="double" indexed="true" stored="true" />
<dynamicField name="*_dt" type="date" indexed="true" stored="true" />
<dynamicField name="*_dts" type="date" indexed="true" stored="true" multiValued="true" />
<!-- some trie-coded dynamic fields for faster range queries -->
<dynamicField name="*_ti" type="tint" indexed="true" stored="true" />
<dynamicField name="*_tl" type="tlong" indexed="true" stored="true" />
<dynamicField name="*_td" type="tdouble" indexed="true" stored="true" />
<dynamicField name="*_tdt" type="tdate" indexed="true" stored="true" />
</fields>
<uniqueKey>id</uniqueKey>
<types>
<fieldType name="string" class="solr.StrField" sortMissingLast="true" />
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true" />
<fieldType name="int" class="solr.TrieIntField" precisionStep="0" positionIncrementGap="0" />
<fieldType name="long" class="solr.TrieLongField" precisionStep="0" positionIncrementGap="0" />
<fieldType name="double" class="solr.TrieDoubleField" precisionStep="0" positionIncrementGap="0" />
<fieldType name="tint" class="solr.TrieIntField" precisionStep="8" positionIncrementGap="0" />
<fieldType name="tlong" class="solr.TrieLongField" precisionStep="8" positionIncrementGap="0" />
<fieldType name="tdouble" class="solr.TrieDoubleField" precisionStep="8" positionIncrementGap="0" />
<fieldType name="date" class="solr.TrieDateField" precisionStep="0" positionIncrementGap="0" />
<!-- A Trie based date field for faster date range queries and date faceting. -->
<fieldType name="tdate" class="solr.TrieDateField" precisionStep="6" positionIncrementGap="0" />
<fieldType name="text_general" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory" />
<filter class="solr.LowerCaseFilterFactory" />
</analyzer>
</fieldType>
</types>
</schema>
solrconfig.xml 内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<luceneMatchVersion>4.4</luceneMatchVersion>
<directoryFactory name="DirectoryFactory" class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>
<schemaFactory class="ClassicIndexSchemaFactory"/>
<updateHandler class="solr.DirectUpdateHandler2">
<updateLog>
<str name="dir">${solr.data.dir:}</str>
</updateLog>
</updateHandler>
<requestHandler name="/get" class="solr.RealTimeGetHandler">
<lst name="defaults">
<str name="omitHeader">true</str>
</lst>
</requestHandler>
<requestHandler name="/replication" class="solr.ReplicationHandler" startup="lazy" />
<requestDispatcher handleSelect="true" >
<requestParsers enableRemoteStreaming="false" multipartUploadLimitInKB="2048" formdataUploadLimitInKB="2048" />
<httpCaching never304="true" />
</requestDispatcher>
<requestHandler name="standard" class="solr.StandardRequestHandler" default="true" />
<requestHandler name="/analysis/field" startup="lazy" class="solr.FieldAnalysisRequestHandler" />
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
<requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler" startup="lazy" />
<requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" />
<requestHandler name="/admin/ping" class="solr.PingRequestHandler">
<lst name="invariants">
<str name="q">solrpingquery</str>
</lst>
<lst name="defaults">
<str name="echoParams">all</str>
<str name="df">id</str>
</lst>
</requestHandler>
<queryResponseWriter name="json" class="solr.JSONResponseWriter">
<str name="content-type">text/plain; charset=UTF-8</str>
</queryResponseWriter>
<updateRequestProcessorChain name="sample">
<processor class="solr.LogUpdateProcessorFactory" />
<processor class="solr.DistributedUpdateProcessorFactory"/>
<processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>
<!-- config for the admin interface -->
<admin>
<defaultQuery>solr</defaultQuery>
<pingQuery>q=solr&version=2.0&start=0&rows=0</pingQuery>
<healthcheck type="file">server-enabled</healthcheck>
</admin>
</config>
4、创建 collection 并和配置文件关联:
$ java -classpath .:/usr/local/solrcloud/solr-lib/* org.apache.solr.cloud.ZkCLI -zkhost 192.168.56.121:2181,192.168.56.122:2181,192.168.56.123:2181 -cmd linkconfig -collection primary -confname primaryconf
说明:
- 创建的 collection 叫做 primary,并指定和 primaryconf 连接
5、查看 ZooKeeper 上状态
在任意一个节点的 /opt 目录下执行如下命令:
$ zookeeper-3.4.5/bin/zkCli.sh
[zk: localhost:2181(CONNECTED) 0] ls /
[configs,zookeeper,clusterstate.json,aliases.json,live_nodes,overseer,collections,overseer_elect]
[zk: localhost:2181(CONNECTED) 1] ls /configs
[primaryconf,]
[zk: localhost:2181(CONNECTED) 1] ls /collections
[primary]
查看 /configs
和 /collections
目录均有值,说明配置文件已经上传到 ZooKeeper 上了,接下来启动 solr。
6. Tomcat 配置与启动
1、修改每个节点上的 tomcat 配置文件,在环境变量中添加 zkHost
变量
编辑 apache-tomcat-6.0.36/bin/catalina.sh
,添加如下代码:
JAVA_OPTS='-Djetty.port=8080 -Dsolr.solr.home=/usr/local/solrhome -DzkHost=192.168.56.122:2181,192.168.56.122:2181,192.168.56.123:2181'
在 /usr/local/solrhome/
目录创建 solr.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<solr persistent="true" sharedLib="lib">
<cores adminPath="/admin/cores" zkClientTimeout="${zkClientTimeout:15000}" hostPort="${jetty.port:8080}" hostContext="${hostContext:solr}"></cores>
</solr>
说明:
-
-Djetty.port
:配置 solr 使用的端口,默认为 8983,这里我们使用的是 tomcat,端口为 8080 -
-Dsolr.solr.home
:配置 solr/home -
-zkHost
: 配置 zookeeper 集群地址,多个地址逗号分隔
最后,在 /opt 目录下启动 tomcat:
$ sh apache-tomcat-6.0.36/bin/startup.sh
通过 http://192.168.56.121:8080/solr/ 进行访问,界面如图提示 There are no SolrCores running.
,这是因为配置文件尚未配置 solrcore。