Solr 是一个可扩展的,可快速部署的,对搜索海量文本中心的数据和对返回结果做相关性排序方面做了优化的企业级搜索引擎。
可扩展性:Solr可以把建立索引和查询处理的运算分布到一个集群内的多台服务器上。
快速部署:Solr是开源软件,安装和配置都很方便,可以根据安装包内的Sample配置直接上手。
优化的搜索功能:Solr搜索够快。对于复杂的搜索查询,Solr可以做到亚秒级的处理,通常几十毫秒就能处理完一次复杂查询
海量文本:Solr是针对百万级以上的海量文本处理而设计的,可以很好地处理海量数据。
文本中心的数据:Solr为搜索包含自然语言的文本内容做了优化,比如电子邮件,网页,简历,PDF文档,或是推特、微博、博客这些社交内容等等,都适合用Solr来处理。
结果是按相关性排序的:Solr的搜索返回结果是按照结果文档与用户查询之间的相关程度度做排序的,保证最相关的结果会优先返回。
Why do I need a search engine?
适合用类似Solr这样的搜索引擎来处理的数据的5种主要特点:
-
文本中心数据(text-centric data)
-
读取远多于写入的数据
-
面向文档的数据
-
灵活的Schema
- 海量数的据量,也就是”大数据“
文本中心数据
搜索引擎的设计初衷就是用来提取文本数据的隐含结构,并生成相关索引以提高查询检索的效率。“文本中心数据”这个词隐含表明了文档中的文本信息包含用户感兴趣的查询内容。当然,搜索引擎也支持非文本数据,比如数字类型的数据,但是其主要强项,还是在于处理基于自然语言的文本数据。
前面说的都是“文本”,其实“中心”这个部分也很重要,因为如果你的用户对于文本部分的内容不感兴趣,那么搜索引擎可能就不是处理你的问题的最佳选择。举个例子,对于一个给员工用来创建差旅支出报告的应用,每份报告都包括一些结构化的数据,比如日期,费用类型,汇率,数量等等,另外每项费用后面可能会包含一些备注信息,用于描述该项费用的大致情况。这样一个应用就是一个包含文本信息,但并不是“文本中心的数据”的一个例子,因为会计部门在使用这些员工的支出费用报告来生成月度支出报告时,并不会通过查找备注里的文本信息来做,文本在这里并不是其关心的主要内容。简单来说,就是不是所有包含文本信息的数据都适合搜索引擎来处理。
读取远多于写入的数据
首先,需要声明的是Solr是允许你更新索引中的现有文档内容的。你可以把“读取远多于写入”解读为对于文档的读取操作频率要远远高于创建文档和更新文档的频率。但是别狭隘的理解为你就完全不能写入数据了,或是你会被限制在一个特定频率之下更新数据。事实上Solr4的一个关键特性就是“近乎实时的查询”,这个功能可以允许你每秒钟为数千的文档建立索引并且几乎立刻就能查询到这些新加入的文档。
“读取远多于写入的数据”背后的关键点是你的数据在写入Solr后,在其生命周期内应该是要被重复读取很多次的。你可以理解为搜索引擎并不是主要用来存储数据的,而是主要用于查询存储的数据的(查询请求是一种读取操作)。
面向文档的数据
一个文档是由值域(field)组成的独立集合,每一个值域都只保存数据值,不能再嵌套包含其他值域。换句话说,在Solr这样的搜索引擎中,文档都是扁平结构的,文档之间不存在相互依赖关系。Solr中“扁平”的概念是比较宽松的,一个值域可以保存多个数据值,但是值域不能再嵌套包含子值域。也就是说你可以在一个值域里存储多个数据值,但是你不能往值域里头嵌套别的值域。
灵活的Schema
在关系型数据库中,表中的每一行数据都必须拥有相同的结构。而在Solr中,文档们可以有不同的值域。当然同一个索引中的文档们至少应该拥有一部分大家都有的值域以便于检索,但是并不要求所有文档中的值域结构完全一样。
海量数的据量,也就是”大数据“
常见的搜索引擎用例
1 基本的关键字查询
- 相关结果必须迅速返回,大多数情况下要求一秒钟之内就能够返回
- 用户的查询字串出现拼写错误时能够自动纠错
- 用户输入时通过自动补全建议来减少用户的输入负担,这在移动应用中很常见
- 处理查询字串中的同义词近义词
- 对包含查询字串的语言变异的文档进行匹配(译者注:语言变异是语义学术语,即用词不完全一样的近似表达)
- 短语处理,用户是希望匹配短语中所有的单词,还是只要匹配短语中的部分单词就行
- 对一些通用介词的处理,比如“a,” “an”, “of”, “the”等等
- 如果最靠前的查询结果用户不满意, 如何给用户返回更多的查询结果
2 排序的检索结果
对于搜索引擎来说,返回的结果文档是按照得分做降序排列的,该得分表示文档和查询的匹配程度。匹配程度得分依据一系列的因子来计算,不过一般说来得分越高,表明结果文档同查询之间的相关度越高。如果要人工干预排序的结果,你可以给特定的文档、值域、或者查询字串增加权重,或着直接提高某个文档的相关度分值。
3 除了关键词查询之外
在返回用户最初的查询所对应的文档结果的同时,提供给用户一个工具,使其能够不断地改进查询以获得更需要的信息。换句话说,在返回匹配的文档之外,你应该返回一个工具让用户知道下一步该怎么办。举个例子,你可以对查询结果按照属性进行分类,便于用户根据需求做进一步的浏览。这种功能称之为分类检索(Faceted-Search),这也是Solr的功能亮点之一。
4 搜索引擎不适合做的事…
对于一个查询结果有好几百万个文档的情况,如果你要求所有的匹配文档都要能够一次返回。那么你会等待很长的时间。查询本身会执行的很快,但是从索引结构中重建上百万的文档绝对是一件很耗时间的事情。因为Solr这样的搜索引擎在硬盘上存储值域的方式只适用于快速生成少量的文档结果,如果需要一次生成大量的查询结果,在这种存储方式之下生成大量文档结果就会耗费大量的时间。
另一个不适合应用搜索引擎的使用场景是需要读取索引文件的大部分子集的才能完成的深度分析任务场景。即使你通过结果分页技术避免了刚刚说的那个问题,如果一次分析需要读取索引文件中的大量数据,你也会遇到很大的性能问题,因为索引文件的底层数据结构就不是为一次大量读取来设计的。
搜索引擎技术并不适合用于在文档的相互关系之间进行查询。Solr确实是可以支持基于父子关系的查询,但是并不支持在复杂的关系型数据结构之间查询。
What is Solr?
2.1 信息检索引擎
信息检索(IR)是指从海量的数据集合(通常存储在计算机系统中)中,根据某种非结构化的本质属性(通常是文本内容)查找出满足信息需求的材料(通常是文档) 的过程。
Lucene底层用JAVA实现倒排索引的建立和管理。倒排索引即倒排表,是用于匹配文本查询的特殊数据结构。
2.2 灵活的Schema管理
虽然Lucene提供了建立文档索引和执行查询的核心架构, 但它并没有提供一个方便的接口来设置索引应该如何建立。要使用Lucene,你需要写一些JAVA代码来定义值域,还要定义如何分析这些值域。而Solr则提供了简单的声明方式来定义索引的结构,你也可以按照需求来指定如何分析索引中的值域。这一切都可以通过一个名叫schema.xml的XML配置文件来完成。Solr在其底层实现中将schema.xml中的配置翻译成Lucene的index。
此外Solr在核心的Lucene索引功能之上还添加了其他一些不错的功能。具体来说,Solr提供了Copy Fields和Dynamic Fields两种新的值域类型。Copy Fields提供了一种方法,可以将一个或多个值域中的原始文本内容赋值到另一个新的field值域中。Dynamic Fields则允许你无须在schema.xml里显式的声明,就可以将同一值域类型赋予多个不同的值域。
2.3 Java web应用
Solr作为一个Java web应用,既可以运行在任意一个现代JAVA Servlet引擎之上,比如Jetty或是Tomcat,也可以运行在JBoss或是Oracle AS之类的完整的J2EE应用服务器上。为了达到易于集成的目标,Solr的核心服务需要能够被不同的应用和编程语言访问。Solr提供简单的类REST服务,支持XML,JSON,HTTP等标准。顺便说一句,我们并不使用RESTFul一词来描述Solr基于HTTP的 API,因为它 并不严格遵守所有的REST(Representatonal state transfer)原则。针对许多流行的编程语言,Solr都提供了相应的库,包括Python,JAVA, .NET, 还有Ruby等等。
2.4 同一服务器上建立多份索引
Solr支持在单一的Solr 引擎上运行多个Solr 核心。每一个核心都有一个独立的索引和配置,在一个Solr实例中可以存在多个Solr 核心。这样你只需要一个Solr服务器就可以管理多个核心, 可以方便的实现服务器资源共享,以及及监控维护服务的共享。Solr有专门的API用于创建和管理多个Core。Solr多核心支持功能的一个应用是数据分区,比如用一个core来负责最近更新的文档,而用另外的core来处理之前生成的文档,这个功能被称为按时间顺序分片。
2.5 可扩展性(通过插件扩展功能)
Solr种最主要的三个子系统:文档管理,查询处理,和文本分析。当然,这些子系统是对Solr中复杂的子系统所做的宏观抽象,我们会在稍后的章节中一一研究这些子系统。这其中的每一个都是由一系列功能模块的流水线串成的,你可以在流水线中串入新的功能模块。这意味着如果你想给solr加入新的功能的话,根本不需要重写整个查询处理引擎,只需要在合适的位置串入自己的新功能模块即可。这样一来Solr的核心功能模块扩展和定制起来都很方便,可以完全按照你的特定应用需求进行定制。
2.6 可伸缩性
Solr实现可伸缩性的第一张牌是灵活的cache管理功能,该功能可以避免服务器重复进行耗费资源的操作。具体来说就是Solr预先设置了一些cache来节省开销很大的重复计算,比如Solr会缓存查询过滤器的计算结果。
缓存的作用是有限的,为了处理更多的文档和获得更高的查询吞吐能力,你需要能够通过扩展服务器来横向扩展系统的性能。
Solr扩展时最常见的两个方面:
第一个是查询的吞吐能力扩展, 增加replicas,如果需要得到更高的查询吞吐能力,你需要增加查询服务器和索引的拷贝数量,以便让更多的服务器来同时处理更多的请求。
另一个扩展维度是被索引的文档数, 增加shards,把索引文件切分成一个个被称为“分片”的小块,然后把查询请求分布到这些分片上进行操作。
2.7 容错性
给每一个shard增加replica,当某一个分片挂了,把所有请求都发到备份哪儿去。
Features overview
主要从一下三类介绍一下
- 用户体验
- 数据建模
- Solr 4的新功能
3.1 用户体验
Solr提供了一系列的重要功能来帮助你搭建一个易用的,符合用户直觉的,功能强大的搜索引擎。不过你需要注意的是Solr仅仅是提供了类REST风格的HTTP API接口,她并不提供搜索界面相关的UI组件和框架。
分页和排序功能
Solr 不会返回所有符合查询条件的结果。Solr在分页请求查询结果方面做了优化,每次只有最靠前的N个文档会被在请求第一页结果时返回。如果用户在第一页结果中没有找到想要的信息,那么可以通过很简单的API调用和请求参数获得后续页码的内容。分页功能对于两类关键的输出有帮助:1)结果返回的更快了,因为每次查询都只需要返回整个搜索结果中的一个很小的集合; 2)可以帮助你追踪到底有多少请求是针对更多页码内容的。这个指标可以反映出你的相关性得分的计算是否有问题。
分类检索功能
分类检索功能将搜索结果按照特性分类放到一个个小组中,这就为为用户提供了一个不断优化搜索关键字和浏览搜索结果的工具。其实就是导航功能。
自动补全功能
自动补全功能会根据系统索引文件中的文档内容在用户输入关键词的时候做出相应的自动填补建议。Solr的自动补全功能使得用户只需要输入少数几个字符就能得到一个根据这些输入字符推荐出来的查询词列表。这能大大降低用户输入错误查询词的几率,尤其是现在很多用户都会在移动设备上用小键盘输入搜索内容。
拼写检查功能
用户在输入带有拼写错误的查询词时,仍然会期待搜索引擎能够优雅的自动处理掉这些小错误,返回给用户正确的查询结果。Solr的拼写检查支持两种基本的模式:
自动纠错模式:Solr可以在用户出现拼写错误的时候自动根据该词语在索引中是否存在而做出相应的纠错处理
”您要找的是不是…“功能: Solr也可以根据用户的输入,为用户建议一个更佳的输入方案,比如当用户输入”hilands“时,solr会建议用户”您要找的是不是 highlands?“
高亮命中结果功能
在搜索文本量比较大的文档时,你可以通过Solr的高亮命中结果功能对命中的内容进行高亮显示。这在文本内容很长的文档中很实用,用户可以借此功能很方便的在长长的文本内容中一眼找到命中的搜索内容部分。
地理位置查询功能
地理位置搜索是Solr 4 中的一个很棒的功能,Solr 4 自建了对经度值和纬度值的索引支持, 可以对文档按照地理位置的远近做出排序。Solr 可以根据到地理位置上某一点(某一具体的经度和纬度上的一点)的距离,查找出相应的文档记录并对结果排序。 Solr 4中另一个激动人心的功能是你甚至可以通过在地图上画出各种几何图形,比如多边形,根据不同形状之间的交集来做地理位置查询。
3.2 数据建模类功能
值域的合并和分组功能
虽然Solr要求处理的文档尽量的扁平化、非规格化,但还是允许你将多个文档按照大家共有的某种属性进行归组管理。值域分组,也被称为值域的合并,允许你在返回结果时除了可以返回一个个的文档之外还可以返回一个特定的文档分组。
灵活的查询支持功能
Solr提供了一系列强大的查询功能,包括:
- 支持与(and), 或(or),非(not)的条件逻辑
- 支持通配符匹配
- 支持日期和数字的范围查询
- 支持模糊的短语查询支持模糊字串匹配
- 支持正则表达式匹配
- 支持功能查询
连接功能
但是在Solr中,join操作更像是SQL中的子查询,只是你并不会通过链接文档之间的数据而创建新的文档。例如,通过Solr的join功能, 你可以返回父文档符合查询条件的子文档。Solr连接功能在你需要拿到某条推特或是微博的所有评论时很有用,所有评论都是原文的子文档。
归集功能
文档归集功能允许可以根据每个文档的描述将相似的文档归为一组。这有助于避免在返回查询结果时返回很多内容很近似的文档结果。例如,如果你的搜索引擎是一个新闻应用,通过多个RSS链接来推送文章,那么你很可能会同时收到很多关于同一条新闻的报道。把这些内容差不多的报道都返回给用户显然不是一个好主意,此时你可以使用文档归集功能把这些类似的报导分成一组,选取一篇有代表性的报道返回给用户就妥了。
从PDF和word等格式的文档中导入富媒体数据的功能
在某些场合下,你可能需要处理一些已有的通用格式文档,比如PDF和微软word文档之类的,你需要这些文档也能被检索。用Solr的话要实现这一点很简单,因为Solr直接集成了Apache Tika项目,该项目几乎支持所有的流行文档格式。
从关系型数据库中导入数据的功能
如果你想要搜索的数据是存储在传统的关系型数据库当中的,那你可以配置Solr来通过SQL查询语句创建文档。
多种语言的支持
Solr和Lucene对多语言环境的支持已经发展了很长一段时间了。Solr内建了一个语言自动检测系统,对多种不同的语言环境都提供特定语言的文本分析方案支持。
3.3 Solr 4的新功能
几乎实时的搜索查询
Solr的近乎实时(NRT)查询功能支持应用在索引建立之后几秒钟就可以查询到新加入的文本。所以利用NRT功能,Solr完全可以应付内容更新会很快的场景,比如头条新闻或是社交网络之类的应用。
支持乐观并发机制的原子更新
原子更新功能允许客户端应用可以对现有文档的值域做添加、更新、删除或是增加等操作而并不用重新发送整个文档给Solr。
如果两个不同的客户端用户试图同时更新同一条文档记录时会怎么样。在这种情况下,Solr会使用乐观并发机制来避免会产生冲突的更新。简言之,Solr会用一个特定的叫做_Version_的值域来加强文档更新过程中的安全性。当两个不同用户试图同时更新同一文档时,最后提交更新的用户会得到过期版本的数据,所以其更新请求会失败。
实时获取功能
Solr也属于NoSQL技术的一种。Solr的实时获取功能绝对符合典型的NoSQL方式,它可以让你通过文档的唯一标识获得最新版本的文档内容,完全不需要考虑新版本的文档内容是否提交到了索引当中。而在Solr 4版本之前,文本内容必须先要提交到Lucene索引文件中之后才能够被访问到。而利用Solr4的实时获取功能,通过唯一标识获取文档内容的过程已经安全的同建立Lucene索引的过程分离开了。这在索引已经建立之后对文档内容进行更新的时候很有用,不用再重新提交文档内容建立新的索引了。
事务日志的持久层写入
当一个文档被发送到Solr进行索引的建立时,其内容会被写入到一个事务日志中,以避免因为server故障而产生数据的丢失。Solr的事务日志处于从客户端应用发送文档过来,到把文档内容提交到Lucene索引文件之间的一个中间状态。它也参与实时获取功能的实现,因为不管文档是否已经提交到了Lucene索引文件中,其内容都可以通过唯一标识提取出来。
事务日志使得Solr可以将更新内容的持久化和更新内容的可见性分离开来。这意味着文档可能会存在于持久化存储中但是在搜索结果中并不可见。你自己的应用可以灵活控制何时将新的文档内容提交到索引中从而使得新文档内容在搜索时可以被检索到。而你并不用担心如果服务器在你提交索引之前挂掉的话新文档内容会丢失的问题。
使用Zookeeper轻松的进行分片操作和复制操作
有了SolrCloud之后,横向扩展变得很简单而且自动化了。因为solr使用了Apache Zookeeper来同步配置和管理主分片及分片的复制备份。在Apache的官方网站上是这样描述Zookeeper的:”这是一个用于维护配置信息,命名,提供分布式同步和分组服务的中心服务“。
在Solr中,Zookeeper负责指定主分片和分片的复制备份,并且负责监控服务器是否可以正常的响应查询请求。SolrCloud已经绑定了Zookeeper服务,所以你不需要再做额外的配置就可以启动SolrCloud。