作者:涛升一舅_250 | 来源:互联网 | 2023-05-18 17:48
SolrCloud为了降低单机的处理压力,需要由多台服务器共同来完成索引和搜索任务。实现的思路是将索引数据进行Shard(分片)拆分,每个分片由多台的服务器共同完成,当一个索引或搜索请求过来时会分别从不同的Shard的服务器中操作索引。
SolrCloud需要Solr基于Zookeeper部署,Zookeeper是一个集群管理软件,由于SolrCloud需要由多台服务器组成,由zookeeper来进行协调管理。
下图是一个SolrCloud应用的例子:
对上图进行图解,如下:
单机版安装:
第一步:安装jdk、安装tomcat
Usr/local下建立solr目录,tomcat的解压包放进去一份
第二步:解压solr压缩包。
第三步:把dist/solr-4.10.3.war部署到tomcat下。
第四步:解压缩war包(启动tomcat解压)。
完成后关闭
将solr.war删除
第五步:需要把/solr-4.10.3/example/lib/ext目录下的所有的jar包添加到solr工程中。solr工程目录如下:
第六步:usr/local/solr下创建solrhome。把/root/solr-4.10.3/example/solr文件夹复制一份作为solrhome。
第七步:告诉solr服务solrhome的位置。需要修改web.xml
目录:
修改:
第八步:启动tomcat。
访问 ip:8080/solr
Zookeeper
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务。
应用场景:
1、集群管理
每个加入集群的机器都创建一个节点,写入自己的状态。监控父节点的用户会受到通知,进行相应的处 理。离开时删除节点,监控父节点的用户同样会收到通知。主从的管理、负载均衡、高可用的管理。集群的 入口。Zookeeper必须是集群才能保证高可用。Zookeeper有选举和投票的机制。集群中至少应该有三个节 点。
2、配置文件的集中管理
应用配置集中到节点上,应用启动时主动获取,并在节点上注册一个watcher,每次配置更新都会通知到应 用。
搭建solr集群时,需要把Solr的配置文件上传zookeeper,让zookeeper统一管理。每个节点都到zookeeper 上取配置文件。
3、分布式锁
Zookeeper能保证数据的强一致性,用户任何时候都可以相信集群中每个节点的数据都是相同的。一个用 户创建一个节点作为锁,另一个用户检测该节点,如果存在,代表别的用户已经锁住,如果不存在,则可以 创建一个节点,代表拥有一个锁。
4、名空间服务
分布式命名服务,创建一个节点后,节点的路径就是全局唯一的,可以作为全局名称使用。
5、分布式通知/协调
不同的系统都监听同一个节点,一旦有了更新,另一个系统能够收到通知。
集群搭建步骤
如上为要完成的solr集群的框架图。
集群需要的服务器
Zookeeper:3台
Solr:4台
伪分布式,zookeeper三个实例、tomcat(solr)需要四个实例。
Zookeeper需要安装jdk。
第一部分:Zookeeper集群搭建
第一步:需要把zookeeper的安装包上传到服务器。
第二步:把zookeeper解压。
第三步:把zookeeper向/usr/local/solr-cloud目录下复制三份。
第四步:配置zookeeper。
1、在zookeeper01目录下创建一个data文件夹。
2、在data目录下创建一个myid的文件
3、Myid的内容为1(02对应“2”,03对应“3”)
4、 5-8步,Zookeeper02、03以此类推。
5、进入conf文件,把zoo_sample.cfg文件改名为zoo.cfg
6、修改zoo.cfg,把dataDir=属性指定为刚创建的data文件夹。
7、修改zoo.cfg,把clientPort指定为不冲突的端口号(01:2181、02:2182、03:2183)
8、在zoo.cfg中添加如下内容:
server.1=192.168.169.154:2881:3881 //分别为投票、选举端口
server.2=192.168.25.154:2882:3882
server.3=192.168.25.154:2883:3883
第五步:启动zookeeper。
Zookeeper的目录下有一个bin目录。使用zkServer.sh启动zookeeper服务。
启动:./zkServer.shstart
关闭:./zkServer.shstop
查看服务状态:./zkServer.shstatus
第二部分:搭建solr集群
第一步:安装四个tomcat到solr-cloud下,修改其端口号不能冲突。8080~8083
第二步:向tomcat下部署solr。把单机版的solr工程复制到tomcat下即可。
第三步:为每个solr实例创建一solrhome。创建完成后的目录结构
第四步:为每个solr实例关联对应的solrhome。修改web.xml,参考单机版。
第五步:修改每个solrhome下的solr.xml文件。修改host、hostPort两个属性。分别是对应的ip及tomcat的端口号。
第六步:把配置文件上传到zookeeper。需要使用
/solr-4.10.3/example/scripts/cloud-scripts/zkcli.sh命令上传配置文件。
把/usr/local/solr-cloud/solrhome01/collection1/conf目录上传到zookeeper。
需要zookeeper集群已经启动。
./zkcli.sh -zkhost 192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183 -cmd upconfig -confdir /usr/local/solr-cloud/solrhome01/collection1/conf -confname myconf |
第七步:查看是否上传成功。
使用任意一个zookeeper的zkCli.sh命令。
第八步:告诉solr实例zookeeper的位置。需要修改tomcat的catalina.sh添加
JAVA_OPTS="-DzkHost=192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183"
每个tomcat都需要添加。
第九步:启动每个solr实例。
第十步:集群分片。
将集群分为两片,每片两个副本。
http://192.168.25.154:8080/solr/admin/collectiOnsaction=CREATE&name=collection2
&numShards=2&replicatiOnFactor=2
第十一步:删除不用collection1
http://192.168.25.154:8080/solr/admin/collections?action=DELETE&name=collection1
更多的命令请参数官方文档:apache-solr-ref-guide-4.10.pdf
另一种配置方法:如下
${solr_home}/collenction1/core.properties
numShards=2
name=collection1
shard=shard1
coreNodeName=core_node1
以上参数说明
numShards=2 //分片数量
name=collection1 //core名称
shard=shard1 //所属分片
coreNodeName=core_node1 //结点名称
1.1 SolrCloud测试
创建索引:
测试1:在一台solr上创建索引,从其它solr服务上可以查询到。
测试2:一次创建100个文档甚至更多,通过观察每个solr的core下边都有索引文档,说明索引文档是分片存储。
查询索引:
从任意一台Solr上查询索引,返回一个完整的结果,说明查询请求从不同的分片上获取数据,最终返回集群上所有匹配的结果。
1.2 solrJ访问solrCloud
public class SolrCloudTest {
// zookeeper地址
private static StringzkHostString ="192.168.101.7:2181,192.168.101.8:2181,192.168.101.9:2181";
// collection默认名称,比如我的solr服务器上的collection是collection2_shard1_replica1,就是去掉“_shard1_replica1”的名称
private static StringdefaultCollection ="collection2";
// 客户端连接超时时间
private static int zkClientTimeout = 3000;
// zookeeper连接超时时间
private static int zkCOnnectTimeout= 3000;
// cloudSolrServer实际
private CloudSolrServercloudSolrServer;
// 测试方法之前构造 CloudSolrServer
@Before
public void init() {
cloudSolrServer =new CloudSolrServer(zkHostString);
cloudSolrServer.setDefaultCollection(defaultCollection);
cloudSolrServer.setZkClientTimeout(zkClientTimeout);
cloudSolrServer.setZkConnectTimeout(zkConnectTimeout);
cloudSolrServer.connect();
}
// 向solrCloud上创建索引
@Test
public void testCreateIndexToSolrCloud()throws SolrServerException,
IOException {
SolrInputDocument document =new SolrInputDocument();
document.addField("id","100001");
document.addField("title","李四");
cloudSolrServer.add(document);
cloudSolrServer.commit();
}
// 搜索索引
@Test
public void testSearchIndexFromSolrCloud()throws Exception {
SolrQuery query =new SolrQuery();
query.setQuery("*:*");
try {
QueryResponse respOnse=cloudSolrServer.query(query);
SolrDocumentList docs = response.getResults();
System.out.println("文档个数:" + docs.getNumFound());
System.out.println("查询时间:" + response.getQTime());
for (SolrDocument doc : docs) {
ArrayList title = (ArrayList) doc.getFieldValue("title");
String id = (String) doc.getFieldValue("id");
System.out.println("id: " + id);
System.out.println("title: " + title);
System.out.println();
}
} catch (SolrServerException e) {
e.printStackTrace();
} catch (Exception e) {
System.out.println("Unknowned Exception!!!!");
e.printStackTrace();
}
}
// 删除索引
@Test
public void testDeleteIndexFromSolrCloud()throws SolrServerException, IOException {
// 根据id删除
UpdateRespOnseresponse=cloudSolrServer.deleteById("zhangsan");
// 根据多个id删除
// cloudSolrServer.deleteById(ids);
// 自动查询条件删除
// cloudSolrServer.deleteByQuery("product_keywords:教程");
// 提交
cloudSolrServer.commit();
}
}