第一章 Solr 简介
本章速览:
·搜索引擎处理的数据特性
·常见搜索引擎用例
·Solr核心模块介绍
·选择Solr的理由
·功能概述
伴随着社交媒体、云计算、移动互联网和大数据等技术的高速发展,我们正迎来一个令人激动的计算时代。软件架构师们开始面对的主要挑战之一,便是如何处理全球巨大的用户基数所产生及使用的海量数据。此外,用户们开始期待在线软件应用永远都是稳定可用的,并且能够一直保持响应,这对应用就提出了更高的可扩展性和稳定性需求。为了满足这些需求,一些专用的非关系型数据存储及处理技术,统称为NoSQL(Not
Only SQL)技术,开始获得越来越多的青睐。这些系统并不强制要求将所有的数据都存储在曾经成为事实上标准的关系型数据模型当中,而是共用了一个通用的设计模式,在数据存储处理引擎和特定的数据类型之间进行匹配。换句话说,NoSQL技术为处理特定数据类型的特定类别问题做了性能优化。由于对可扩展性的需求和性能的需求不断增加,导致各种NoSQL技术和传统关系型数据库开始混合使用,这种跨界架构变得越来越流行。过去那种一种数据处理方案就能吃遍天下的时代已经一去不复返了。
本书主要讨论一种特殊的NoSQL技术,即Apache Solr。和她的其他非关系型兄弟们一样,Solr也为一类特定问题的处理做了优化。具体来说,Solr 是一个可扩展的,可快速部署的,对搜索海量文本中心的数据和对返回结果做相关性排序方面做了优化的企业级搜索引擎。
这句话读上去有点拗口,不过没关系,我们把这个定义中的亮点分解出来看:
·可扩展性:Solr可以把建立索引和查询处理的运算分布到一个集群内的多台服务器上。
·快速部署:Solr是开源软件,安装和配置都很方便,可以根据安装包内的Sample配置直接上手。
·优化的搜索功能:Solr搜索够快。对于复杂的搜索查询,Solr可以做到亚秒级的处理,通常几十毫秒就能处理完一次复杂查询
·海量文本:Solr是针对百万级以上的海量文本处理而设计的,可以很好地处理海量数据。
·文本中心的数据:Solr为搜索包含自然语言的文本内容做了优化,比如电子邮件,网页,简历,PDF文档,或是推特、微博、博客这些社交内容等等,都适合用Solr来处理。
·结果是按相关性排序的:Solr的搜索返回结果是按照结果文档与用户查询之间的相关程度度做排序的,保证最相关的结果会优先返回。
在本书中,你将学到如何使用Solr来设计实现一个可扩展的搜索方案。我们的学习旅程从了解Solr支持的数据类型和典型用例开始。这样你能更好的理解在整个现代软件应用架构全景图中Solr所处的位置,以及Solr到底是设计来处理哪些问题的。
1.1我到底需要一个搜索引擎吗?
我们猜测你已经有了些想法要准备使用搜索引擎了,否则你也不会翻开这本书。因此,我们就不浪费时间来揣度你到底是为什么开始考虑用Solr的了,我们直接来讨论点干货,看看关于你的数据和用例方面, 有哪些问题是你在决定是否使用搜索引擎之前所必须要回答的。这最终会归结为如何深刻理解你的数据和你的用户,以选用一个合适的技术来同时满足二者的需求。我们先从讨论一下哪些数据属性是搜索引擎适合处理的。
-
1.1.1 管理文本中心的数据
合理选用同数据匹配的存储及处理引擎,是现代软件应用架构的标志性要求之一。如果你是一个优秀的程序员,那么你应该知道要根据在算法中使用数据的方式来选取最合适的数据结构。比如,如果你需要实现快速随机查找,你就不会使用链表结构来存储数据。同样的道理也适用于搜索引擎的选取。这里列出了适合用类似Solr这样的搜索引擎来处理的数据的4种主要特点:
-
文本中心的数据
-
读取远多于写入的数据
-
面向文档的数据
-
灵活的Schema
也许在这儿应该加上第五个数据特性,即:海量数的据量,也就是”大数据“,但是我们主要关注的是Solr区别于其他NoSQL技术的主要特性,而可以处理海量的数据并不是它们的主要区别之一。
虽然这里列出了类似Solr这样的搜索引擎可以有效处理的数据类型的4个主要特点,但是这只是一个粗略的准则,并不是一个严格的标准。我们来深入的讨论一下这些数据特性,看看为什么它们对于搜索来说这么重要。我们现在只关注概念,具体的实现细节在稍后的章节讨论。
文本中心的数据
你肯定见过有人用“非结构化数据“这个术语来描述搜索引擎处理的数据。我们认为“非结构化”这个词有些模糊不清,因为任何一个基于人类语言产生的文档都是隐含有一定的结构的。要理解“非结构化”这个术语你可以认为这是从计算机的角度来看的。在计算机眼中,文本文档就是一个字符流。这个字符流必须通过特定的语言规则解析出语义结构,才能被检索到。而这正是搜索引擎的工作所在。
我们认为“文本中心的数据”这个词更适合用来描述Solr处理的数据类型。因为搜索引擎的设计初衷就是用来提取文本数据的隐含结构,并生成相关索引以提高查询检索的效率。“文本中心的数据”这个词隐含表明了文档中的文本信息包含用户感兴趣的查询内容。当然,搜索引擎也支持非文本数据,比如数字类型的数据,但是其主要强项,还是在于处理基于自然语言的文本数据。
前面说的都是“文本”,其实“中心”这个部分也很重要,因为如果你的用户对于文本部分的内容不感兴趣,那么搜索引擎可能就不是处理你的问题的最佳选择。举个例子,对于一个给员工用来创建差旅支出报告的应用,每份报告都包括一些结构化的数据,比如日期,费用类型,汇率,数量等等,另外每项费用后面可能会包含一些备注信息,用于描述该项费用的大致情况。这样一个应用就是一个包含文本信息,但并不是“文本中心的数据”的一个例子,因为会计部门在使用这些员工的支出费用报告来生成月度支出报告时,并不会通过查找备注里的文本信息来做,文本在这里并不是其关心的主要内容。简单来说,就是不是所有包含文本信息的数据都适合搜索引擎来处理。
所以现在先花几分钟好好想想你的数据是否是“文本中心的数据”。考虑的重点主要就是数据中的文本信息用户是不是会拿来做检索。如果答案是YES,那么搜索引擎很可能是一个好的方案选择。我们在第5章和第6章会讨论如何利用Solr的文本分析来提取文本数据的结构的细节。
读取远多于写入的数据:
另外一个搜索引擎可以高效处理的数据特性是“读取远多于写入的数据”。首先,需要声明的是Solr是允许你更新索引中的现有文档内容的。你可以把“读取远多于写入”解读为对于文档的读取操作频率要远远高于创建文档和更新文档的频率。但是别狭隘的理解为你就完全不能写入数据了,或是你会被限制在一个特定频率之下更新数据。事实上Solr4的一个关键特性就是“近乎实时的查询”,这个功能可以允许你每秒钟为数千的文档建立索引并且几乎立刻就能查询到这些新加入的文档。
“读取远多于写入的数据”背后的关键点是你的数据在写入Solr后,在其生命周期内应该是要被重复读取很多次的。你可以理解为搜索引擎并不是主要用来存储数据的,而是主要用于查询存储的数据的(查询请求是一种读取操作)。所以如果你需要很频繁的更新数据,那么搜索引擎可能不太适合你的需求,其他的NoSQL技术,比如Cassandra,可能更适合你的快速随机写入的需求。
面向文档的数据
到目前为止,我们一直使用更通用的“数据”这一术语,但是实际中搜索引擎处理的都是文档数据。在搜索引擎中,一个文档是由值域(field)组成的独立集合,每一个值域都只保存数据值,不能再嵌套包含其他值域。换句话说,在Solr这样的搜索引擎中,文档都是扁平结构的,文档之间不存在相互依赖关系。Solr中“扁平”的概念是比较宽松的,一个值域可以保存多个数据值,但是值域不能再嵌套包含子值域。也就是说你可以在一个值域里存储多个数据值,但是你不能往值域里头嵌套别的值域。
Solr中这种扁平化的、面向文档的方式可以很好的处理已经文档化的数据,比如网页,博客,pdf文档等等。那么如果要用solr来处理关系型数据库中已经结构化好的数据应该怎么办呢?这种情况下你需要先把关系型数据库中跨表存储的数据取出来,去结构化,然后放到扁平化的自包含文档结构里。我们会在第三章学习怎么处理这样的问题。
你还需要考虑你的文档数据中的哪些值域需要存储在Solr中,哪些值域需要存储在其他系统中(比如数据库中)。简单来说,搜索引擎只存储需要被检索到的数据,以及用于显示检索结果的数据。举个例子,如果你有一个在线视频的搜索索引,你应该不会希望把视频文件本身存储在Solr中,合理的方案应该是把大的视频文件都放在内容分发网络(CDN)中。通常你只需要在搜索引擎中存储满足搜索需求的最少数据即可。刚才这个在线视频的例子清楚的说明了不要把Solr当成通用数据存储技术,Solr的工作是找到用户感兴趣的视频文件,而不是存储视频文件本身。
灵活的Schema
最后一个搜索引擎数据的主要特性是有灵活的schema。这意味着查询索引中的文档不需要拥有统一的结构。在关系型数据库中,表中的每一行数据都必须拥有相同的结构。而在Solr中,文档们可以有不同的值域。当然同一个索引中的文档们至少应该拥有一部分大家都有的值域以便于检索,但是并不要求所有文档中的值域结构完全一样。
举个例子,假如要做一个用于查找出租和出售房源的搜索应用。显然每条房源文档都会有地段,房间数,卫生间数等一些共有的值域,但是根据类型是出租还是出售的不同,不同的房源文档会有不同的值域。一条出售的房源会有售价值域,财产税值域,而一条出租的房源文档则会有月租金和宠物政策等等不同的值域。
总结一下,Solr这样的搜索引擎是专门优化用于处理文本中心的,读取远多于写入的,面向文档的,拥有灵活Schema的数据用的。Solr并不是一种通用数据存储处理技术,这也是区别于其他NoSQL技术的主要因素。
有众多不同的数据存储和处理方案可供选择的好处是你不再需要费劲脑汁地寻找一种可以满足所有需求的通用技术方案。搜索引擎在某些特定任务上表现出色,但是在其他一些方面性能很差。这意味着在大多数情况下,你可以用Solr来作为关系型数据库和其他NoSQL技术的有力补充,而并不是要取代后者。
既然我们已经谈到了Solr所针对优化处理的数据类型,那我们就接着来讨论一下像solr这样的搜索引擎主要是设计来解决哪些实际用例的。理解这些用例可以帮助你理解搜索引擎技术是如何区别于其他数据处理技术的。
-
1.1.2 常见的搜索引擎用例
在这一节中,我们来看看Solr这样的搜索引擎都能干些什么。正如我们在1.1.1节中所提到的那样,这些讨论只是一种指南性质的建议,不要把它们当成严格的使用规则来看。在我们开始之前,你需要意识到想做出一个优秀的搜索服务,其门槛是很高的。现在的用户都习惯于使用像Google和Bing这样又快又高效的网络搜索引擎,而很多受欢迎的网站也有自己强大的搜索方案来帮助用户快速的获取想要的信息, 所以用户对搜索服务并不陌生并且会非常的挑剔。当你在评估像Solr这样的搜索引擎时,或是在设计你自己的搜索方案时,一定要有根弦儿,要把用户体验放在高优先级上来考虑。
基本的关键字查询
很明显,作为一个搜索引擎来说, 首先必须要能够支持基本的关键词查询。这也是搜索引擎的主要功能之一。不过关键词查询功能还是值得在这里强调一下的,因为这是用户使用搜索引擎最典型的方式。很少有用户想要会一上来就填写一个很完整的复杂搜索表单来进行搜索的。考虑到关键词搜索功能将会是用户和你的搜索引擎之间最常见的交互方式,这个基本功能必须能够提供给用户以非常好的用户体验才行。
一般来说,用户希望只输入几个简单的关键词就能获取到很好的搜索结果。这也许听上去像是一个简单的匹配任务:把查询字串和文档进行匹配即可。不过请考虑一下要实现良好的用户体验所必须解决的几个问题:
· 相关结果必须迅速返回,大多数情况下要求一秒钟之内就能够返回
· 用户的查询字串出现拼写错误时能够自动纠错
· 用户输入时通过自动补全建议来减少用户的输入负担,这在移动应用中很常见
· 处理查询字串中的同义词近义词
· 对包含查询字串的语言变异的文档进行匹配(译者注:语言变异是语义学术语,即用词不完全一样的近似表达)
· 短语处理,用户是希望匹配短语中所有的单词,还是只要匹配短语中的部分单词就行
· 对一些通用介词的处理,比如“a,” “an”, “of”, “the”等等
· 如果最靠前的查询结果用户不满意, 如何给用户返回更多的查询结果
就像你看到的那样,不使用特定的处理方法的话,这样一堆问题会使得看上去如此简单的功能实现起来变得很困难。然而利用像Solr这样的搜索引擎,这些功能就能立等可取,实现起来变得很简单。当你给用户提供了一个强大的关键词搜索工具之后,接下来你就需要考虑如何去展示查询的结果,这就引出了下一个用例,按照结果同查询请求之间的相关性顺序,对搜索返回的查询结果进行排序。
排序的检索结果
搜索引擎为查询返回“最靠前“的结果。在SQL查询关系型数据库的时候,某一行数据记录要么匹配查询被返回,要么不匹配查询被忽略,查询结果也是按照数据记录的某一列属性来排序的。而对于搜索引擎来说,返回的结果文档是按照得分做降序排列的,该得分表示文档和查询的匹配程度。匹配程度得分依据一系列的因子来计算,不过一般说来得分越高,表明结果文档同查询之间的相关度越高。
有好几个因素决定了将结果文档按照相关度排序的方式很重要。首先,现代搜索引擎一般都存储着海量的文档,都是上百万甚至数十亿记的。如果不对查询结果进行相关度排序,那用户就会被海量的返回结果所淹没,无法清晰有效的浏览搜索的结果。其次,用户使用其他搜索引擎的经验使得用户已经习惯于使用少数的几个关键词就能获得不错的查询结果,也使得用户普遍比较缺乏耐心。他们会期待搜索引擎按照他们想要的意思来工作,而不管其所输入的信息是否完全正确。比如对于移动应用的后台搜索服务来说,用户会期待在输入了简短的几个可能还包含有拼写错误的查询词之后,搜索服务就能够返回正确的搜索结果。
如果要人工干预排序的结果,你可以给特定的文档、值域、或者查询字串增加权重,或着直接提高某个文档的相关度分值。比如你如果希望把新加入的文档推送到最靠前的位置,就可以通过按照创建时间来提高文档排序的方式实现。我们在第三章中会学习关于文档排序的知识。
除了关键词查询之外
利用像Solr这样的搜索引擎,用户可以输入少数几个关键词就能获取到一些搜索结果。然而对于很多用户来说这仅仅是一个查询交互的第一步。他们需要在查询结果中能够继续地浏览。驱动一个信息发现的交互会话过程也是搜素引擎的一个主要应用场景。通常用户在搜索前并不是很精确的知道想要查询的信息什么样的,他们事先也不知道你的系统中到底存储了哪些信息。一个好的搜索引擎可以帮助用户不断地细化信息需求,一步步到达最需要的信息。
这里的核心思想是在返回用户最初的查询所对应的文档结果的同时,提供给用户一个工具,使其能够不断地改进查询以获得更需要的信息。换句话说,在返回匹配的文档之外,你应该返回一个工具让用户知道下一步该怎么办。举个例子,你可以对查询结果按照属性进行分类,便于用户根据需求做进一步的浏览。这种功能称之为分类检索(Faceted-Search),这也是Solr的功能亮点之一。我们会在1.2节中看到一个关于房地产的分类检索实例,在第八章中会详细介绍分类检索功能的细节。
搜索引擎不适合做的事…
最后,我们来讨论一下不适合应用搜索引擎的一些用例场景。首先,搜索引擎一般的设计是,为每个查询返回一个小的文档集,通常包含10个到100个的结果文档。更多的结果文档可以通过Solr自带的结果分页功能来获取。对于一个查询结果有好几百万个文档的情况,如果你要求所有的匹配文档都要能够一次返回,那么你会等待很长的时间。查询本身会执行的很快,但是从索引结构中重建上百万的文档绝对是一件很耗时间的事情。因为Solr这样的搜索引擎在硬盘上存储值域的方式只适用于快速生成少量的文档结果,如果需要一次生成大量的查询结果,在这种存储方式之下生成大量文档结果就会耗费大量的时间。
另一个不适合应用搜索引擎的使用场景是需要读取索引文件的大部分子集的才能完成的深度分析任务场景。即使你通过结果分页技术避免了刚刚说的那个问题,如果一次分析需要读取索引文件中的大量数据,你也会遇到很大的性能问题,因为索引文件的底层数据结构就不是为一次大量读取来设计的。
我们前面有提到过一点,但是在这里还是要再次强调一下,那就是搜索引擎技术并不适合用于在文档的相互关系之间进行查询。Solr确实是可以支持基于父子关系的查询,但是并不支持在复杂的关系型数据结构之间查询。在第三章,你会学习到如何将关系型数据结构适配到适合solr处理的扁平型文档结构中进行查询。
最后,绝大多数搜索引擎都没有直接的文档级安全支持,至少Solr是没有。如果你需要严格管理文档的权限,那你只能在搜索引擎之外来想办法。
到这里我们已经了解了适合搜索引擎处理的用例场景和数据类型,下一步该是时候讨论Solr到底能做些什么,以及这些功能是如何实现的了。在下一节中,你将学习到Solr到底有哪些主要功能,以及她是如何实现外部系统集成、可扩展性、以及高可用性等软件设计原则的。