Solr技术(附软件分享)

2020-07-27 10:36:13 浏览数 (1)

一. 介绍

全文检索

我们生活中的数据总体分为两种:结构化数据和非结构化数据。 1)结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。 2)非结构化数据:指不定长或无固定格式的数据,如邮件,word 文档等. 非结构化数据又一种叫法叫全文数据。 按照数据的分类,搜索也分为两种: 1)对结构化数据的搜索:如对数据库的搜索,用 SQL 语句。 2)对非结构化数据的搜索:如利用 windows 的搜索也可以搜索文件内容,Linux 下的 grep 命令,再如用 Google 和百度可以搜索大量内容数据

Lucene

Lucene 是一个高效的,基于 Java 的全文检索库。 Lucene 是 apache 软件基金会 4 jakarta 项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构 Lucene 的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现 全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene 是一套用于全文检索和搜寻的开源程序库,由 Apache 软件基金会支持和提供。Lucene 提供了一个简单却 强大的应用程序接口,能够做全文索引和搜寻。在 Java 开发环境里 Lucene 是一个成熟的 免费开源工具。就其本身而言,Lucene 是当前以及最近几年最受欢迎的免费 Java 信息检索程序库。

Solr简介

Solr 是基于 Lucene 的面向企业搜索的 web 应用 Solr 是一个独立的企业级搜索应用服务器,它对外提供类似于 Web-service 的 API 接口。用户可以通过 http 请求,向搜索引擎服务器提交一定格式的 XML 文件,生成索引;也 可以通过 Http Get 操作提出查找请求,并得到 xml/json 格式的返回结果。 Solr 是一个高性能,采用 Java5 开发,基于 Lucene 的全文搜索服务器。同时对其进行了扩展,提供了比 Lucene 更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能 进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文检索引擎。 文档通过 Http 利用 XML 加到一个搜索集合中。查询该集合也是通过 http 收到一个 XML/JSON 响应来实现。它的主要特性包括:高效、灵活的缓存功能,垂直搜索功能,高亮显示搜索结果,通过索引复制来提高可用性,提供一套强大 Data Schema 来定义字段, 类型和设置文本分析,提供基于 Web 的管理界面等。

二. Solr单机版安装

安装环境

solar基于基于java,所以需要jdk,部署在tomcat上所以需要tomcat

点击查看JDK与Tomcat安装与下载

安装solr

Solr 版本:solr-4.10.3.tgz.tgz

SolrLinux下的软件安装包以及中文分词器见末尾百度云1

安装Solr的Web服务

  1. 上传并解压Solr压缩包 压缩包在底部分享,自行解压到root目录下的一个文件夹中,无需放到/usr/local目录下
  2. Solr目录结构

bin:启动 solr 的一些脚本,但是需要依赖 jeety 容器 contrib:存放的是 solr 对第三方插件支持的内容 dist:solr 编译后所产生一些文件夹。War 或者是 jar example:是 solr 的案例。在该目录下有两个文件夹对于我们来说比较重要。 1 ) webapps:在该目录中存放了一个 solr 的 war 包。与 dist 目录下的那个 war 文 件是同一个,只是存放的目录及名称不同而已。 2 ) solr: 是 solr 的一个标准的索引库示例。undefined 3 ) lib/ext:该目录下存放的是一些日志处理器的 jar 包。Solr 的 web 服务也要依赖于日志 处理的 jar 包。所以我们在安装 solr 服务时,需要将该目录下的 jar 拷贝 给 solr 服务

  1. 安装solar服务 安装 solr 服务就是将 solr 下的webapps下的 solr.war ,拷贝到 tomcat 的 webapps 目录下。 cp solr.war /usr/local/tomcat/webapps/ -r
  2. 启动tomcat解压war包 启动后查看webapps下是否有solr文件夹
代码语言:txt复制
1. 添加服务所依赖jar包

由于我们在解压后的 solr 的项目中,需要依赖一些日志处理的 jar 包。所以我们 在添加依赖的 jar 包时,需要将原来的 war 删除掉。否则 tomcat 再次启动时,会将原来的目录覆盖掉。那么新添加的 jar 包也就没了。注意:在删除 war 包时,一定要在 tomcat 关闭的状态下 删除 solr.war 包。如果在 tomcat 启动状态下删除 war 包,那么 tomcat 在关闭时会将解压的目录 一并的也删除掉。

#查看解压后的solr下的ext文件夹 cd /root/chy/solr-4.10.3/example/lib/ext/ #复制全部jar到安装后的solr的lib文件夹下 cp * /usr/local/tomcat//webapps/solr/WEB-INF/lib/ #查看是否复制成功 cd /usr/local/tomcat/webapps/solr/WEB-INF/lib/

安装Solar的索引库

  1. 创建索引库目录 将该索引库拷贝到指定目录下(可以是任意目录),虽然具备任意性。但是也不能太随便。 应该放到/usr/local/solrhome。先创建 solrhome 目录 mkdir /usr/local/sorlhome
  2. 拷贝解压过后的solr索引库文件(solr的example目录下) cp solr/ /usr/local/solrhome/ -rf
  3. 进入solr索引库文件, 复制解压后的文件所在路径 root@bogon solr# pwd /usr/local/solrhome/solr
  4. 编辑tomcat下的solr的web.xml文件 cd /usr/local/tomcat/webapps/solr/WEB-INF/ #编辑该文件,将下图中的隐藏的设置放开,并修改value的值 vim web.xml

三. solr索引库(example目录下)

solrhome的目录结构

1. solr.xml 配置 solr 集群

2. collection1(索引库:solr core)

3. core.properties 设置索引库的名称 ,collection1子目录

4. data 存放索引 ,collection1子目录

5. conf 索引库的配置目录 (schema.xml:配置字段以及字段类型 )

索引库配置

索引路配置文件所在目录如下

定义索引库中的Field

代码语言:javascript复制
<field>:定义域 <field name="_version_" type="long" indexed="true" stored="true"/> 

name:表示域的名称,是强制必须有的属性 type:域类型的名称,与 fieldType 元素的 name 属性值对应,是强制必须有的属性 indexed:是否参与检索。 true 即表示需要对该域进行索引。默认值为 false stored:是否将 field 域中的内容存储到文档域,简单通俗的来说,就是你 这一个 field 需不需要被当作查询结果返回。 required:表示这个域是否是必须要在 document 中存在,默认值为 false,如果此配置项设为 true,则你的 document 中必须要添加此域,否则你创建索引时会抛异常。

定义索引库中的FieldType

代码语言:javascript复制
<fieldType>:定义域的类型 <fieldType name="string" class="solr.StrField" sortMissingLast="true" /> 

Name: 域类型的名称,作为域类型标识符存在,在定义域(Field)时使用的类型 (FieldType)属性就是域类型的名称。 Class: 域类型的数据类型,该属性指向的是 solr 中的已定义的类型,或者是用户定 义的类型,域类型中的数据会被初始化成 class 执行类类的对象。 sortMissingFirst/sortMissingLast:控制当排序域的值不存在时该文档(Document) 所在队列的位置。true 是则在队头/队尾

定义索引库中的CopyField

代码语言:javascript复制
<copyField>:复制域。可实现更新与查询分离 <copyField source="item_title" dest="item_keywords"/> 

Source:源域 Dest:目标域

solr中的索引机制

正排索引

正排索引是以文档的 ID 为关键字,索引文档中每个字的位置信息,并记录每个关键词出现的次数. 查找时扫描索引中每个文档中字的信息直到找出所有包含查询关键字的文档。 但是在查询的时候需对所有的文档进行扫描以确保没有遗漏,这样就使得检索时间大大延长,检索效率低下。 尽管正排索引的工作原理非常的简单,但由于其检索效率太低,除非在特定情况下, 否则实用性价值不大。

倒排索引(反向索引)

对数据进行分析,抽取出数据中的词条,以词条作为 key,对应数据的存储位置作为 value,实现索引的存储。这种索引称为倒排索引。 当 solr 存储文档时, solr 会首先对文档数据进行分词 ,创建索引库和文档数据库。所谓的分词是指:将一段字符文本按照一定的规则分成若干个单词。

配置中文分词器(IK Analyzer)

  1. 上传并解压相关jar包 " "对空格使用转义字符进行处理 unzip IK Analyzer 2012FF_hf1.zip
  2. 将中文分词器的配置文件以及jar包拷贝到Solr所对应的目录下 创建 classes 目录 cd /usr/local/tomcat/webapps/solr/WEB-INF/ mkdir classes 将中文分词器的配置(3个)文件拷贝到class目录下 #如果不能拷贝,可以直接解压IK,然后将这三个文件通过Filezila上传即可 cp ext_stopword.dic IKAnalyzer.cfg.xml mydict.dic /usr/local/tomcat/webapps/solr/WEB-INF/classes/

将解压好的文件中的jar包放到solr中存放jar包的地方

cp IKAnalyzer2012FF_u1.jar /usr/local/tomcat/webapps/solr/WEB-INF/lib/

  1. 在 schema.xml 中配置中文分词器

<!--引入中文分词器--> <fieldType name="text_ik" class="solr.TextField"> <analyzer class="org.wltea.analyzer.lucene.IKAnalyzer"/> </fieldType>

将name的类型改为中文分词器所定义的类型(也可自定义一个field,用于下面的测试)

  1. 效果: 在没开启中文分词器前 访问: http://192.168.179.138:8080/solr/

开启之后

solr管理页面操作

页面展示

页面主要模块功能介绍

名称

作用

Dashboard(仪表盘)

访问 http://localhost:8080/solr 时,出现该主页面,可查看到 solr 运行时间、solr 版本, 系统内存、虚拟机内存的使用情况

Logging(日志)

显示 solr 运行出现的异常或错误

Core Admin (core 管理)

主要有 Add Core(添加核心), Unload(卸载核心),Rename(重命名核心),Reload(重 新加载核心),Optimize(优化索引库) Add Core 是添加 core : 主 要 是 在 instanceDir 对 应 的 文 件 夹 里 生 成 一 个 core.properties 文件

Java Properties

可查看到 java 相关的一些属性的信息

Thread Dump

查看每个线程的详细信息,以及状态信息

Core Selecter(core 选择器)

主要有 overview(概览), ,Analysis(分析) , Dataimport(导入数据) ,Documents 索引的相关操作, Files 文件夹 , Files 文件夹 ,Plugins /stats 插件的信息以及统计 , Query(查询页面) ,Request-Handler(qt): 请求处理器

四. SolrJ的使用

solrJ 是访问 Solr 服务的 JAVA 客户端,提供索引和搜索的请求方法,SolrJ 通常嵌入在业务系统中,通过 solrJ 的 API接口操作 Solr 服务。

创建项目

创建Maven项目,添加两个jar坐标

代码语言:javascript复制
<dependencies>
		<!-- solrj的jar -->
		<dependency>
			<groupId>org.apache.solr</groupId>
			<artifactId>solr-solrj</artifactId>
			<version>4.10.3</version>
		</dependency>
		
		<!-- 导入LogFactory -->
	<dependency>
	    <groupId>commons-logging</groupId>
	    <artifactId>commons-logging</artifactId>
	    <version>1.2</version>
	</dependency>
	</dependencies>

创建测试类

代码语言:javascript复制
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
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;

public class TestSolr {
	public static void main(String[] args) throws Exception {
		//TestSolr.testSolrDemo();
		//TestSolr.solrDelete();
		TestSolr.solrQuery();
	}
	
	/**
	 * 添加文档到索引库中
	 * @throws Exception
	 */
	public static void testSolrDemo() throws Exception {
		//创建一个solrJ的连接对象
		SolrServer server=new HttpSolrServer("http://192.168.179.131:8080/solr");
		
		for (int i = 1; i < 20 ;i  ) {
			//创建一个solr文传对象
			SolrInputDocument doc=new SolrInputDocument();
			//向文档中添加需要插入的索引
			doc.addField("id", "chy" i);
			doc.addField("item_title", "时间静止不是简史" i);
			doc.addField("item_price", 666 i);
			//将文档插入到solr的索引库中
			server.add(doc);
		}
		
		
		
		//事务的提交
		server.commit();
	}
	
	/**
	 * 从索引库中删除文档
	 * @throws Exception
	 */
	public static void solrDelete() throws Exception {
		//创建一个solrJ对象
		SolrServer server =new HttpSolrServer("http://192.168.179.131:8080/solr");
		
		//给定删除条件
			//1.根据主键删除
			//server.deleteById("chy");
			//2.根据查询删除
			server.deleteByQuery("*:*");
		
		//事务提交
			server.commit();
	}
	
	/**
	 * 从索引库中查询文档
	 * @throws Exception
	 */
	public static void solrQuery() throws Exception {
		//创建一个solrJ对象
		SolrServer server=new HttpSolrServer("http://192.168.179.131:8080/solr");
		//创建查询条件
		SolrQuery query=new SolrQuery();
		query.setQuery("chy0");
		query.set("df", "item_keywords");
		
		//设置分页	
		query.setStart(0);
		query.setRows(10);
		
		//执行查询
		//QueryResponse:封装查询结果集
		QueryResponse res=server.query(query);
		SolrDocumentList results = res.getResults();
		System.out.println(results.getNumFound());//h获取查询结果总条数
		
		//List.getNUmFound()数据总条数
		for(SolrDocument solr : results ) {
			System.out.println(solr);
			System.out.println(solr.get("item_title"));
			System.out.println(solr.get("item_price"));
		}
	}
}

测试效果

插入

查询

删除

五、创建solr集群(SolrCloud)

SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模容错分布式索引和检索能力时 , 使用 SolrCloud。当一个系统的索引数据量少的时候是不需要使用SolrCloud的,当索引量很大,搜索请求并发很高,这时需要使用SolrCloud 来满足这些需求。 SolrCloud是基于 Solr和 Zookeeper的分布式搜索方案,它的主要思想是使用Zookeeper作为集群的配置信息中心。

SolrCloud特色

1) 集中式的配置信息

2) 自动容错

3) 近实时搜索

4) 查询时自动负载均衡

solr集群结构图

安装集群环境

0 ) 在/usr/local/ 下创建一个solrcloud目录,在下面创建如下文件 1)在 192.168.179.131(Linux环境下) 环境中安装3个 zookeeper 集群 2) 创建并安装 4 个 tomcat 3) 使用已安装好的单机版 solr 作为集群的节点使用,并复制4个solrhome

安装tomcat: https://blog.csdn.net/qq_43371556/article/details/97012990 安装zookeeper集群: https://blog.csdn.net/qq_43371556/article/details/96477011

安装4个tomcat实例修改 tomcat 启动关闭运行的端口,使其能够同时运行,修改 solr 服务中指向 solr 索引库的路径

创建集群

1 上传索引库配置文件,打开的是解压后的目录下,复制好命令以后点回车,注意端口号

代码语言:javascript复制
./zkcli.sh -zkhost 192.168.179.131:2181,192.168.179.131:2182,192.168.179.131:2183 -cmd upconfig -confdir /usr/local/solrcloud/solrhome1/solr/collection1/conf -confname myconf 

2. 查看是否上传成功,打开任意zookeeper,运行客户端

如果查询myconf节点出现下图则表示上传成功

3 修改4个索引库 solrhome 下的 solr.xml 文件,指定当前实例运行的 ip地址及端口号。

4 修改每一台 solr的 tomcat 的 bin 目录下 catalina.sh 文件中加入 DzkHost 指定 zookeeper 服务器地址 注意逗号之间不能有空格

代码语言:javascript复制
JAVA_OPTS="-DzkHost=192.168.179.131:2181,192.168.179.131:2182,192.168.179.131:2183" 

5 启动每一个tomcat,通过浏览器访问任意一个solr如: http://192.168.179.131:8080/solr/ 来查看solr集群solrcloud是否安装成功

6 solrcloud安装成功后,创建一个新的 collection,并分两片,每片是一主一备

浏览器下输入,如下图然后返回到solr的cloud界面显示第二个图则该步骤成功

代码语言:javascript复制
http://192.168.179.131:8080/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2

注:该图collection的两个节点应该是绿色的,如果不是绿色,如果不是就重新删除4个索引库并修改4个索引库 solrhome 下的 solr.xml 文件,指定当前实例运行的 ip地址及端口号。 坑啊~~~

7 删除原来的逻辑索引库 ,成功后效果如下,最终成功(ヽ( ̄▽ ̄)و 好累~~~)

代码语言:javascript复制
http://192.168.179.131:8080/solr/admin/collections?action=DELETE&name=collection1 

以后重新启动solr集群时需要: 关闭防火墙 打开Zookeeper集群 打开tomcat

  1. SolrLinux下的软件安装包以及中文分词器 链接:https://pan.baidu.com/s/1WzFwwRaRH9gomZOMIpOMcg 提取码:rw6p

0 人点赞