分布式技术入坑指南(三)

分布式技术入坑指南(三)

11.Solr索引库的搭建与使用(单机版和集群版)

下载地址:https://lucene.apache.org/solr/

单机版

搭建

* 版本:solr-4.10.3
* windows下的配置完全一样。

第一步:把solr 的压缩包上传到Linux系统
第二步:解压solr。
第三步:把solr部署到Tomcat下。

路径:`/opt/solr-4.10.3/dist/solr-4.10.3.war`

第四步:解压缩war包。可以启动Tomcat解压。

第五步:把/root/solr-4.10.3/example/lib/ext目录下的所有的jar包,添加到solr工程中。
第六步:创建一个solrhome。安装包自带有一个solrhome:/example/solr,该目录就是一个solrhome。复制此目录到自己创建solrhome。
第七步:关联solr及solrhome。需要修改solr工程的web.xml文件。

1
2
3
4
5
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>/opt/solrhome</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>

第八步:启动Tomcat
http://192.168.184.130:8080/solr/

使用

添加文档必须有id域,其他域 必须在solr的schema.xml中定义。

schema.xml中定义

本系统业务所需要的业务域有:
1、商品Id 使用schema.xml中的id域
2、商品标题
3、商品卖点
4、商品价格
5、商品图片
6、分类名称
7、商品描述

配置中文分词器

创建对应的业务域。需要制定中文分析器。
下载地址:https://code.google.com/archive/p/ik-analyzer/downloads

第一步:把中文分析器添加到solr工程中。
1、把IKAnalyzer2012FF_u1.jar添加到solr工程的lib目录下。
2、把扩展词典、配置文件放到solr工程的WEB-INF/classes目录下。

第二步:配置一个FieldType,制定使用IKAnalyzer

修改solrHome中的schema.xml文件,添加FieldType。
路径:`/opt/solrhome/collection1/conf/schema.xml`
1
2
3
<fieldType name="text_ik" class="solr.TextField">
<analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/>
</fieldType>

第三步:配置业务域,type制定使用自定义的FieldType。
设置业务系统Field

1
2
3
4
5
6
7
8
9
10
11
12
<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_sell_point" type="text_ik" indexed="true" stored="true"/>
<field name="item_price" type="long" indexed="true" stored="true"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_category_name" type="string" indexed="true" stored="true" />
<field name="item_desc" type="text_ik" indexed="true" stored="false" />

<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_sell_point" dest="item_keywords"/>
<copyField source="item_category_name" dest="item_keywords"/>
<copyField source="item_desc" dest="item_keywords"/>

Alt text
第四步:重启tomcat
Alt text

Tomcat启动后访问不了?

多次出现这样的问题,启动之后访问不了,一定要看日志!/opt/apache-tomcat-8.5.32/logs/catalina.out

  • 由于本机中dubbo-admin和solr放在了同一个tomcat,而dubbo-admin启动需要先开启zookeeper服务,所以tomcat一直处于启动状态。
  • Linux中多次启动关闭Tomcat下次启动会异常,需要强制杀死进程 kill -s 9 pid 然后再启动。

测试CRUD

使用SolrJ可以实现索引库的增删改查操作。

Maven:

1
2
3
4
5
<!-- solr客户端 -->
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
</dependency>

添加到文档

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
/**
* 第一步:把solrJ的jar包添加到工程中。
* 第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
* 第三步:创建一个文档对象SolrInputDocument对象。
* 第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
* 第五步:把文档添加到索引库中。
* 第六步:提交。
*
* @throws Exception
*/
@Test
public void addDocument() throws Exception {
// 第一步:把solrJ的jar包添加到工程中。
// 第二步:创建一个SolrServer,使用HttpSolrServer创建对象。
SolrServer solrServer = new HttpSolrServer("http://192.168.184.130:8080/solr");
// 第三步:创建一个文档对象SolrInputDocument对象。
SolrInputDocument document = new SolrInputDocument();
// 第四步:向文档中添加域。必须有id域,域的名称必须在schema.xml中定义。
document.addField("id", "test001");
document.addField("item_title", "测试商品");
document.addField("item_price", "199");
// 第五步:把文档添加到索引库中。
solrServer.add(document);
// 第六步:提交。
solrServer.commit();
}

删除文档

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
/**
* 第一步:创建一个SolrServer对象。
* 第二步:调用SolrServer对象的根据id删除的方法。
* 第三步:提交。
*
* @throws Exception
*/
@Test
public void deleteDocumentById() throws Exception {
// 第一步:创建一个SolrServer对象。
SolrServer solrServer = new HttpSolrServer("http://192.168.184.130:8080/solr");
// 第二步:调用SolrServer对象的根据id删除的方法。
solrServer.deleteById("1");
// 第三步:提交。
solrServer.commit();
}

/**
* 根据查询删除
*/
@Test
public void deleteDocumentByQuery() throws Exception {
SolrServer solrServer = new HttpSolrServer("http://192.168.184.130:8080/solr");
solrServer.deleteByQuery("title:change.me");
solrServer.commit();
}

查询文档

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
60
61
62
63
64
65
66
67
68
69
70
71
/**
* 第一步:创建一个SolrServer对象
* 第二步:创建一个SolrQuery对象。
* 第三步:向SolrQuery中添加查询条件、过滤条件。。。
* 第四步:执行查询。得到一个Response对象。
* 第五步:取查询结果。
* 第六步:遍历结果并打印。
*
* @throws Exception
*/
@Test
public void queryDocument() throws Exception {
// 第一步:创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.184.130:8080/solr");
// 第二步:创建一个SolrQuery对象。
SolrQuery query = new SolrQuery();
// 第三步:向SolrQuery中添加查询条件、过滤条件。。。
query.setQuery("*:*");
// 第四步:执行查询。得到一个Response对象。
QueryResponse response = solrServer.query(query);
// 第五步:取查询结果。
SolrDocumentList solrDocumentList = response.getResults();
System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
// 第六步:遍历结果并打印。
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_price"));
}
}

/**
* 高亮查询
*/
@Test
public void queryDocumentWithHighLighting() throws Exception {
// 第一步:创建一个SolrServer对象
SolrServer solrServer = new HttpSolrServer("http://192.168.184.130:8080/solr");
// 第二步:创建一个SolrQuery对象。
SolrQuery query = new SolrQuery();
// 第三步:向SolrQuery中添加查询条件、过滤条件。。。
query.setQuery("测试");
//指定默认搜索域
query.set("df", "item_keywords");
//开启高亮显示
query.setHighlight(true);
//高亮显示的域
query.addHighlightField("item_title");
query.setHighlightSimplePre("<em>");
query.setHighlightSimplePost("</em>");
// 第四步:执行查询。得到一个Response对象。
QueryResponse response = solrServer.query(query);
// 第五步:取查询结果。
SolrDocumentList solrDocumentList = response.getResults();
System.out.println("查询结果的总记录数:" + solrDocumentList.getNumFound());
// 第六步:遍历结果并打印。
for (SolrDocument solrDocument : solrDocumentList) {
System.out.println(solrDocument.get("id"));
//取高亮显示
Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
List<String> list = highlighting.get(solrDocument.get("id")).get("item_title");
String itemTitle = null;
if (list != null && list.size() > 0) {
itemTitle = list.get(0);
} else {
itemTitle = (String) solrDocument.get("item_title");
}
System.out.println(itemTitle);
System.out.println(solrDocument.get("item_price"));
}
}

搭建搜索服务工程

Alt text

分布式集群版

一些概念

SolrCloud
是Solr提供基于Solr和Zookeeper的分布式搜索方案,它的主要思想是使用Zookeeper作为集群的配置信息中心。

Solr集群的系统架构

Alt text

需要实现的solr集群架构

Alt text

Zookeeper作为集群的管理工具。
1、集群管理:容错、负载均衡。
2、配置文件的集中管理
3、集群的入口

搭建伪分布式

  • 需要三个zookeeper节点
  • 需要四个tomcat节点

Zookeeper集群搭建

第一步:创建solr集群的根目录 /opt/solrCloud/
第二步:解压 zookeeper.tar.gz 并在根目录下复制三份

1
2
3
drwxr-xr-x. 11 1000 1000    4096 7月  22 20:15 zookeeper01
drwxr-xr-x. 11 root root 4096 7月 22 20:18 zookeeper02
drwxr-xr-x. 11 root root 4096 7月 22 20:18 zookeeper03

第三步:在每一个zookeeper中创建data目录,在data中创建文件 myid,内容就是每个实例的id,比如:1,2,3
第四步:把每一个zookeeper下的conf目录下的zoo_sample.cfg文件改名为zoo.cfg
第五步:修改配置文件

  • dataDir
  • clientPort
  • 集群的节点列表

Alt text
1.集群的节点列表,1、2、3代表节点的id
2.ip后的端口号是zookeeper内部通讯的端口和投票选举的端口,每个端口不能重复。

第六步:启动每个zookeeper实例

1
2
3
4
5
6
7
8
9
10
[root@yuzh solrCloud]# vim zookeeper_start_all.sh 

cd /opt/solrCloud/zookeeper01/bin
./zkServer.sh start

cd /opt/solrCloud/zookeeper02/bin
./zkServer.sh start

cd /opt/solrCloud/zookeeper03/bin
./zkServer.sh start

授权、启动。

Solr集群搭建

第一步:创建四个tomcat实例。每个tomcat运行在不同的端口。8180、8280、8380、8480
第二步:部署solr的war包。把单机版的solr工程复制到集群中每个的tomcat中。
第三步:为每个solr实例创建一个对应的solrhome。使用单机版的solrhome复制四份。

1
2
3
4
5
6
7
8
drwxr-xr-x.  4 root root 4096 7月  23 14:40 solrhome01
drwxr-xr-x. 4 root root 4096 7月 23 14:40 solrhome02
drwxr-xr-x. 4 root root 4096 7月 23 14:40 solrhome03
drwxr-xr-x. 4 root root 4096 7月 23 14:40 solrhome04
drwxr-xr-x. 9 root root 4096 7月 22 20:23 tomcat01
drwxr-xr-x. 9 root root 4096 7月 22 20:24 tomcat02
drwxr-xr-x. 9 root root 4096 7月 22 20:24 tomcat03
drwxr-xr-x. 9 root root 4096 7月 22 20:24 tomcat04

第四步:需要修改每个tomcat实例中的solr的web.xml文件。把solrhome关联起来。

1
2
3
4
5
<env-entry>
<env-entry-name>solr/home</env-entry-name>
<env-entry-value>/opt/solrCloud/solrhome01</env-entry-value>
<env-entry-type>java.lang.String</env-entry-type>
</env-entry>

第五步:配置SolrCloud相关的配置。每个solrhome下都有一个solr.xml,把其中的ip及端口号配置好。

1
2
3
4
5
6
7
8
9
<solrcloud>
<!-- 本机IP -->
<str name="host">192.168.184.130</str>
<!-- 每个solr对应的solrhome所属的tomcat端口号 -->
<int name="hostPort">8180</int>
<str name="hostContext">${hostContext:solr}</str>
<int name="zkClientTimeout">${zkClientTimeout:30000}</int>
<bool name="genericCoreNodeNames">${genericCoreNodeNames:true}</bool>
</solrcloud>

第六步:让zookeeper统一管理配置文件。

需要把`solrhome/collection1/conf`目录上传到zookeeper。上传任意solrhome中的配置文件即可。(需要保证zookeeper集群是启动的状态)

使用工具上传配置文件:
执行
/opt/solr-4.10.3/example/scripts/cloud-scripts/zkcli.sh
注意不是zookeeper/bin中的zkCli.sh

./zkcli.sh -zkhost 192.168.184.130:2181,192.168.184.130:2182,192.168.184.130:2183 -cmd upconfig -confdir /opt/solrCloud/solrhome01/collection1/conf -confname myconf

第七步:修改每一个tomcat/bin目录下的catalina.sh 文件,关联solrzookeeper
把此配置添加到配置文件中:

1
JAVA_OPTS="-DzkHost=192.168.184.130:2181,192.168.184.130:2182,192.168.184.130:2183"

Alt text

第八步:启动每个tomcat实例。要保证zookeeper集群是启动状态。
第九步:访问集群 http://192.168.184.130:8180/solr

创建新的Collection进行分片处理:
http://192.168.184.130:8180/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2
删除不用的Collection:
http://192.168.184.130:8180/solr/admin/collections?action=DELETE&name=collection1

注意:关闭防火墙吧,端口太多了。每次开机之后防火墙会自动重启。

使用solrJ管理集群

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
60
package xyz.taotao.search.test;

import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.CloudSolrServer;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.junit.Test;

/**
* Created with IntelliJ IDEA.
* Author: yu_zh
* DateTime: 2018/07/23 14:46
* Solr集群版客户端连接测试
*/
public class SolrCloudTest {

@Test
public void add() throws Exception {
//1.创建集群版Solr,传入zookeeper集群地址。
CloudSolrServer solrServer = new CloudSolrServer("192.168.184.130:2181,192.168.184.130:2182,192.168.184.130:2183");
//2.设置默认集合属性
solrServer.setDefaultCollection("collection2");
//3.创建文档对象
SolrInputDocument document = new SolrInputDocument();
//4.向文档对象添加业务域(这些域要在配置文件 schema.xml 中存在)
document.addField("id", "test01");
document.addField("item_title", "测试商品");
document.addField("item_price", "100");
//5.把文档对象写入索引库
solrServer.add(document);
//6.提交操作
solrServer.commit();
}

@Test
public void query() throws Exception {
//创建solrServer对象实现类CloudSolrServer对象
CloudSolrServer solrServer = new CloudSolrServer("192.168.184.130:2181,192.168.184.130:2182,192.168.184.130:2183");
//设置查询的默认集合
solrServer.setDefaultCollection("collection2");
//创建SolrQuery查询
SolrQuery solrQuery = new SolrQuery();
//添加查询条件
solrQuery.setQuery("*:*");
//执行查询,得到结果集对象
QueryResponse queryResponse = solrServer.query(solrQuery);
//操作结果
SolrDocumentList resultList = queryResponse.getResults();
System.out.println("总记录数:" + resultList.getNumFound());
for (SolrDocument solrDocument : resultList) {
System.out.println(solrDocument.get("id"));
System.out.println(solrDocument.get("item_title"));
System.out.println(solrDocument.get("item_price"));
}
}

}

把搜索业务功能切换到集群版

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">

<!-- 单机版 -->
<!-- <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<constructor-arg name="baseURL" value="http://192.168.184.130:8080/solr"/>
</bean>-->

<!-- 集群版 -->
<bean id="cloudSolrServer" class="org.apache.solr.client.solrj.impl.CloudSolrServer">
<constructor-arg name="zkHost"
value="192.168.184.130:2181,192.168.184.130:2182,192.168.184.130:2183"></constructor-arg>
<property name="defaultCollection" value="collection2"></property>
</bean>

</beans>

OVER~~😭

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×