孔雀V–CtrlV百度文库集文件编号:20121223-02整理人:基于Sphinx构建准实时更新的分布式通用搜索引擎平台标签:搜索引擎、分布式、Sphinx、MySQL、并发前言:2008年7月,我写过一篇文章《基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计》。有不少网友希望阅读全文,我将该文档整理了一下,分享出来。文档解压后大小为7.33M,共19页。本站下载地址:新浪下载分流:上述文档架构存在的局限,我在2008年12月的文章《亿级数据的高并发通用搜索引擎架构设计》中已经指出:一是MySQL本身的并发能力有限,在200~300个并发连接下,查询和更新就比较慢了;二是由于MySQL表的主键与Sphinx索引的ID一一对应,从而无法跨多表建立整站查询,而且新增加类别还得修改配置文件,比较麻烦;三是因为和MySQL集成,无法发挥出Sphinx的优势。虽然如此,但对于一些写入量不大的搜索应用,已经足够了,或许对很多人会有帮助。正文:在这之后,本人基于《亿级数据的高并发通用搜索引擎架构设计》开发的Sphinx分布式通用站内搜索引擎平台,已经在生产环境运行9个月以上,经过运营中的不断完善与改进,目前已形成了一套可扩展的分布式通用站内搜索引擎框架。CMS、视频、论坛等产品发生的增、删、改操作,文本内容实时写入自行开发的HTTPSQS高性能简单消息队列服务,通过队列控制器更新索引和存储。提供支持XML、JSON的API查询接口,支持亿级数据的索引、分布式、中文分词、高亮显示、自动摘要、准实时(1分钟内)增量索引更新。孔雀V–CtrlV百度文库集文件编号:20121223-02整理人:下面是Sphinx新的搜索架构中技术关键点实现方式的一些介绍,与大家分享、交流一下:1、一元分词和中文分词的结合:①、一元分词位于索引更新模块。Sphinx索引引擎对于CJK(中日韩)语言(必须是UTF-8编码)支持一元切分,假设【反恐行动是国产主视角射击网络游戏】这段文字,Sphinx会将其切成【反恐行动是国产主视角射击网络游戏】,然后对每个字建立反向索引。如果用这句话中包含的字组成一个不存在的词语,例如【恐动】,也会被搜索到,所以搜索时,需要加引号,例如搜索【反恐行动】,就能完全匹配连在一起的四个字,不连续的【恐动】就不会被搜索到。但是,这样还有一个问题,搜索【反恐行动游戏】或【国产网络游戏】就会搜索不到。对于这个问题,采用位于搜索查询模块的中文分词来处理。sphinx.conf配置文件中关于UTF-8中文一元分词的配置如下:...省略...indext_source_main{source=t_source_main孔雀V–CtrlV百度文库集文件编号:20121223-02整理人:=/data0/search/sphinx/data/t_source_maindocinfo=externmlock=0morphology=nonemin_word_len=1charset_type=utf-8min_prefix_len=0html_strip=1charset_table=0..9,A..Z-a..z,_,a..z,U+410..U+42F-U+430..U+44F,U+430..U+44Fngram_len=1ngram_chars=U+3000..U+2FA1F}...省略...②、中文分词位于搜索查询模块。搜索“反恐行动游戏”、“国产网络游戏”,先调用独立的中文分词系统,分别切分为“反恐行动游戏”、“国产网络游戏”,这时候,再给以空格分隔的词语加上引号,去Sphinx搜索【反恐行动游戏】或【国产网络游戏】,就能搜索到这条记录了。中文分词词库发生增、删、改,无需重建整个Sphinx搜索索引。2、使用自行开发的HTTPSQS()开源简单队列服务程序,来缓冲高并发数据写入新闻、论坛帖子、客服公告、SNS社区等发生的增、删、改操作,文本内容通过更新接口实时写入HTTPSQS队列,再通过队列控制器更新到Sphinx搜索引擎索引中。3、Sphinx不能严格按照字段排序的小问题如果不想使用权重,只希望严格按照时间、主键等排序,而匹配模式(Matchingmodes)又为非SPH_MATCH_BOOLEAN时(比较常用的是SPH_MATCH_ALL、SPH_MATCH_EXTENDED),Sphinx搜索结果在某一页中的排序会不太准确。例如:按照UNIX时间戳倒序排序,0,20为第一页,20,40为第二页,第一页的最小时间戳一定会大于第二页的最大时间戳,但是,第一页中的0,20条记录却不会严格按照时间戳排序,第二页亦是如此。因此,如果需要精确排序,用户翻到搜索结果的某一页,就需要对Sphinx在某一搜索孔雀V–CtrlV百度文库集文件编号:20121223-02整理人:结果页中的记录另行再排序,在我的这套搜索架构中,这一再排序操作由search.php查询接口使用array_multisort()函数处理。一般情况下,一页只会显示5~30条记录,因此,只对几十条记录采用PHP再排序,速度也是非常快的。4、队列控制器中“时间控制”与“数量控制”相结合,实现搜索索引的1分钟内准实时更新:①、Sphinx0.9.9生产环境的建索引速度大约在5.5Mbytes/秒、6400文档/秒。队列控制器可以设置10秒钟更新一次增量索引,只要Sphinx增量索引数据源的文档数在38万以内,就能保证增量索引在1~60秒内得到更新,这是从“时间”上进行控制。②、为了避免增量索引数据源的文档数增长到38万,队列控制器在增量索引数据源的文档数超过1万时,还将激活增量索引合并入主索引的操作,合并完成的文档将从增量索引数据源中删除,这是从“数量”上进行控制。5、自行编写的“搜索引擎查询API接口”调用说明:=%E9%87%91%E5%B1%B1(搜索关键字。程序能够识别关键字是GBK编码还是UTF-8编码,能够识别关键字是否进行了URL编码)&output=xml(输出类型支持:xml或json)&excerpts=1(是否开启高亮显示与文本摘要,1开启或0关闭)&excerpts_before=fontcolor=red(高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字前面插入的字符串。)&excerpts_after=/font(高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字之后插入的字符串。)&excerpts_limit=256(高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。摘要最多包含的符号(码点)数。)&excerpts_field=c1,c2,c3,c4,c5(仅对指定的字段进行高亮显示,其余字段不进行高亮显示,如果此参数为空,则默认所有的字符型字段都进行高亮显示)&offset=0&limit=20(相当于SQL语句中的limit0,20)&max_matches=30000(最大搜索结果集数量)&match_mode=SPH_MATCH_EXTENDED2&ranking_mode=SPH_RANK_PROXIMITY_BM25&sort_mode=SPH_SORT_EXTENDED&sort_by=@relevanceDESC,u1ASC,@idDESC(排序模式:@relevance和@id是内置变量,@relevance代表相关度权值,@id等于search_id,u1为字段名)孔雀V–CtrlV百度文库集文件编号:20121223-02整理人:=c1,7;c2,1(权重设置:字段c1的权重为7,字段c2的权重为1)&filter=u1:0_1_6,false;u2:4,true(整数值过滤器:匹配字段u1等于0、1或6,并且字段u2不等于4的结果集。false表示等于,true表示不等于)&filter_range=u1:0,100,false;u2:50,90,true(整数范围过滤器:字段u1=0并且u1=100,字段u250并且u290)&filter_range=u1:1.23,99.645,false;u2:1034.3,7834.56,true(浮点数范围过滤器:字段u1=1.23并且u1=99.645,字段u21034.3并且u27834.56)6、搜索结果前台页面示例:7、同一套服务器平台与API接口,通用于各类产品:示例:金山游戏文章与视频搜索:=%E5%89%91%E7%BD%913孔雀V–CtrlV百度文库集文件编号:20121223-02整理人:金山游戏论坛帖子搜索:=%E4%B8%83%E7%A7%80&select=title