A-A+

基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计

2008年11月29日 学习随笔 暂无评论 阅读 1 次
[2008-7-27 22:29 | by 张宴 ]

[文章作者:张宴本文版本:v1.0 最后修改:2008.07.27 转载请注明原文链接:http://blog.s135.com/read.php/360.htm]

  前言:本文阐述的是一款经过生产环境检验的千万级数据全文检索(搜索引擎)架构。本文只列出前几章的内容节选,不提供全文内容。
  在DELL PowerEdge 6850服务器(四颗64 Inter Xeon MP 7110N处理器 / 8GB内存)、RedHat AS4 Linux操作系统、MySQL 5.1.26MyISAM存储引擎、key_buffer=1024M环境下实测,单表1000万条记录的数据量(这张MySQL表拥有intdatetimevarchartext等类型的10多个字段,只有主键,无其它索引),用主键(PRIMARY KEY)作为WHERE条件进行SQL查询,速度非常之快,只耗费0.01秒。

  出自俄罗斯的开源全文搜索引擎软件Sphinx,单一索引最大可包含1亿条记录,在1千万条记录情况下的查询速度为0.x秒(毫秒级)。Sphinx创建索引的速度为:创建100万条记录的索引只需34分钟,创建1000万条记录的索引可以在50分钟内完成,而只包含最新10万条记录的增量索引,重建一次只需几十秒。

  基于以上几点,我设计出了这套搜索引擎架构。在生产环境运行了一周,效果非常不错。有时间我会专为配合Sphinx搜索引擎,开发一个逻辑简单、速度快、占用内存低、非表锁的MySQL存储引擎插件,用来代替MyISAM引擎,以解决MyISAM存储引擎在频繁更新操作时的锁表延迟问题。另外,分布式搜索技术上已无任何问题。


 


一、搜索引擎架构设计:
1、搜索引擎架构图:

2、搜索引擎架构设计思路:
(1)、调用方式最简化:
  尽量方便前端Web工程师,只需要一条简单的SQL语句“SELECT ... FROM myisam_table JOIN sphinx_table ON (sphinx_table.sphinx_id=myisam_table.id) WHERE query='...';”即可实现高效搜索。

(2)、创建索引、查询速度快:
Sphinx Search 是由俄罗斯人Andrew Aksyonoff 开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行。
Sphinx的特征:
•Sphinx支持高速建立索引(可达10MB/秒,而Lucene建立索引的速度是1.8MB/秒)
高性能搜索(在2-4 GB的文本上搜索,平均0.1秒内获得结果)
高扩展性(实测最高可对100GB的文本建立索引,单一索引可包含1亿条记录)
支持分布式检索
支持基于短语和基于统计的复合结果排序机制
支持任意数量的文件字段(数值属性或全文检索属性)
支持不同的搜索模式(完全匹配短语匹配任一匹配
支持作为Mysql的存储引擎

、通过国外《High Performance MySQL》专家组的测试可以看出,根据主键进行查询的类似“SELECT ... FROM ... WHERE id = ...”SQL语句(其中idPRIMARY KEY),每秒钟能够处理10000次以上的查询,而普通的SELECT查询每秒只能处理几十次到几百次:

Sphinx不负责文本字段的存储。假设将数据库的iddatetitlebody字段,用sphinx建立搜索索引。根据关键字、时间、类别、范围等信息查询一下sphinxsphinx只会将查询结果的ID号等非文本信息告诉我们。要显示titlebody等信息,还需要根据此ID号去查询MySQL数据库,或者从Memcachedb等其他的存储中取得。安装SphinxSE作为MySQL的存储引擎,将MySQLSphinx结合起来,是一种便捷的方法。
  创建一张Sphinx类型表,将MyISAM表的主键IDSphinx表的ID作一个JOIN联合查询。这样,对于MyISAM表来所,只相当于一个WHERE id=...的主键查询,WHERE后的条件都交给Sphinx去处理,可以充分发挥两者的优势,实现高速搜索查询。

(3)、按服务类型进行分离:
  为了保证数据的一致性,我在配置Sphinx读取索引源的MySQL数据库时,进行了锁表。Sphinx读取索引源的过程会耗费一定时间,由于MyISAM存储引擎的读锁和写锁是互斥的,为了避免写操作被长时间阻塞,导致数据库同步落后跟不上,我将提供搜索查询服务的和提供索引源服务MySQL数据库进行了分开。监听3306端口的MySQL提供搜索查询服务,监听3406端口的MySQL提供索引源服务

(4)主索引+增量索引更新方式:
  一般网站的特征:信息发布较为频繁;刚发布完的信息被编辑、修改的可能性大;两天以前的老帖变动性较小。
  基于这个特征,我设计了Sphinx主索引和增量索引。对于前天17:00之前的记录建立主索引,每天凌晨自动重建一次主索引;对于前天17:00之后到当前最新的记录,间隔3分钟自动重建一次增量索引。

(5)“Ext3文件系统+tmpfs内存文件系统相结合:
  为了避免每3分钟重建增量索引导致磁盘IO较重,从而引起系统负载上升,我将主索引文件创建在磁盘,增量索引文件创建在tmpfs内存文件系统“/dev/shm/”内。“/dev/shm/”内的文件全部驻留在内存中,读写速度非常快。但是,重启服务器会导致“/dev/shm/”内的文件丢失,针对这个问题,我会在服务器开机时自动创建“/dev/shm/”内目录结构和Sphinx增量索引。

(6)、中文分词词库:
  我根据自整理的中文分词库搜狗拼音输入法细胞词库“LibMMSeg高频字库... 综合整理成一份中文分词词库,出于某些考虑暂不提供。你可以使用LibMMSeg自带的中文分词词库。


 


二、MySQL+Sphinx+SphinxSE安装步骤:
1、安装python支持(以下针对CentOS系统,其他Linux系统请使用相应的方法安装)

yum install -y python python-devel

 

2、编译安装LibMMSegLibMMSeg是为Sphinx全文搜索引擎设计的中文分词软件包,其在GPL协议下发行的中文分词法,采用Chih-Hao TsaiMMSEG算法。LibMMSeg在本文中用来生成中文分词词库。)

  以下压缩包“sphinx-0.9.8-rc2-chinese.zip”中包含mmseg-0.7.3.tar.gzsphinx-0.9.8-rc2.tar.gz以及中文分词补丁。

下载文件 (已下载 18 )

点击这里下载文件

unzip sphinx-0.9.8-rc2-chinese.zip
tar zxvf mmseg-0.7.3.tar.gz
cd mmseg-0.7.3/
./configure
make
make install
cd ../

 

3、编译安装MySQL 5.1.26-rcSphinxSphinxSE存储引擎

wget http://dev.mysql.com/get/Downloads/MySQL-5.1/mysql-5.1.26-rc.tar.gz/from/http://mirror.x10.com/mirror/mysql/
tar zxvf mysql-5.1.26-rc.tar.gz

tar zxvf sphinx-0.9.8-rc2.tar.gz
cd sphinx-0.9.8-rc2/
patch -p1 < ../sphinx-0.98rc2.zhcn-support.patch
patch -p1 < ../fix-crash-in-excerpts.patch
cp -rf mysqlse ../mysql-5.1.26-rc/storage/sphinx
cd ../

cd mysql-5.1.26-rc/
sh BUILD/autorun.sh
./configure --with-plugins=sphinx --prefix=/usr/local/mysql-search/ --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-big-tables --with-readline --with-ssl --with-embedded-server --enable-local-infile
make && make install
cd ../

cd sphinx-0.9.8-rc2/
CPPFLAGS=-I/usr/include/python2.4
LDFLAGS=-lpython2.4
./configure --prefix=/usr/local/sphinx --with-mysql=/usr/local/mysql-search
make
make install
cd ../

mv /usr/local/sphinx/etc/sphinx.conf /usr/local/sphinx/etc/sphinx.conf.old


 


第二章第3节之后的正文内容不予公布,全文的目录如下(共24页):

 

 



Tags: linux , php , mysql , sphinx , search , fulltext , sql , 全文索引 , 全文检索 , 全文搜索 , 搜索引擎 , bash , sh

纯粹技术 | 评论(18) | 引用(0) | 阅读(2533)

引用地址:
注意:该地址仅在今日23:59:59之前有效

lphy

2008-7-28

这是一条隐藏评论或留言。您需要以合适的身份登入后才能看到。

king'space

2008-7-28

很好很强大.
现在你的博客的访问速度快了不少。

是网通和电信的互访问题?

加油张宴

Roast

2008-7-28

SphinxLibMMSeg的结合存在比较多的问题,就我目前使用的状态来看还不足以在对搜索结果要求比较准确的情况下使用:
1
LibMMSeg的分词是基于正向最大匹配和逆向最大匹配的结合来做的分词,但功能较差,过份依赖词库,有许多特性没有支持,包括中文名字智能识别等,这也是使用这一分词组件的所有搜索引擎存在的问题。
2
、另外一个就是分词补丁存在的问题,据我最近一月的使用状况和用户的反馈来看,有许多内容没有索引或者检索失败。使用searchd打开的端口进行搜索的结果更加糟糕。
3
、另外该分词组件也没有提供语法高亮、全文摘要等必备的特性,都需要自己去编写。
综于以上原因,就我的使用经验来看,呵呵,玩玩还可以,要用的话还是有点……
所以我打算重新把我原来的Sphinx中文分词插件完善起来!

张宴回复于 2008-7-28 13:24

基于中文分词技术的搜索引擎主要依赖于词库,LibMMSeg自带的词库是不完善的,所以我在弄到的百度早期词库的基础上,自己做了中文分词词库,精准度在90%以上。

另外,一般搜索引擎应用中,并不需要100%精准的匹配度,而是需要比较高的相关度,例如在Sphinx中搜索莱镇香格里,文章中包含莱镇香格里的内容也会列出来;用户搜索左家庄附近,包含左家庄小区附近的内容也会列出来,这正是用户所需要查找的内容。

中文名字的智能识别,就连Google目前也没有做到(比如你在www.google.cn中搜索张老三正在重装操作系统,点击网页快照可以看到,这句话会被切分成正在操作系统),所以不要苛刻要求LibMMSeg了。

要想对搜索结果100%的精准匹配,中文分词技术是做不到的,只能通过例如N元切分等其他技术实现。

taxuerb

2008-7-28

Sphinx?是不是和AvaFind差不多,我电脑上搜索一直用AvaFind,挺快

张宴回复于 2008-7-28 13:23

不一样。AvaFind只是类似百度硬盘搜索的硬盘搜索工具。

tombob

2008-7-28

张宴大师有空写一篇squid的安装和配置的详解吧

互联网上的教程也就你的最容易学!

Roast

2008-7-28

引用

基于中文分词技术的搜索引擎主要依赖于词库,LibMMSeg自带的词库是不完善的,所以我在弄到的百度早期词库的基础上,自己做了中文分词词库,精准度在90%以上。  另外,一般搜索引擎应用中,并不需要100%精准的匹配度,而是需要比较高的相关度,例如在Sphinx中搜索莱镇香格里,文章中包含莱镇香格里的内容也会列出来;用户搜索左家庄附近,包含左家庄小区附近的内容也会列出来,这正是用户所需要查找的内容。  中文名字的智能识别,就连Google目前也没有做到(比如你在www.google.cn中搜索张老三正在重装操作系统,点击网页快照可以看到,这句话会被切分成正在操作系统),所以不要苛刻要求LibMMSeg了。  要想对搜索结果100%的精准匹配,中文分词技术是做不到的,只能通过例如N元切分等其他技术实现。


只有基于词库的分词技术才依赖于词库,基于语义识别、二分法等分词技术是不需要词库的。并且名字等的智能识别在中文分词技术中是必须的,具体你可以看下hightman的简易分词算法,就具有这些功能。而对于复杂的分词算法来说,他的准确程度是相当高的,包括地名、人名、生僻词等的识别都比较智能化的。而N元切分这种技术是不可能使用到搜索技术中来的,只与简单索引有关……

outrace

2008-7-29

还是以前碰到的问题使得我没法使用sphinx
就是:id必须是数字,而我们系统都是使用uuid()的字符串。

另外中文分词的插件是根据版本的补丁,而目前官方已经是0.9.8-release了。
而中文分词补丁还是rc2的。

七夜

2008-7-29

Roast 説的有问题了。语义搜索现在还处于实验室当中,并不能实用。
再接下去,你看一下 hightman 的人名自动识别功能。
"
陈凯歌并不是《无极》的唯一著作权人,一部电影的整体版权归电影制片所有。"
这个是hightman 演示站的第一句。我把"陈凯歌" ""去掉。这个自动识别就有错误了。识别成了"陈凯并"

你説是识别成"陈凯并"还是"陈凯"好了,只能两个歧义都保存成一个词。

hightman 只是针对常用没什么大的歧义句子分词的。对于复杂的还是 N元分词有必要的。

语义识别也是基于语义库的,而不是凭空就蹦出来的。多研究一下吧

Roast

2008-7-29

呵呵,不管是识别成"陈凯并"还是"陈凯"都是正确的,但是如果没有识别,那肯定就是不行的,对于地名、人名、生僻词的识别就我看过的文档,是做为一个分词系统必须的,想想你拿一句"陈凯歌识别成""和识别成"陈凯"还是"陈凯并"是相差很大的,如果你把"陈凯歌换成是张宴或者是其它名字,有地名、人名、生僻词的识别规则的分词系统与没有的质量完全不是同一个档次的,而在中文中文本中地名、人名、生僻词无处不在。可以说没有地名、人名、生僻词的中文分词算法玩玩还可以,对于要求比较高的系统是必须的,这也是我见过的自己做站内搜索引擎存在的最大的问题,大都使用的LibMMSegLibMMSeg的其它语言的实现版本

对于N元分词我个人的看法,对于专业级别的搜索引擎来说,肯定不会去用,从准确度到索引块的大小等方面都不适合做为专业级别的搜索引擎来用。

对于七夜同学的说法,我不认同,语义识别在现在的分词系统中都是用到了的,并不是处理实验室阶段。就我看过的分词算法的代码和资料,分词算法中语义对于分词算法是非常重要的

我讲的是分词算法中的语义识别,而非语义搜索,~!语义识别当然也是基于语义库的,但并不仅仅就一个语义库。

routerpipe

2008-7-30

感谢老大提供如此详细的文档。

能否提供您整理的词库用用?

万分感谢!我的email:routerpipe@gmail.com

七夜

2008-7-31

N元分词的,关键词检索命中率几乎是百分之一百。对于一个大众搜索足够用了。唯一的问题,就是产生非常多的垃圾索引。
使用google bigtableGFS,这些垃圾索引存储几乎是没问题的。像一些外国人的中译名不好分词。N元分词是比较合适的。

我的搜索引擎用的就是 N元分词,非常好用。我的用不着严格的科学分词

Roast

2008-8-2

如果我没有猜错,你的搜索引擎是基于数据库的LIKE....

dd_macle

2008-8-2

对这块没有什么研究,学习。。。。

dancebear

2008-8-2

我觉得使用sphinx+mysql+libmmseg来进行搜索的话还不如直接使用coreseek开发的用于中文搜索的sphinx修改版,而且使用他的python数据源的话可以不再局限于sphinx单一的支持utf-8mysql的数据源。相对来说比sphinx的适应度更高。

张宴回复于 2008-8-2 11:43

打了补丁的sphinx可以支持utf-8gbklatin1

nzinfo

2008-8-4

呵呵,我是coreseek的站长。很高兴大家讨论我们在sphinx上的工作。
mmseg
是有很多不足;我平时使用的是crf切分系统。
不过,当用户使用自定义词库时,如果进行一些词库的定制(比如将常用的检索式定义成词)或者建立两级索引,mmseg+sphinx的表现在某些情况下甚至好于crf( or bi-gram ) + sphinx的方案。
处于简单易用的考虑,mmseg+sphinix应该能够满足一般网站的全文检索需要了。
陈凯歌,在词库中加入陈凯歌要比换一套更好切词器更经济。
包括Google|百度目前工业上也都是采用某种MMSegN-gram | Maxent | Crf 的方法在计算上还不是很经济。

至于语法高亮、全文摘要这个Sphinx已经自带了,自然分词器就不带了。

yls

2008-8-5

nzinfo有没有更新的版本出来呀,linux上的

test

2008-8-9

可惜好东西,不公开

joomlaer

2008-8-19

我有个更简单的主义,又实现了联想,又分了词。
把内容分词后转换为拼音,以增量索引进行sphix.
然后用SQL进行查询。

给我留言

Copyright © 浩然东方 保留所有权利.   Theme  Ality 07032740

用户登录