一、Solr基础
介绍
Solr是一个文档储存与检索引擎。
Solr是基于Lucene做的,Lucene是一套信息检索工具包,但并不包含搜索引擎系统,它包含了索引结构、读写索引工具、相关性工具、排序等功能,因此在使用Lucene时你仍需要关注搜索引擎系统,例如数据获取、解析、分词等方面的东西。
Solr的目标是打造一款企业级的搜索引擎系统,因此它更接近于我们认识到的搜索引擎系统,它是一个搜索引擎服务,通过各种API可以让你的应用使用搜索服务,而不需要将搜索逻辑耦合在应用中。而且Solr可以根据配置文件定义数据解析的方式,更像是一个搜索框架,它也支持主从、热换库等操作。
什么是文档
每个文档包含一个或者多个字段,提交到Solr处理的每份数据都是文档。
文档可以是一篇报道,一份简历,一段话,甚至是一本书。
倒排索引
Lucene是一个Java类库,用于倒排索引的构建与管理,倒排索引是专门用于匹配查询词项与文本文档的数据结构。
倒排索引构建过程如下图:
Solr创建索引过程
索引的创建过程可以分为:1、分词组件 2、语言处理组件 3、索引组件
一、把原始文档交给分词组件(Tokenizer)
1、将文档分成一个一个单独的单词
2、去除标点符号
3、去除停词(stop word)
二、词汇单元(Token)传给语言处理组件(Linguistic Processor)
1、变为小写(Lowercase)。
2、将单词缩减为*词根形式,如”cars”到”car”等。这种操作称为:stemming。
3、将单词转变为词根形式,如”drove”到”drive”等。这种操作称为:lemmatization
三、 得到的词(Term)传递给索引组件(Indexer)
1、利用得到的词(Term)创建字典
2、对字典按字母顺序排序
3、合并相同的词(Term)成为文档倒排(Posting List)链表
Solr查询过程
1、对查询内容进行词法分析、语法分析、语言处理
2、搜索索引,得到符合语法树的文档集合
3、根据查询语句与文档的相关性,对结果进行排序
如何储存
为了加快查找速度,倒排表无论是文档号及词频,还是位置信息,都是以跳跃表的结构存在的。
https://www.cnblogs.com/bonelee/p/6394920.html
Solr和ES区别
1、solr利用zookeeper进行分布式管理,而es自身带有分布式系统管理功能
2、solr官网提供的功能更多,而es本身更注重于核心功能,高级功能有多个第三方插件
3、solr是传统搜索应用的有力解决方案,但是es更适合用于新兴的实时搜索应用。solr不考虑建索引的同时进行搜索,速度更快。
4、Solr 支持更多格式的数据,而 Elasticsearch 仅支持json文件格式;
https://zhuanlan.zhihu.com/p/24286279
为什么ES实时性强
Lucene使用Searcher来执行索引的读取,一次提交不足以保证新索引被搜索到,出于性能考虑,Lucen延迟了耗时的刷新(Searcher重新打开)。
Searcher会每秒刷新一次,ES提供了强制刷新API。
一个Index由若干段组成,搜索的时候按段搜索,我们索引一条段后,每个段会通过fsync 操作持久化到磁盘,而fsync 操作比较耗时,如果每索引一条数据都做这个full commit(rsync)操作,提交和查询的时延都非常之大,所以在这种情况下做不到实时的一个搜索。
针对这个问题的解决是在Elasticsearch和磁盘之间引入一层称为FileSystem Cache的系统缓存,正是由于这层cache的存在才使得es能够拥有更快搜索响应能力。
然后在es中新增的document会被收集到indexing buffer区后被重写成一个segment写入filesystem cache中,这个操作相对耗时较少,之后经过一定的间隔或外部触发后才会被flush到磁盘上,这个操作非常耗时。但只要sengment文件被写入cache后,这个sengment就可以打开和查询,从而确保在短时间内就可以搜到,而不用执行一个full commit也就是fsync操作,这是一个非常轻量级的处理方式而且是可以高频次的被执行,而不会破坏es的性能。
相关度
1、默认相似度
Solr的相关度得分是基于Similarity类的,Similarity是Java类,它根据给定查询定义了搜索结果相关度得分的计算方法。
2、词项频次
3、反向文档频次
4、词项权重
5、规范化因子
查准率与查全率
1、查准率
查询的结果是不是我想要?
查准率 = 正确匹配的文档数量 / 返回的文档数量
2、查全率
查全率衡量的是搜索结果的全面性。
查全率 = 返回的正确匹配的文档数 / 全部正确匹配的文档数。
3、查准率与查全率之间的平衡
最大限度提升查准率与查全率是绝大多数搜索相关度优化的最终目标。
大部分技术更倾向于提高返回完整文档集的查全率。
Solr和Lucene的区别?
Lucene是一个基于Java的全文信息检索工具包,局限于Java调用,而Solr底层的核心技术是使用Lucene来实现的,是一个跨平台的搜索应用,而且提供了一个HTTP的管理页面。
倒排索引和全文检索
倒排索引就是讲数据中的词拆分构建一个大表,将关键字拆出来,后面带上这个文章的documentid号,例如中间这个就是倒排索引了。
全文检索就比较好理解的,就是当我们输入“全瓦解”,会被拆分成”全”,“瓦解”2个此,用2个词去倒排索引里面去检索数据,检索到的数据返回。整个过程就叫做全文检索
什么是全文检索?
数据总体分为两类:结构化数据和非结构化数据。
- 结构化数据:指具有固定格式或有限长度的数据,如数据库,元数据等。
- 非结构化数据:指不定长或无固定格式的数据。非结构化数据又一种叫法叫全文数据。
对结构化数据的搜索:如对数据库的搜索,用SQL语句。再如对元数据的搜索,如利用windows搜索对文件名,类型,修改时间进行搜索等。
对非结构化数据的搜索:如利用windows的搜索也可以搜索文件内容,Linux下的grep命令,再如用Google和百度可以搜索大量内容数据。
全文检索:即先建立索引,再对索引进行搜索。索引是从非结构化数据中提取出之后重新组织的信息。
倒排索引和常规索引区别
常规索引:
文档——>关键词 但是这样检索关键词的时候很费力,要一个文档一个文档的遍历一遍。
倒排索引:倒排索引是关键词到文档的映射
关键词——>文档 这样,只要有关键词,立马就能找到她在那个文档里出现过,然后就可以查出整个文档。
中文分析器 IK Analyzer
IK Analyzer 是一个开源的,基亍 java 语言开发的轻量级的中文分词工具包。可以自己添加扩展词典和停用词典。
配置域
域相当于数据库的字段
域的常用属性:
name:指定域的名称
type:指定域的类型
indexed:是否索引
stored:是否存储
required:是否必须
multiValued:是否多值
我们根据自己的需求自定义域,例如:id,标题,价格,品牌,商家名称,分类名称,商品的SKU的ID,图片地址等。
复制域
复制域的作用在于将某一个 Field 中的数据复制到另一个域中,就是说可以将域进行组合
我们把标题、品牌、分类名称、商品放进复制域中,用来后续的组合查询
注意:复制域不需要存储,只是逻辑上进行组合,属性就选择Ik分词器,需要建立索引搜索
动态域
将两个域的域名复制到一个text文本域中。
我们数据库中的规格字段,存储的是动态的值,不固定的,需要动态拼接,在末尾+*号表示。
我们为什么要使用Solr来进行查询,而不用MySQL呢?
- 数据库中不能分词
- 在数据库中我们只能使用Like来模糊搜索,太低效,太慢
- 在电商项目中,使用搜索会承担很大的压力,每一个人过来搜一下,数据库扛不住压力
- 所以我们需要使用更专业的工具来实现搜索功能,我们要把数据库中的内容导入到Solr的索引库中,并且要随着数据库中的变化而变化
批量数据导入
思路:通过Mybatis来查询数据库中的数据,在调用批量添加的方法到Solr索引库
SolrCloud
SolrCloud(solr 云)是 Solr 提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud。当一个系统的索引数据量少的时候是不需要使用 SolrCloud的,当索引量很大,搜索请求并发很高,这时需要使用 SolrCloud 来满足这些需求。 SolrCloud 是基于 Solr 和Zookeeper的分布式搜索方案,它的主要思想是使用 Zookeeper作为集群的配置信息中心。
Zookeeper 作为集群的配置信息中心。
它有几个特色功能:
- 集中式的配置信息
- 自动容错
- 近实时搜索
- 查询时自动负载均衡
Solr Cloud的结构
solrcloud为了降低单机的处理压力,需要由多台服务器共同来完成索引和搜索任务。实现的思路是将索引数据进行Shard分片,每个分片由多台服务器共同完成,当一个索引或搜索请求过来时会分别从不同的Shard的服务器中操作索引。
solrcloud是基于solr和zookeeper部署,zookeeper是一个集群管理软件,solrcloud需要由多台solr服务器组成,然后由zookeeper来进行协调管理。
物理结构和逻辑结构
一个Solr Cloud集群从架构方面来讲分成物理结构和逻辑结构进行理解.
物理结构:
一个Solr Cloud集群,由多台solr服务器(安装了solr对应的tomcat服务器的邮件服务器)组成,每一台solr服务器又是可以安装多个tomcat,每个tomcat中安装一个solr.war.每个solr.war对应一个solrhome,每个solrhome只需要配置一个solrcore.
逻辑结构:
一个Solr Cloud从逻辑上可以看成是一个collection(索引集合).一个collection可以从逻辑上被分为多个片shard,每个片又可以由多个solrcore组成,一个片的多个solrcore需要有一个master,其他的都是slave.
Solr Cloud架构的优势:
高扩展:1、solrcloud集群中使用分片的架构,每片提供搜索和索引的内容是不一样的。这样架构的好处是可以高扩展。(分片)
高可用:2、solrcloud集群中同一片由不同的solrcore组成,这样如果一台solrcore失败,是不会影响使用,这样就解决了高可用。而且还可以解决高并发。(副本集)
地理位置搜索(GeoHash:经纬度转为base32的编码,让它来标记区域)
geohash基本原理是将地球理解为一个二维平面,将平面递归分解成更小的子块,每个子块在一定经纬度范围内拥有相同的编码,这种方式简单粗暴,可以满足对小规模的数据进行经纬度的检索
在Solr索引将经纬度的二位坐标通过geoHash变成一维的字符串base32的坐标。
比如将经纬度(34.2,45.4)转换base32的DRT2Y,R到D的子区域,T是R的子区域。
进入D区域,则看到又分为若干区域,而R为其子区域:
所以让base32的编码来标记区域。
具体流程以(39.92324 纬度, 116.3906 经度)为例,首先将纬度的范围(-90, 90)平分成两个区间(-90, 0)、(0, 90),如果目标纬度位在(-90,0),则编码为0,在(0,90)则编码为1。
所以通过16轮的计算后得到经度39.92324的编码为:
1011 1000 1100 0111 1001
经度也用同样的算法,对(-180, 180)多轮的依次细分计算:
得到纬度116.3906的编码为1101 0010 1100 0100 0100
经纬度的编码都计算完毕后,接下来就需要合并经纬度的编码,规则是以经度开始,依次每次取一位合并成5位的新编码,如上图红色字标示顺序所示:
完成合并编码后就需要将该编码和base32编码表对应起来,做法是每5位为一个十进制数,以11100为例,它的十进制数是28,所以对应的base32编码表示W,如下图所示:
其他的五位编码依次从表中找到对应位置后,(39.92324 纬度, 116.3906 经度)的base32编码为:wx4g0ec1
解码算法与编码算法相反,先进行base32解码,然后分离出经纬度,最后根据二进制编码对经纬度范围进行细分即可,这里不再赘述。不过由于geohash表示的是区间,编码越长越精确,但不可能解码出完全一致的地址
步骤总结
1、把经度经过16轮的计算后得到编码为:
1011 1000 1100 0111 1001
2、纬度也一样计算得1101 0010 1100 0100 0100
3、将经纬度的编码进行合并,以经度开始得到10111 00011 00 011 11001 11010 01011 00010 00100
4、将得到编码 每5位为一个十进制数,有8个数。比如以11100的十进制数是28,所以对应的base32编码表示W。
5、然后就得到8个base32编码