全文检索工具包Lucene以及企业及应用Solr的学习(一)
初见Lucene
关于Lucene,百度百科是这样描述的:
Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。
大概在2009年,在大学里第一次接触到Lucene。当时对于可以利用Lucene来实现简陋的全文信息检索,模仿百度页面实现功能,我可是感到非常有成就感的。在室友面前,打开一个自己写的页面,在输入框输入关键字,然后列出一堆结果,并做了关键字高亮(当时我记得是正则替换实现的),当时还是挺有威风的感觉的。
当然,那个时候对于Lucene仅仅会写一个demo,对于原理、底层结构、算法等等一无所知,更不用说自己去扩展。
了解Lucene
虽然最终我的毕设没有用到lucene相关技术,但是第一份工作的后半期,参与并负责了一个以lucene为核心技术的电子商务搜索引擎项目。那个时候多少了解了全文检索的一些粗枝大叶。
索引阶段:
将不同来源的非结构、半结构化、结构化数据整合一起
通过分词器,分析文本,生成一个具有实体意义的小单元Term
将一系列Term进行形式变化、字典序排列
遍历文档,通过Term生成对于的倒排链表,记录Term的次数、位置等
查询阶段:
分析关键字,分词,生成Term树
生成Query数据
查询Term倒排链表
链表的合并:交集、并集、差集等等
结合权重树、文档权重、域权重,通过空间向量模型,进行一个文档打分排序
在这个项目中,我学到了非常多的东西,特别是关于电商搜索引擎区别于常规全文检索的地方。这个时候通过多服务器发布独立任务的方式,来进行负载均衡和单点故障容灾,但是服务器之间并没有直接的数据同步,而是通过定时任务各自独立数据更新,缺点非常明显。
电商搜索引擎最常用的功能就是属性的分类统计,现在已经不记得,当初在不知道Lucene有facet的情况下,如何实现这个功能的。
接触Solr、深入Lucene
后来我从乙方顺利转入甲方工作,继续参与这个商城搜索引擎项目。那个时候,我遇到了工作以来对我帮助最大的人,他叫朱炜。他带我接触了一个企业级搜索引擎的新天地——Solr。
Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引;也可以通过Http Get操作提出查找请求,并得到XML格式的返回结果。
Solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。
当时我觉得自己见识太少太少了,原来有这么一个优秀的框架。Solr具有简单易用且丰富的管理后台、封装了主从同步、封装了负载均衡、简化了Facet功能、Group、SolrFunction、扩展了查询方式dismax、edismax,通过简单的xml配置,即可实现丰富的功能扩展。
同时也接触了MongoDB、MongoDB的MapReduce功能、Memcached、Redis的一些互联网开发常用的技术。总之在那一段时间内,我学到了很多,也成长了很多。
后来他离职了,我只能独立负责这个基于Solr的电商搜索引擎系统,随着系统的上线,需求的增加,后来陆续遇到了许多挑战(对于当时的我,确实算大挑战了)。比如,
关键字的自动补全:基于汉字、拼音、声母的协同实现,为了支持对连续拼音的分割,不得不又去实现了拼音的识别、分割(将sousuoyinqing,分割成sou suo yin qing)以及平翘舌音的兼容
关键字的联想推荐:通过分析关键字中包含的一些属性信息,进行信息偏移推荐。当时我们是服装行业的电商搜索,因此我先实现了词库分类,定义若干个词库:人群属性词库(裙子、吊带、男装、女式等),季节属性词库(羽绒服、棉衣、冬季、短袖等),服装类别属性词库(衬衫、鞋、裤等)。然后通过简易的多词库分词器,来识别其中的关键字,最后通过各类词库分词的权重,进行不同权重的分词搜索,将与目标关键字相近而不同的热门关键字推荐给用户。
关键字的打散重组:对于包含信息比较多的关键字,当搜索引擎无法返回结果的时候,会对原始关键字进行打散、重组,依据各个分词的权重不同,生成若干个新词,重新进行检索,返回。
关键字的纠错推荐:通过N-Gram算法结合文本编辑距离(Levenshtein)算法和拼音分析纠错算法,对于用户手误的一些关键字进行纠错。
属性筛选器的统计、层级筛选器的统计:主要是对于某些属性统计需要查询条件的固定和查询条件的排除。
这段时间,我也试着去了解了下Lucene的一些底层原理,阅读了觉先的《Lucene 原理与代码分析》一文,也算是对Lucene有了一个入门。结合两次电商搜索引擎的开发、维护,个人也是受益匪浅。
了解Solr
随着工作的深入,接触的技术越来越多,我负责的电商搜索引擎项目迎来了又一次的重大重构——平台化搜索引擎开发。
趁着这次改版,我修复了上一版中一大隐患:
先前业务服务器有多台,为了避免定时任务不冲突,每次发布都修改定时任务配置文件,只让某一台的服务器可以执行定时任务。如此一来,每次发布都需要修改配置文件,增加了出错的概率,而且无法避免单点故障,如果主服务器宕机,更新任务将会停止。新版本有两个选择,一个是通过统一调度平台来进行任务调度,另一个是我自己实现多服务器定时任务的分布式锁。由于当时任务调度平台承载着大量的订单和统计任务,服务器压力比较大,加上我也想趁此学习下zookeeper相关,所以我选择了方案二。通过Zookeeper来实现多服务器之间的分布式锁。如此既可以做到一包多服务器发布,也避免了单点故障,同时减少了系统之间的依赖。
通过增加数据版本号,实现全量更新数据时的数据短暂缺失问题。
Solr相关的搜索引擎开发回忆先到这,后面有想起来再做更新!
后续将记录一些个人在5年互联网、电子商务搜索引擎领域的心得,遇到的问题的解决方案和思路,以及一部分关于推荐引擎的心得:
深入Lucene搜索引擎,链表的学习和扩展
结合工作中遇到的问题,学习edismax,扩展Java端的SolrFunction支持
Solr Facet的相关功能展示