SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud。当一个系统的索引数据量少的时候是不需要使用SolrCloud的,当索引量很大,搜索请求并发很高,这时需要使用SolrCloud来满足这些需求。
SolrCloud是基于Solr和Zookeeper的分布式搜索方案,它的主要思想是使用Zookeeper作为集群的配置信息中心。
它有几个特色功能:
1)集中式的配置信息
2)自动容错
3)近实时搜索
4)查询时自动负载均衡
顾名思义zookeeper就是动物园管理员,他是用来管hadoop(大象)、Hive(蜜蜂)、pig(小猪)的管理员, Apache Hbase和 Apache Solr 的分布式集群都用到了zookeeper;Zookeeper:是一个分布式的、开源的程序协调服务,是hadoop项目下的一个子项目。
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都是使用配置文件的方式,在代码中引入这些配置文件。但是当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多,有很多服务器都需要这个配置,而且还可能是动态的话使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。比如我们可以把配置放在数据库里,然后所有需要配置的服务都去这个数据库读取配置。但是,因为很多服务的正常运行都非常依赖这个配置,所以需要这个集中提供配置服务的服务具备很高的可靠性。一般我们可以用一个集群来提供这个配置服务,但是用集群提升可靠性,那如何保证配置在集群中的一致性呢? 这个时候就需要使用一种实现了一致性协议的服务了。Zookeeper就是这种服务,它使用Zab这种一致性协议来提供一致性。现在有很多开源项目使用Zookeeper来维护配置,比如在HBase中,客户端就是连接一个Zookeeper,获得必要的HBase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列Kafka中,也使用Zookeeper来维护broker的信息。在Alibaba开源的SOA框架Dubbo中也广泛的使用Zookeeper管理一些配置来实现服务治理。
名字服务这个就很好理解了。比如为了通过网络访问一个系统,我们得知道对方的IP地址,但是IP地址对人非常不友好,这个时候我们就需要使用域名来访问。但是计算机是不能是别域名的。怎么办呢?如果我们每台机器里都备有一份域名到IP地址的映射,这个倒是能解决一部分问题,但是如果域名对应的IP发生变化了又该怎么办呢?于是我们有了DNS这个东西。我们只需要访问一个大家熟知的(known)的点,它就会告诉你这个域名对应的IP是什么。在我们的应用中也会存在很多这类问题,特别是在我们的服务特别多的时候,如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。
其实在第一篇文章中已经介绍了Zookeeper是一个分布式协调服务。这样我们就可以利用Zookeeper来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进行操作,那又存在单点。通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即fail over到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫Leader Election(leader选举)。比如HBase的Master就是采用这种机制。但要注意的是分布式锁跟同一个进程的锁还是有区别的,所以使用的时候要比同一个进程里的锁更谨慎的使用。
在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。还有,比如一个分布式的SOA架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如Alibaba开源的SOA框架Dubbo就采用了Zookeeper作为服务发现的底层机制)。还有开源的Kafka队列就采用了Zookeeper作为Cosnumer的上下线管理。
SolrCloud为了降低单机的处理压力,需要由多台服务器共同来完成索引和搜索任务。实现的思路是将索引数据进行Shard(分片)拆分,每个分片由多台的服务器共同完成,当一个索引或搜索请求过来时会分别从不同的Shard的服务器中操作索引。
SolrCloud需要Solr基于Zookeeper部署,Zookeeper是一个集群管理软件,由于SolrCloud需要由多台服务器组成,由zookeeper来进行协调管理。
下图是一个SolrCloud应用的例子:
对上图进行图解,如下:
三个Solr实例( 每个实例包括两个Core),组成一个SolrCloud。
索引集合包括两个Shard(shard1和shard2),shard1和shard2分别由三个Core组成,其中一个Leader两个Replication,Leader是由zookeeper选举产生,zookeeper控制每个shard上三个Core的索引数据一致,解决高可用问题。
用户发起索引请求分别从shard1和shard2上获取,解决高并发问题。
Collection在SolrCloud集群中是一个逻辑意义上的完整的索引结构。它常常被划分为一个或多个Shard(分片),它们使用相同的配置信息。
比如:针对商品信息搜索可以创建一个collection。
collection=shard1+shard2+....+shardX
每个Core是Solr中一个独立运行单位,提供 索引和搜索服务。一个shard需要由一个Core或多个Core组成。由于collection由多个shard组成所以collection一般由多个core组成。
Master是master-slave结构中的主结点(通常说主服务器),Slave是master-slave结构中的从结点(通常说从服务器或备服务器)。同一个Shard下master和slave存储的数据是一致的,这是为了达到高可用目的。
Collection的逻辑分片。每个Shard被化成一个或者多个replication,通过选举确定哪个是Leader。
本课程的这套安装是单机版的安装,所以采用伪集群的方式进行安装,如果是真正的生产环境,将伪集群的ip改下就可以了,步骤是一样的。
SolrCloud结构图如下:
1. zookeeper集群
a) zookeeper需要保证高可用,需要搭建集群
b) zookeeper需要进行投票和选举机制,最少需要三个节点
c) zookeeper的三个节点,注意修改端口号不一样
2. Solr的集群
a) 需要四个节点
b) 整个core分成两个分片,每个分片都由两个服务器组成,master和slave
c) 每个Tomcat有一个solr服务
CentOS 6.5 32位
jdk1.7
单机版的虚拟机内存最好是1G以上
[root@itcast-01 WEB-INF]# cd /usr/local/
[root@itcast-01 local]# cp zookeeper-3.4.6.tar.gz solr/solr-cloud/
[root@itcast-01 local]# cd solr/solr-cloud/
[root@itcast-01 solr-cloud]# tar -zxf zookeeper-3.4.6.tar.gz
[root@itcast-01 solr-cloud]# mv zookeeper-3.4.6 zookeeper01
[root@itcast-01 solr-cloud]# cp -r zookeeper01/ zookeeper02
[root@itcast-01 solr-cloud]# cp -r zookeeper01/ zookeeper03
[root@itcast-01 solr-cloud]# mkdir zookeeper01/data
[root@itcast-01 solr-cloud]# mkdir zookeeper02/data
[root@itcast-01 solr-cloud]# mkdir zookeeper03/data
[root@itcast-01 solr-cloud]# vim zookeeper01/data/myid
1
[root@itcast-01 solr-cloud]# vim zookeeper01/data/myid
2
[root@itcast-01 solr-cloud]# vim zookeeper01/data/myid
3
[root@itcast-01 solr-cloud]# mv zookeeper01/conf/zoo_sample.cfg zookeeper01/conf/zoo.cfg
[root@itcast-01 solr-cloud]# mv zookeeper02/conf/zoo_sample.cfg zookeeper02/conf/zoo.cfg
[root@itcast-01 solr-cloud]# mv zookeeper03/conf/zoo_sample.cfg zookeeper03/conf/zoo.cfg
[root@itcast-01 solr-cloud]# vim zookeeper01/conf/zoo.cfg
[root@itcast-01 solr-cloud]# vim zookeeper02/conf/zoo.cfg
[root@itcast-01 solr-cloud]# vim zookeeper03/conf/zoo.cfg
修改dataDir和端口号
底部加上:
server.1=192.168.25.154:2881:3881
server.2=192.168.25.154:2882:3882
server.3=192.168.25.154:2883:3883
效果
[root@itcast-01 solr-cloud]# zookeeper01/bin/zkServer.sh start
JMX enabled by default
Using config: /usr/local/solr/solr-cloud/zookeeper01/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@itcast-01 solr-cloud]# zookeeper02/bin/zkServer.sh start
JMX enabled by default
Using config: /usr/local/solr/solr-cloud/zookeeper02/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@itcast-01 solr-cloud]# zookeeper03/bin/zkServer.sh start
JMX enabled by default
Using config: /usr/local/solr/solr-cloud/zookeeper03/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@itcast-01 solr-cloud]# ./zookeeper01/bin/zkServer.sh status
JMX enabled by default
Using config: /usr/local/solr/solr-cloud/zookeeper01/bin/../conf/zoo.cfg
Mode: follower
[root@itcast-01 solr-cloud]# ./zookeeper02/bin/zkServer.sh status
JMX enabled by default
Using config: /usr/local/solr/solr-cloud/zookeeper02/bin/../conf/zoo.cfg
Mode: leader
[root@itcast-01 solr-cloud]# ./zookeeper03/bin/zkServer.sh status
JMX enabled by default
Using config: /usr/local/solr/solr-cloud/zookeeper03/bin/../conf/zoo.cfg
Mode: follower
1. 上传
按alt+p进入SFTP界面,进行上传
sftp> put -r "C:\0423\07taotao\01课前资料\02技术资料\tomcat\apache-tomcat-7.0.47.tar.gz"
2. 解压
[root@itcast-01 ~]# tar -zxf apache-tomcat-7.0.47.tar.gz
3. 移动
[root@itcast-01 ~]# mkdir /usr/local/solr
[root@itcast-01 ~]# mv apache-tomcat-7.0.47 /usr/local/solr/tomcat
按alt+p进入SFTP界面,进行上传
sftp> put -r "C:\0423\07taotao\01课前资料\02技术资料\Solr\solr-4.10.3.tgz.tgz"
[root@itcast-01 ~]# mv solr-4.10.3.tgz.tgz /usr/local/solr/
[root@itcast-01 ~]# cd /usr/local/solr/
[root@itcast-01 solr]# tar -zxf solr-4.10.3.tgz.tgz
1. 复制Tomcat并删除webapps内所有文件,创建ROOT目录
[root@itcast-01 example]# cd /usr/local/solr/tomcat/webapps/
[root@itcast-01 webapps]# rm -rf *
[root@itcast-01 webapps]# mkdir ROOT
2. 部署solr.war到Tomcat中
[root@itcast-01 webapps]# cp /usr/local/solr/solr-4.10.3/example/webapps/solr.war ROOT/
[root@itcast-01 webapps]# cd ROOT
[root@itcast-01 ROOT]# jar -xf solr.war
3. 删除war包
[root@itcast-01 ROOT]# rm -f solr.war
4. 把solr-4.10.2/example/lib/ext目录下的所有的jar包,添加到solr工程中
[root@itcast-01 ROOT]# cd /usr/local/solr/solr-4.10.3/example/lib/ext/
[root@itcast-01 ext]# cp * /usr/local/solr/tomcat/webapps/ROOT/WEB-INF/lib/
/example/solr目录就是一个solrhome。复制此目录到/usr/local/solr/solrhome
[root@itcast-01 ext]# cd /usr/local/solr/solr-4.10.3/example/
[root@itcast-01 example]# cp -r solr /usr/local/solr/solrhome
根据业务需求,添加中文分词jar包,修改自己的solrcore的schema.xml配置文件的业务域等等。
例如schema.xml增加内容如下:
solr的集群应该有4个solr服务
[root@itcast-01 example]# cd /usr/local/solr/
[root@itcast-01 solr]# mkdir solr-cloud/
[root@itcast-01 solr]# cp -r solrhome/ solr-cloud/solrhome01
[root@itcast-01 solr]# cp -r solrhome/ solr-cloud/solrhome02
[root@itcast-01 solr]# cp -r solrhome/ solr-cloud/solrhome03
[root@itcast-01 solr]# cp -r solrhome/ solr-cloud/solrhome04
其实就是复制4分之前准备的4个solr单机版
[root@itcast-01 solr]# cp -r tomcat/ solr-cloud/tomcat-solr01
[root@itcast-01 solr]# cp -r tomcat/ solr-cloud/tomcat-solr02
[root@itcast-01 solr]# cp -r tomcat/ solr-cloud/tomcat-solr03
[root@itcast-01 solr]# cp -r tomcat/ solr-cloud/tomcat-solr04
[root@itcast-01 solr]# cd solr-cloud/
[root@itcast-01 solr-cloud]# vim tomcat-solr01/conf/server.xml
[root@itcast-01 solr-cloud]# vim tomcat-solr02/conf/server.xml
[root@itcast-01 solr-cloud]# vim tomcat-solr03/conf/server.xml
[root@itcast-01 solr-cloud]# vim tomcat-solr04/conf/server.xml
需要修改3个地方的端口号,
如下图第一个Tomcat为例,修改三个端口号8001,8081,8011,其他Tomcat类似
4个Tomcat都要修改为对应的solrhome
[root@itcast-01 solr-cloud]# vim tomcat-solr01/webapps/ROOT/WEB-INF/web.xml
[root@itcast-01 solr-cloud]# vim tomcat-solr02/webapps/ROOT/WEB-INF/web.xml
[root@itcast-01 solr-cloud]# vim tomcat-solr03/webapps/ROOT/WEB-INF/web.xml
[root@itcast-01 solr-cloud]# vim tomcat-solr04/webapps/ROOT/WEB-INF/web.xml
修改各自的solrhome
例如/usr/local/solr/solr-cloud/solrhome01
[root@itcast-01 solr-cloud]# vim solrhome01/solr.xml
[root@itcast-01 solr-cloud]# vim solrhome02/solr.xml
[root@itcast-01 solr-cloud]# vim solrhome03/solr.xml
[root@itcast-01 solr-cloud]# vim solrhome04/solr.xml
例如solrhome01需要修改为8081,其他类似
进入/usr/local/solr/solr-4.10.3/example/scripts/cloud-scripts,执行命令
[root@itcast-01 solr-cloud]# cd /usr/local/solr/solr-4.10.3/example/scripts/cloud-scripts
需要运行的以下命令,需要修改IP地址和修改solrcore的路径地址
[root@itcast-01 cloud-scripts]# ./zkcli.sh -zkhost 192.168.37.161:3181,192.168.37.161:3182,192.168.37.161:3183 -cmd upconfig -confdir /usr/local/solr/solr-cloud/solrhome01/collection1/conf -confname myconf
zookeeper是做配置文件的集中管理,
以上命令的作用是把配置文件上传给zookeeper,由zookeeper管理配置文件
zookeeper把所有的solr集群的配置文件进行统一管理
进入任意zookeeper,使用客户端进行查看
[root@itcast-01 cloud-scripts]# cd /usr/local/solr/solr-cloud/zookeeper01/bin
[root@itcast-01 bin]# ./zkCli.sh -server 192.168.37.161:3181
使用ls命令查看zookeeper配置信息
需要修改每个Tomcat的bin/catalina.sh文件
[root@itcast-01 bin]# cd /usr/local/solr/solr-cloud/
[root@itcast-01 solr-cloud]# vim tomcat-solr01/bin/catalina.sh
[root@itcast-01 solr-cloud]# vim tomcat-solr02/bin/catalina.sh
[root@itcast-01 solr-cloud]# vim tomcat-solr03/bin/catalina.sh
[root@itcast-01 solr-cloud]# vim tomcat-solr04/bin/catalina.sh
例如Tomcat01,其他Tomcat都一样设置,添加JAVA_OPTS
JAVA_OPTS="-DzkHost=192.168.37.161:3181,192.168.37.161:3182,192.168.37.161:3183"
[root@itcast-01 solr-cloud]# ./tomcat-solr01/bin/startup.sh
[root@itcast-01 solr-cloud]# ./tomcat-solr02/bin/startup.sh
[root@itcast-01 solr-cloud]# ./tomcat-solr03/bin/startup.sh
[root@itcast-01 solr-cloud]# ./tomcat-solr04/bin/startup.sh
访问任意一个solr集群的节点都可以
例如http://192.168.37.161:8081/solr
如果集群中有四个solr节点创建新集群collection2,将集群分为两片,每片一个副本。
http://192.168.37.161:8081/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2
效果
http://192.168.37.161:8081/solr/admin/collections?action=DELETE&name=collection1
效果