[文章作者:张宴 本文版本:v1.0 最后修改:2010.02.05 转载请注明原文链接:http://blog.zyan.cc/sphinx_search/]

  前言:

  2008年7月,我写过一篇文章《基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计》。有不少网友希望阅读全文,我将该文档整理了一下,分享出来。文档解压后大小为7.33M,共19页。

  本站下载地址: http://blog.zyan.cc/book/sphinx/sphinx_mysql.zip

  新浪下载分流: http://ishare.iask.sina.com.cn/f/6728201.html

  上述文档架构存在的局限,我在2008年12月的文章《亿级数据的高并发通用搜索引擎架构设计》中已经指出:一是MySQL本身的并发能力有限,在200~300个并发连接下,查询和更新就比较慢了;二是由于MySQL表的主键与Sphinx索引的ID一一对应,从而无法跨多表建立整站查询,而且新增加类别还得修改配置文件,比较麻烦;三是因为和MySQL集成,无法发挥出Sphinx的优势。虽然如此,但对于一些写入量不大的搜索应用,已经足够了,或许对很多人会有帮助。



  正文:

  在这之后,本人基于《亿级数据的高并发通用搜索引擎架构设计》开发的Sphinx分布式通用站内搜索引擎平台,已经在生产环境运行9个月以上,经过运营中的不断完善与改进,目前已形成了一套可扩展的分布式通用站内搜索引擎框架。CMS、视频、论坛等产品发生的增、删、改操作,文本内容实时写入自行开发的 HTTPSQS 高性能简单消息队列服务,通过队列控制器更新索引和存储。提供支持XML、JSON的API查询接口,支持亿级数据的索引、分布式、中文分词、高亮显示、自动摘要、准实时(1分钟内)增量索引更新。

  点击在新窗口中浏览此图片

  下面是Sphinx新的搜索架构中技术关键点实现方式的一些介绍,与大家分享、交流一下:

  1、一元分词和中文分词的结合:

  ①、一元分词位于索引更新模块。Sphinx索引引擎对于CJK(中日韩)语言(必须是UTF-8编码)支持一元切分,假设【反恐行动是国产主视角射击网络游戏】这段文字,Sphinx会将其切成【反 恐 行 动 是 国 产 主 视 角 射 击 网 络 游 戏】,然后对每个字建立反向索引。如果用这句话中包含的字组成一个不存在的词语,例如【恐动】,也会被搜索到,所以搜索时,需要加引号,例如搜索【"反恐行动"】,就能完全匹配连在一起的四个字,不连续的【"恐动"】就不会被搜索到。但是,这样还有一个问题,搜索【"反恐行动游戏"】或【"国产网络游戏"】就会搜索不到。对于这个问题,采用位于搜索查询模块的中文分词来处理。

  sphinx.conf配置文件中关于UTF-8中文一元分词的配置如下:
...省略...
index t_source_main
{
        source                  = t_source_main
        path                    = /data0/search/sphinx/data/t_source_main
        docinfo                 = extern
        mlock                   = 0
        morphology              = none
        min_word_len            = 1
        charset_type            = utf-8
        min_prefix_len          = 0
        html_strip              = 1
        charset_table           = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
        ngram_len               = 1
        ngram_chars             = U+3000..U+2FA1F
}
...省略...


  ②、中文分词位于搜索查询模块。搜索“反恐行动游戏”、“国产网络游戏”,先调用独立的中文分词系统,分别切分为“反恐行动 游戏”、“国产 网络游戏”,这时候,再给以空格分隔的词语加上引号,去Sphinx搜索【"反恐行动" "游戏"】或【"国产" "网络游戏"】,就能搜索到这条记录了。中文分词词库发生增、删、改,无需重建整个Sphinx搜索索引。



  2、使用自行开发的HTTPSQS(http://code.google.com/p/httpsqs)开源简单队列服务程序,来缓冲高并发数据写入

  新闻、论坛帖子、客服公告、SNS社区等发生的增、删、改操作,文本内容通过更新接口实时写入HTTPSQS队列,再通过队列控制器更新到Sphinx搜索引擎索引中。



  3、Sphinx不能严格按照字段排序的小问题

  如果不想使用权重,只希望严格按照时间、主键等排序,而匹配模式(Matching modes)又为非SPH_MATCH_BOOLEAN时(比较常用的是SPH_MATCH_ALL、SPH_MATCH_EXTENDED),Sphinx搜索结果在某一页中的排序会不太准确。例如:按照UNIX时间戳倒序排序,0,20为第一页,20,40为第二页,第一页的最小时间戳一定会大于第二页的最大时间戳,但是,第一页中的0,20条记录却不会严格按照时间戳排序,第二页亦是如此。因此,如果需要精确排序,用户翻到搜索结果的某一页,就需要对Sphinx在某一搜索结果页中的记录另行再排序,在我的这套搜索架构中,这一再排序操作由search.php查询接口使用array_multisort()函数处理。一般情况下,一页只会显示5~30条记录,因此,只对几十条记录采用PHP再排序,速度也是非常快的。



  4、队列控制器中“时间控制”与“数量控制”相结合,实现搜索索引的1分钟内准实时更新:

  ①、Sphinx 0.9.9生产环境的建索引速度大约在5.5 Mbytes/秒、6400文档/秒。队列控制器可以设置10秒钟更新一次增量索引,只要Sphinx增量索引数据源的文档数在38万以内,就能保证增量索引在1~60秒内得到更新,这是从“时间”上进行控制。

  ②、为了避免增量索引数据源的文档数增长到38万,队列控制器在增量索引数据源的文档数超过1万时,还将激活增量索引合并入主索引的操作,合并完成的文档将从增量索引数据源中删除,这是从“数量”上进行控制。



  5、自行编写的“搜索引擎查询API接口”调用说明:
http://xxx.xxx.xxx.xxx/search.php?query=%E9%87%91%E5%B1%B1  (搜索关键字。程序能够识别关键字是GBK编码还是UTF-8编码,能够识别关键字是否进行了URL编码)
&output=xml  (输出类型支持:xml 或 json)
&excerpts=1  (是否开启高亮显示与文本摘要,1开启 或 0关闭)
&excerpts_before=<font color=red>  (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字前面插入的字符串。)
&excerpts_after=</font>  (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字之后插入的字符串。)
&excerpts_limit=256  (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。摘要最多包含的符号(码点)数。)
&excerpts_field=c1,c2,c3,c4,c5  (仅对指定的字段进行高亮显示,其余字段不进行高亮显示,如果此参数为空,则默认所有的字符型字段都进行高亮显示)
&offset=0&limit=20  (相当于SQL语句中的limit 0,20)
&max_matches=30000  (最大搜索结果集数量)
&match_mode=SPH_MATCH_EXTENDED2
&ranking_mode=SPH_RANK_PROXIMITY_BM25
&sort_mode=SPH_SORT_EXTENDED&sort_by=@relevance DESC,u1 ASC,@id DESC  (排序模式:@relevance和@id是内置变量,@relevance代表相关度权值,@id等于search_id,u1为字段名)
&field_weights=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,字段u2 < 50并且u2 > 90)
&filter_range=u1:1.23,99.645,false;u2:1034.3,7834.56,true  (浮点数范围过滤器:字段u1 >= 1.23并且u1 <= 99.645,字段u2 < 1034.3并且u2 > 7834.56)




  6、搜索结果前台页面示例:

  点击在新窗口中浏览此图片



  7、同一套服务器平台与API接口,通用于各类产品:

  示例:

  金山游戏文章与视频搜索:http://s.xoyo.com/result.php?w=%E5%89%91%E7%BD%913

  金山游戏论坛帖子搜索:http://jx3.bbs.xoyo.com/search2.php?srchtxt=%E4%B8%83%E7%A7%80&select=title


Tags: , ,



技术大类 » 搜索引擎技术 | 评论(99) | 引用(0) | 阅读(171464)
jackson
2010-5-14 10:28
如果 searchd 死掉了怎么办? 有什么好的方案啊?
叫我小刀
2010-5-19 16:40
问下,我在centos5下make         coreseek       时报如下错误
Making all in src
make[1]: Entering directory `/usr/local/csft-3.1/src'
if test -d ../.svn; then svn info .. --xml | perl svnxrev.pl; fi;
make  all-am
make[2]: Entering directory `/usr/local/csft-3.1/src'
g++  -Wall -g -D_FILE_OFFSET_BITS=64 -O3 -DNDEBUG   -o indexer  indexer.o libsphinx.a  -L/usr/local/mysql/lib/ -lmysqlclient -lz  -L/usr/local/mmseg/lib/ -lmmseg -lm -lz  -L/usr/local/lib -lpthread
/usr/bin/ld: cannot find -lmysqlclient
collect2: ld returned 1 exit status
make[2]: *** [indexer] Error 1
make[2]: Leaving directory `/usr/local/csft-3.1/src'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/local/csft-3.1/src'
make: *** [all-recursive] Error 1

怎么解决啊?
TOPBOY
2010-5-22 23:44
楼主, 系统架构图是用什么画的?
crunchrobble
2010-6-14 21:27
你用一元分词,搜索羊时喜羊羊肯定出来
看我做的搜索引擎 http://www.net114.com/sproduct:手机.html
过路人
2010-7-22 11:23
你听过哪个搜索引擎会用数据库的,用数据库的不叫搜索引擎,搜索引擎里面深度大了
张宴 回复于 2010-7-22 13:48
并没有用数据库。MySQL只是作为一项更便捷地往索引中导入数据的工具而已,跟用XML文件导入数据没有什么区别。
ff Email
2010-8-24 18:48
引用你的话"二是由于MySQL表的主键与Sphinx索引的ID一一对应,从而无法跨多表建立整站查询,而且新增加类别还得修改配置文件,比较麻烦."

你说的这个 在 这个新架构里解决了吗?
我看了那个  千万级数据全文检索(搜索引擎)架构设计 "脚本".
对不同城市不同分类,做了不同索引,类似分区效果, 查不同城市不同分类很快. 但是不能跨多表建立整站查询.

这个新的架构是如何  兼顾"城市分类查询" 和 "全站查询".
easymusic
2010-9-9 22:21
请问一下是使用什么分词软件来分词的?
efish Homepage
2010-10-9 14:34
可以自己架构个玩玩吗
jason Email
2010-10-23 14:04
有个问题,  题外问题, 架构图, 你用的是什么软件画的?

我一直没找到个好工具!
shuitu
2010-10-31 00:37
有个比较菜的问题请教大师。
没有理解错的话,一元分词对“俄罗斯民调显示梅德韦杰夫人气急升”句子是分别对“梅 德 韦 杰 乎”五个单字进行索引。那么sphinx是如何搜索“梅德韦杰夫”这个完整的词的?
lili
2010-11-14 11:05
lili
2010-11-14 11:05
好啊
willin Email
2010-12-2 11:29
张老师,我使用sphinx、pocketsphinx开发语音识别的,现在需要这方面的人员,希望您能介绍几位好友。联系方式:qq,180023862;MSN:guofeng.1975@hotmail.com.非常感谢!
2011-2-9 17:24
请教一下,队列控制器接收到文章的增删除等动作时,如何调用sphinx相关的命令去更新索引,又或把增量索引合到主索引呢?
小覃 Email Homepage
2011-2-22 13:50
张学长,你好伟大哈!
qiudakun
2011-3-9 11:28
FATAL: out of memory (unable to allocate 959632784 bytes):官网说是内存不够的原因。但我空闲的内存还有没有4G. 主索引为4G,增索引为100M.应该内存是够用的。单给主 或 增做--rotate,正常运行。
超越
2011-3-18 12:57
sweat我的个母亲啊,你弄的真详细啊,不顶不行啊。zanzanzan
金华SEO Email Homepage
2011-3-31 19:17
金华SEOhttp://www.jinhuaseo.net/支持你
17ic Homepage
2011-6-27 15:59
如果您的技术很牛,也可以技术入股,欢迎高手加入。。有没有想兼职sphinx工作的,有的话可以联系我guyejun98@163.com  QQ:1009468288
17ic电子渠道网
baoker Email
2011-7-12 10:32
麻烦给些建议。
我有约900万数据,数据库大小约100G,现在只测试了90W记录,9.7G数据,数据全部为UTF-8的英文,建立索引估计用了20分钟。
索引文件比数据库小了很多:
-rw-r--r-- 1 root root    0 07-12 09:11 all.spa
-rw-r--r-- 1 root root 2.0G 07-12 09:29 all.spd
-rw-r--r-- 1 root root  603 07-12 09:29 all.sph
-rw-r--r-- 1 root root 4.4M 07-12 09:29 all.spi
-rw-r--r-- 1 root root    0 07-12 09:11 all.spk
-rw-r--r-- 1 root root    0 07-12 09:11 all.spm
-rw-r--r-- 1 root root 2.4G 07-12 09:29 all.spp
-rw-r--r-- 1 root root    1 07-12 09:29 all.sps
===================================
目前遇到以下2个问题:
   1.当我搜索1个单词的时候速度在0.1秒以下;当我搜索2个单词的时候,速度就4秒,单词越多就越慢,10几个单词的时候就10多秒
   2.主索引可以把900万数据一次性建立起来,但是每天估计还会有5000条数据插入,是应该重新建立索引好【理论I/O开销<100G】,还是应该合并索引呢【I/O开销就是200G】?

目前只测试了90W数据就没办法承受了,不知道该如何是好,服务器为32位CENTOS 5.4,系统配置算可以,是否改为64位会有很大提升呢?
是否能通过修改sphinx配置文件来提升?



谢谢!
分页: 3/5 第一页 上页 1 2 3 4 5 下页 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]