Linux 搭建 SolrCloud 集群服务

概述

Lucene是一个Java语言编写的利用倒排原理实现的文本检索类库

Solr是以Lucene为基础实现的文本检索应用服务。Solr部署方式有单机方式、多机Master-Slaver方式、Cloud方式。

SolrCloud是基于Solr和Zookeeper的分布式搜索方案。当索引越来越大,一个单一的系统无法满足磁盘需求,查询速度缓慢,此时就需要分布式索引。在分布式索引中,原来的大索引,将会分成多个小索引,solr可以将这些小索引返回的结果合并,然后返回给客户端。

特色功能

SolrCloud有几个特色功能:

集中式的配置信息使用ZK进行集中配置。启动时可以指定把Solr的相关配置文件上传 Zookeeper,多机器共用。这些ZK中的配置不会再拿到本地缓存,Solr直接读取ZK中的配置信息。配置文件的变动,所有机器都可以感知到。另外,Solr的一些任务也是通过ZK作为媒介发布的。目的是为了容错。接收到任务,但在执行任务时崩溃的机器,在重启后,或者集群选出候选者时,可以再次执行这个未完成的任务。

自动容错SolrCloud对索引分片,并对每个分片创建多个Replication。每个 Replication都可以对外提供服务。一个Replication挂掉不会影响索引服务。更强大的是,它还能自动的在其它机器上帮你把失败机器上的索引Replication重建并投入使用。

近实时搜索立即推送式的replication(也支持慢推送)。可以在秒内检索到新加入索引。

查询时自动负载均衡SolrCloud索引的多个Replication可以分布在多台机器上,均衡查询压力。如果查询压力大,可以通过扩展机器,增加Replication来减缓。

自动分发的索引和索引分片发送文档到任何节点,它都会转发到正确节点。

事务日志确保更新无丢失,即使文档没有索引到磁盘。

其它值得一提的功能有:

索引存储在HDFS上索引的大小通常在G和几十G,上百G的很少,这样的功能或许很难实用。但是,如果你有上亿数据来建索引的话,也是可以考虑一下的。我觉得这个功能最大的好处或许就是和下面这个“通过MR批量创建索引”联合实用。

通过MR批量创建索引有了这个功能,你还担心创建索引慢吗?

强大的RESTful API通常你能想到的管理功能,都可以通过此API方式调用。这样写一些维护和管理脚本就方便多了。

优秀的管理界面主要信息一目了然;可以清晰的以图形化方式看到SolrCloud的部署分布;当然还有不可或缺的Debug功能。

SolrCloud的基本概念

Cluster集群:一组Solr节点,逻辑上作为一个单元进行管理,整个集群使用同一套Schema和SolrConfig

Node节点:一个运行Solr的JVM实例

Collection:在SolrCloud集群中逻辑意义上的完整的索引,常常被划分为一个或多个Shard。这些Shard使用相同的config set,如果Shard数超过一个,那么索引方案就是分布式索引。

Core:也就是Solr Core,一个Solr中包含一个或者多个SolrCore,每个Solr Core可以独立提供索引和查询功能,Solr Core额提出是为了增加管理灵活性和共用资源。
SolrCloud中使用的配置是在Zookeeper中的,而传统的Solr Core的配置文件是在磁盘上的配置目录中。

Config Set:Solr Core提供服务必须的一组配置文件,每个Config Set有一个名字。必须包含solrconfig.xml和schema.xml,初次之外,依据这两个文件的配置内容,可能还需要包含其他文件。
Config Set存储在Zookeeper中,可以重新上传或者使用upconfig命令进行更新,可以用Solr的启动参数bootstrap_confdir进行初始化或者更新。

Shard分片:Collection的逻辑分片。每个Shard被分成一个或者多个replicas,通过选举确定那个是Leader。

Replica:Shard的一个拷贝。每个Replica存在于Solr的一个Core中。

Leader:赢得选举的Shard replicas,每个Shard有多个replicas,这几个Replicas需要选举确定一个Leader。选举可以发生在任何时间。当进行索引操作时,SolrCloud将索引操作请求传到此Shard对应的leader,leader再分发它们到全部Shard的replicas。

Solr 文档

环境

iptables防火墙关闭命令

1
$ service iptables stop # 关闭命令:

firewall防火墙关闭命令

1
$ systemctl stop firewalld.service # 停止firewall

Solr 6(和SolrJ客户端库)的Java支持的最低版本现在是Java 8。

Solr 安装

下载 Solr

下载最新版本的Solr

1
$ wget https://mirrors.tuna.tsinghua.edu.cn/apache/lucene/solr/6.6.3/solr-6.6.3.zip

提取tar文件

提取zip文件

1
2
$ unzip -xvf solr-6.6.3.zip
$ cd solr-6.6.3

集群配置

编辑 solr.in.sh

集群中的每台机器都要按照以下说明进行配置启动

首先到 solr 安装目录的 bin 下,编辑 solr.in.sh 文件

搜索 SOLR_HOST, 取消注释, 设置成自己的 ip 或机器名 例如(kiko1) 建议使用机器名

搜索 SOLR_TIMEZONE, 取消注释, 设置成 UTC+8

把kiko1 的solr.in.sh 修改为以下配置

建议设置Solr服务器的主机名,特别是在以SolrCloud模式运行时,因为它会在使用ZooKeeper注册时确定节点的地址 ,不建议用ip

1
2
SOLR_HOST="kiko1" #节点(机器)名称
SOLR_TIMEZONE="UTC+8" #时区 UTC+8为东八区

复制 Solr 配置

  1. 把 kiko1 编辑好的 Solr 文件及配置通过 scp -r 复制到集群 kiko2, kiko3

    1
    [root@kiko1 solr-6.6.3]# for a in {2..3} ; do scp -r /home/kiko/tools/solr-6.6.3/ kiko$a:/home/kiko/tools/solr-6.6.3 ; done
  2. 然后依次修改 kiko2, kiko3 的上的 solr.in.sh 的SOLR_HOST 为机器的ip或机器名(建议为机器名)

格式 SOLR_HOST=”ip”

1
[root@kiko2 tools]# vim solr-6.6.3/bin/solr.in.sh

启动 ZooKeeper 集群

1
[root@kiko1 bin]# for a in {1..3} ; do ssh kiko$a "source /etc/profile; /home/kiko/tools/zookeeper-3.4.12/bin/zkServer.sh start" ; done

启动 SolrCloud 集群

在任意一台机器,启动 SolrCloud 集群 并且关联 ZooKeeper 集群

1
[root@kiko1 solr-6.6.3]# for a in {1..3} ; do ssh kiko$a "source /etc/profile; /home/kiko/tools/solr-6.6.3/bin/solr start -cloud -z kiko1:2181,kiko2:2181,kiko3:2181 -p 8983 -force" ; done

响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require
RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'.
Waiting up to 180 seconds to see Solr running on port 8983 [\]
Started Solr server on port 8983 (pid=10860). Happy searching!
Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require
RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'.
Waiting up to 180 seconds to see Solr running on port 8983 [\]
Started Solr server on port 8983 (pid=24326). Happy searching!
Warning: Available entropy is low. As a result, use of the UUIDField, SSL, or any other features that require
RNG might not work properly. To check for the amount of available entropy, use 'cat /proc/sys/kernel/random/entropy_avail'.
Waiting up to 180 seconds to see Solr running on port 8983 [\]
Started Solr server on port 8983 (pid=9689). Happy searching!

创建集群库

在任意一台机器(solr节点服务器kiko1,kiko2,kiko3)执行如下命令

1
[root@kiko1 solr-6.6.3]# /home/kiko/tools/solr-6.6.3/bin/solr create_collection -c test_collection -shards 2 -replicationFactor 3 -force

  • 执行命令参数说明:
    • -c 指定库(collection)名称
    • -shards 指定分片数量,可简写为 -s ,索引数据会分布在这些分片上
    • -replicationFactor 每个分片的副本数量,每个碎片由至少1个物理副本组成

响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Connecting to ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181 ...
INFO - 2018-05-09 20:23:42.323; org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider; Cluster at kiko1:2181,kiko2:2181,kiko3:2181 ready
Uploading /home/kiko/tools/solr-6.6.3/server/solr/configsets/data_driven_schema_configs/conf for config test_collection to ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181
Creating new collection 'test_collection' using command:
http://kiko1:8983/solr/admin/collections?action=CREATE&name=test_collection&numShards=2&replicationFactor=3&maxShardsPerNode=2&collection.configName=test_collection
{
"responseHeader":{
"status":0,
"QTime":6132},
"success":{
"kiko3:8983_solr":{
"responseHeader":{
"status":0,
"QTime":4315},
"core":"test_collection_shard1_replica1"},
"kiko2:8983_solr":{
"responseHeader":{
"status":0,
"QTime":4637},
"core":"test_collection_shard1_replica2"},
"kiko1:8983_solr":{
"responseHeader":{
"status":0,
"QTime":4801},
"core":"test_collection_shard1_replica3"}}}

SolrCloud状态 图表

可以看到 solr 2个分片,个3个副本

服务状态

如果您不确定SolrCloud状态

1
[root@kiko2 tools]# /home/kiko/tools/solr-6.6.3/bin/solr status

响应

1
2
3
4
5
6
7
8
9
10
11
12
13
Found 1 Solr nodes:
Solr process 24326 running on port 8983
{
"solr_home":"/home/kiko/tools/solr-6.6.3/server/solr",
"version":"6.6.3 d1e9bbd333ea55cfa0c75d324424606e857a775b - sarowe - 2018-03-02 15:09:34",
"startTime":"2018-05-09T12:21:22.783Z",
"uptime":"0 days, 0 hours, 26 minutes, 40 seconds",
"memory":"99.4 MB (%20.3) of 490.7 MB",
"cloud":{
"ZooKeeper":"kiko1:2181,kiko2:2181,kiko3:2181",
"liveNodes":"3",
"collections":"1"}}

删除集群库

在任意一台机器(solr节点服务器kiko1,kiko2,kiko3)执行命令 ./solr delete -c <collection>

将检查

1
2
/home/kiko/tools/solr-6.6.3/server/solr/test_collection_shard1_replica1
/home/kiko/tools/solr-6.6.3/server/solr/test_collection_shard2_replica1

配置目录是否被其他集合使用。如果没有,那么该目录将从SolrCloud 集群 中删除

1
[root@kiko1 solr]# /home/kiko/tools/solr-6.6.3/bin/solr delete -c test_collection

响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Connecting to ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181
INFO - 2018-05-10 09:58:23.083; org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider; Cluster at kiko1:2181,kiko2:2181,kiko3:2181 ready
Deleting collection 'test_collection' using command:
http://kiko2:8983/solr/admin/collections?action=DELETE&name=test_collection
{
"responseHeader":{
"status":0,
"QTime":825},
"success":{
"kiko3:8983_solr":{"responseHeader":{
"status":0,
"QTime":40}},
"kiko1:8983_solr":{"responseHeader":{
"status":0,
"QTime":41}},
"kiko2:8983_solr":{"responseHeader":{
"status":0,
"QTime":45}}}}

停止集群

在任意一台机器,停止SolrCloud集群,在SolrCloud模式下停止Solr,可以使用 -all

1
[root@kiko1 solr]# for a in {1..3} ; do ssh kiko$a "source /etc/profile; /home/kiko/tools/solr-6.6.3/bin/solr stop -all" ; done

或者

1
[root@kiko1 solr]# for a in {1..3} ; do ssh kiko$a "source /etc/profile; /home/kiko/tools/solr-6.6.3/bin/solr stop -cloud -z kiko1:2181,kiko2:2181,kiko3:2181 -p 8983 -force" ; done

响应

1
2
3
Sending stop command to Solr running on port 8983 ... waiting up to 180 seconds to allow Jetty process 10860 to stop gracefully.
Sending stop command to Solr running on port 8983 ... waiting up to 180 seconds to allow Jetty process 24326 to stop gracefully.
Sending stop command to Solr running on port 8983 ... waiting up to 180 seconds to allow Jetty process 9689 to stop gracefully.

副本状态

healthcheck 命收集有关集合中每个副本的基本信息,例如副本数量,当前运行状态,是否正常,以及每个副本运行多长时间,内存 和地址(副本在群集中的位置)

1
[root@kiko1 solr]# /home/kiko/tools/solr-6.6.3/bin/solr healthcheck -c test_collection -z kiko1:2181,kiko2:2181,kiko3:2181

响应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
INFO - 2018-05-10 10:19:41.025; org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider; Cluster at kiko1:2181,kiko2:2181,kiko3:2181 ready
{
"collection":"test_collection",
"status":"healthy",
"numDocs":0,
"numShards":2,
"shards":[
{
"shard":"shard1",
"status":"healthy",
"replicas":[
{
"name":"core_node1",
"url":"http://kiko1:8983/solr/test_collection_shard1_replica2/",
"numDocs":0,
"status":"active",
"uptime":"0 days, 0 hours, 9 minutes, 46 seconds",
"memory":"42.1 MB (%8.6) of 490.7 MB"},
{
"name":"core_node3",
"url":"http://kiko3:8983/solr/test_collection_shard1_replica3/",
"numDocs":0,
"status":"active",
"uptime":"0 days, 0 hours, 9 minutes, 34 seconds",
"memory":"30.1 MB (%6.1) of 490.7 MB",
"leader":true},
{
"name":"core_node6",
"url":"http://kiko2:8983/solr/test_collection_shard1_replica1/",
"numDocs":0,
"status":"active",
"uptime":"0 days, 0 hours, 9 minutes, 40 seconds",
"memory":"104 MB (%21.2) of 490.7 MB"}]},
{
"shard":"shard2",
"status":"healthy",
"replicas":[
{
"name":"core_node2",
"url":"http://kiko1:8983/solr/test_collection_shard2_replica2/",
"numDocs":0,
"status":"active",
"uptime":"0 days, 0 hours, 9 minutes, 46 seconds",
"memory":"42.6 MB (%8.7) of 490.7 MB"},
{
"name":"core_node4",
"url":"http://kiko3:8983/solr/test_collection_shard2_replica3/",
"numDocs":0,
"status":"active",
"uptime":"0 days, 0 hours, 9 minutes, 34 seconds",
"memory":"31 MB (%6.3) of 490.7 MB",
"leader":true},
{
"name":"core_node5",
"url":"http://kiko2:8983/solr/test_collection_shard2_replica1/",
"numDocs":0,
"status":"active",
"uptime":"0 days, 0 hours, 9 minutes, 40 seconds",
"memory":"27.6 MB (%5.6) of 490.7 MB"}]}]}

ZK管理solr配置

配置文件上传到ZooKeeper 集群

可用参数(所有参数都是必需的)

  • -n 在ZooKeeper中设置的配置名称,可以通过管理界面,点击菜单,Cloud 选中 Tree / configs 下查看,配置列表
  • -d 配置设置为上传的路径。路径需要有一个“conf”目录,依次包含solrconfig.xml等。最好可以提供绝对路径
  • -z Zookeeper IP 端口,多个zk用”,” 分隔
    SolrCloud是通过Zookeeper集群来保证配置文件的变更及时同步到各个节点上,所以,可以将配置文件上传到Zookeeper集群。

例如 我们可以在/home/kiko/tools/solr-6.6.3/server/solr/configsets/basic_configs/conf/路径中对db-data-config.xml,managed-schema,solrconfig.xml进行配置,包括配置中文分词,导入数据库数据等,
然后对test_collection进行配置文件上传,命令如下:

1
[root@kiko2 solr]# /home/kiko/tools/solr-6.6.3/bin/solr zk upconfig -z kiko1:2181,kiko2:2181,kiko3:2181 -n test_collection -d /home/kiko/tools/solr-6.6.3/server/solr/configsets/basic_configs/

响应

1
2
Connecting to ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181 ...
Uploading /home/kiko/tools/solr-6.6.3/server/solr/configsets/basic_configs/conf for config test_collection to ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181

删除上传到ZooKeeper 集群的solr 配置

rm 删除 -r 递归删除

1
[root@kiko1 solr]# /home/kiko/tools/solr-6.6.3/bin/solr zk rm -r /configs/mynewconfig -z kiko1:2181,kiko2:2181,kiko3:2181

响应

1
2
Connecting to ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181 ...
Removing Zookeeper node /configs/mynewconfig from ZooKeeper at kiko1:2181,kiko2:2181,kiko3:2181 recurse: true

本文参考 CentOs7.3 搭建 SolrCloud 集群服务