资源描述
(word完整版)Sphinx搜索引擎架构与使用文档(和MySQL结合)V1.1
Sphinx搜索引擎架构与使用文档(和MySQL结合)V1.1
作者:张宴 (http://blog。) 时间:2008—11-18
本文档修订历史:
版本号
修订人
修订说明
1。0。0—20080721
张宴
新建
1。0。1-20080723
张宴
增加搜索索引配置
1。0。2-20080916
张宴
增加在指定字段中搜索的SQL实例
1.1.0-20081118
张宴
修正小错误
●说明:水绿色背景表示Linux Shell命令、橄榄色背景表示MySQL的SQL语句、淡蓝色背景表示配置文件内容、黑底白字表示屏幕显示内容.
目 录
一、XX网搜索引擎架构设计: 3
1、搜索引擎架构图(基于PHP+MySQL+Sphinx): 3
2、搜索引擎架构设计思路: 3
⑴、调用方式最简化: 3
⑵、创建索引、查询速度快: 3
⑶、按服务类型进行分离: 4
⑷、“主索引+增量索引”更新方式: 4
⑸、“Ext3文件系统+tmpfs内存文件系统”相结合: 4
⑹、中文分词词库: 5
二、MYSQL+SPHINX+SPHINXSE安装步骤: 5
1、安装python支持 5
2、编译安装LibMMSeg 5
3、编译安装MySQL 5.1.26-rc、Sphinx、SphinxSE存储引擎 5
4、创建Sphinx索引文件和MySQL数据文件存放目录 6
5、创建MySQL配置文件(以线上配置文件为准) 6
⑴、创建配置文件/mysql/3306/f(以db11的3306端口为例) 6
⑵、创建配置文件/mysql/3406/f(以db11的3406端口为例) 8
6、制作一份MySQL Slave供搜索引擎使用 10
7、创建快捷启动、停止、重启、杀死MySQL进程的脚本(以db11的3306端口为例) 10
三、SPHINX配置: 11
1、生成Sphinx中文分词词库 11
⑴、词典的构造 12
⑵、词典文件格式 12
⑶、XX网搜索引擎的中文分词词库 12
2、创建Sphinx主索引文件、增量索引文件存放目录 12
3、创建Sphinx配置文件 13
4、初始化sphinx.conf中配置的全部索引 13
5、创建两个shell脚本,一个用来创建主索引、一个用来创建增量索引。 13
⑴、主索引更新脚本 13
①、创建脚本build_main_index.sh: 13
②、赋予主索引更新脚本可执行权限: 13
③、每天凌晨定时重建主索引: 13
⑵、增量索引更新脚本 13
①、创建脚本build_delta_index.sh: 13
②、赋予增量索引更新脚本可执行权限: 14
③、每3分钟自动重建一次搜索引擎的增量索引: 14
6、启动Sphinx守护进程(searchd) 14
7、配置服务器开机启动时需要自动执行的命令(以db11为例) 14
8、创建Sphinx存储引擎表: 14
⑴、设置/etc/hosts 14
⑵、登录运行在3306端口的MySQL服务器(提供“搜索查询服务”): 14
⑶、创建数据库“Sphinx”和相对应的Sphinx表(SQL语句): 15
示例SQL: 15
四、如何通过SQL语句调用搜索引擎: 15
1、搜索应用实例 15
⑴、XX网北京出租房搜索 15
⑵、XX网北京小区搜索 15
⑶、在指定字段中搜索(例如在字段“title”中搜索关键字“中关村") 16
2、SphinxSE存储引擎及SQL语法详细说明 16
一、XX网搜索引擎架构设计:
1、搜索引擎架构图(基于PHP+MySQL+Sphinx):
注:目前有两台搜索数据库,db9(192.168.113。209)(MySQL 3306端口用于搜索查询、3406端口用于建索引)和db11(192。168.113.211)(MySQL 3306、3307端口用于搜索查询,3406端口用于建索引),dbsearch为NetScaler虚拟IP 192。168。113.163(做db9的3306,db11的3306、3307负载均衡)的hosts。
2、搜索引擎架构设计思路:
⑴、调用方式最简化:
尽量方便前端Web工程师,只需要一条简单的SQL语句“SELECT .。. FROM 。.。 JOIN 。。. ON (。。.=..。) WHERE query='.。。’;"即可实现高效搜索.
⑵、创建索引、查询速度快:
①、Sphinx Search 是由俄罗斯人Andrew Aksyonoff 开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行。
Sphinx的特征:
·Sphinx支持高速建立索引(可达10 MB/秒,而Lucene建立索引的速度是1。8MB/秒)
·高性能搜索(在2-4 GB的文本上搜索,平均0.1秒内获得结果)
·高扩展性(在单一CPU上,实测最高可对100GB的文本建立索引,单一索引可包含1亿条记录)
·支持分布式检索
·支持基于短语和基于统计的复合结果排序机制
·支持任意数量的文件字段(数值属性或全文检索属性)
·支持不同的搜索模式(“完全匹配”,“短语匹配”和“任一匹配”)
·支持作为Mysql的存储引擎
②、通过国外《High Performance MySQL》专家组的测试可以看出,根据主键进行查询的类似“SELECT .。. FROM ... WHERE id = .。.”的SQL语句(其中id为PRIMARY KEY),每秒钟能够处理10000次以上的查询,而普通的SELECT查询每秒只能处理几十次到几百次:
③、Sphinx不负责文本字段的存储。假设将数据库的id、date、title、body字段,用sphinx建立搜索索引。根据关键字、时间、类别、范围等信息查询一下sphinx,sphinx只会将查询结果的ID号告诉我们。要显示title、body等信息,还需要根据此ID号去查询MySQL数据库,或者从Memcachedb等其他的存储中取得。安装SphinxSE作为MySQL的存储引擎,将MySQL与Sphinx结合起来,是一种便捷的方法。
创建一张Sphinx类型表,将MyISAM表的主键ID和Sphinx表的ID作一个JOIN联合查询。这样,对于MyISAM表来所,只相当于一个WHERE id=.。。的主键查询,WHERE后的条件都交给Sphinx去处理,可以充分发挥两者的优势,实现高速搜索查询。
⑶、按服务类型进行分离:
为了保证数据的一致性,我在配置Sphinx读取索引源的MySQL数据库时,进行了锁表.Sphinx读取索引源的过程会耗费一定时间,由于MyISAM存储引擎的读锁和写锁是互斥的,为了避免写操作被长时间阻塞,导致数据库同步落后跟不上,我将提供“搜索查询服务”的和提供“索引源服务”的MySQL数据库进行了分开。监听3306端口的MySQL提供“搜索查询服务”,监听3406端口的MySQL提供“索引源服务".
⑷、“主索引+增量索引"更新方式:
XX网的特征:发帖较为频繁;刚发完的帖被用户自己编辑、修改的可能性大;新发的帖会被编辑审核(删除、标记为中介等);两天以前的老帖变动性较小.
基于这个特征,我设计了Sphinx主索引和增量索引。对于前天17:00之前的记录建立主索引,每天凌晨自动重建一次主索引;对于前天17:00之后到当前最新的记录,间隔3分钟自动重建一次增量索引。
⑸、“Ext3文件系统+tmpfs内存文件系统”相结合:
为了避免每4分钟重建增量索引导致磁盘IO较重,从而引起系统负载上升,我将主索引文件创建在磁盘,增量索引文件创建在tmpfs内存文件系统“/dev/shm/”内。“/dev/shm/”内的文件全部驻留在内存中,读写速度非常快。但是,重启服务器会导致“/dev/shm/”内的文件丢失,针对这个问题,我会在服务器开机时自动创建“/dev/shm/”内目录结构和Sphinx增量索引。
⑹、中文分词词库:
XX网搜索引擎使用到的中文分词词库,为本人根据“百度早期中文分词库”+“搜狗拼音输入法细胞词库”+“XX网地标词库”+“LibMMSeg高频字库”综合处理而成.
二、MySQL+Sphinx+SphinxSE安装步骤:
1、安装python支持(以下针对CentOS系统,其他Linux系统请使用相应的方法安装)
yum install —y python python—devel
2、编译安装LibMMSeg(LibMMSeg是为Sphinx全文搜索引擎设计的中文分词软件包,其在GPL协议下发行的中文分词法,采用Chih-Hao Tsai的MMSEG算法。LibMMSeg在本文中用来生成中文分词词库。)
wget http://
tar zxvf mmseg-0.7.3.tar。gz
cd mmseg—0.7.3/
。/configure
make
make install
cd 。./
3、编译安装MySQL 5.1.26-rc、Sphinx、SphinxSE存储引擎
wget http://blog。
tar zxvf mysql—5.1.26—rc。tar.gz
wget
wget
wget http://www。coreseek。com/uploads/sources/fix—crash-in-excerpts。patch
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 .。/
4、创建Sphinx索引文件和MySQL数据文件存放目录(/mysql/3306/data和/mysql/3406/data)
mkdir -p /usr/local/sphinx/var/data/beijing/house/
mkdir -p /usr/local/sphinx/var/data/shanghai/house/
mkdir —p /usr/local/sphinx/var/data/guangzhou/house/
mkdir -p /usr/local/sphinx/var/data/wuhan/house/
mkdir —p /usr/local/sphinx/var/data/nanjing/house/
mkdir -p /usr/local/sphinx/var/data/tianjin/house/
mkdir -p /usr/local/sphinx/var/data/shenzhen/house/
mkdir -p /usr/local/sphinx/var/data/qita/house/
mkdir —p /dev/shm/sphinx/var/data/beijing/house/
mkdir -p /dev/shm/sphinx/var/data/shanghai/house/
mkdir -p /dev/shm/sphinx/var/data/guangzhou/house/
mkdir -p /dev/shm/sphinx/var/data/wuhan/house/
mkdir -p /dev/shm/sphinx/var/data/nanjing/house/
mkdir —p /dev/shm/sphinx/var/data/tianjin/house/
mkdir —p /dev/shm/sphinx/var/data/shenzhen/house/
mkdir -p /dev/shm/sphinx/var/data/qita/house/
/usr/sbin/groupadd mysql
/usr/sbin/useradd —g mysql mysql
chmod +w /usr/local/mysql—search
chown -R mysql:mysql /usr/local/mysql—search
mkdir —p /mysql/3306/data
chmod +w /mysql/3306/data
mkdir —p /mysql/3307/data
chmod +w /mysql/3307/data
mkdir -p /mysql/3406/data
chmod +w /mysql/3406/data
chown -R mysql:mysql /mysql
#cp support—files/my-medium。cnf /mysql/3306/f
#cp support-files/my-f /mysql/3307/my。cnf
#cp support—files/my—medium。cnf /mysql/3406/my。cnf
5、创建MySQL配置文件(以线上配置文件为准)
⑴、创建配置文件/mysql/3306/f(以db11的3306端口为例)
vi /mysql/3306/f
输入以下内容:
[client]
#password = your_password
port = 3306
socket = /mysql/3306/mysql。sock
[mysqld_safe]
datadir = /mysql/3306/data
log—error = /mysql/3306/mysql_error。log
pid-file = /mysql/3306/mysql.pid
[mysqld]
port = 3306
socket = /mysql/3306/mysql。sock
skip—locking
#skip—slave—start
key_buffer = 2048M
max_allowed_packet = 2M
table_cache = 2048
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 16M
max_length_for_sort_data = 64
myisam_sort_buffer_size = 128M
thread_cache = 8
query_cache_size = 128M
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
#skip-name—resolve
max_connections = 1000
max_connect_errors = 1000
open_files_limit = 51200
ft_min_word_len = 1
concurrent_insert = 2
low_priority_updates = 1
slave—skip—errors = 1032,1062,126,1114,1146,1048,1396,1030
server-id = 113306
#master-host = db1
#master-user = repl
#master-password = slavepass
#master-port = 3306
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto—rehash
# Remove the next comment character if you are not familiar with SQL
#safe-updates
[isamchk]
key_buffer = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M
[myisamchk]
key_buffer = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive-timeout
⑵、创建配置文件/mysql/3406/f(以db11的3406端口为例)
vi /mysql/3406/f
输入以下内容:
[client]
#password = your_password
port = 3406
socket = /mysql/3406/mysql.sock
[mysqld_safe]
datadir = /mysql/3406/data
log—error = /mysql/3406/mysql_error.log
pid-file = /mysql/3406/mysql。pid
[mysqld]
port = 3406
socket = /mysql/3406/mysql.sock
skip—locking
#skip-slave-start
key_buffer = 512M
max_allowed_packet = 2M
table_cache = 1024
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
max_length_for_sort_data = 64
myisam_sort_buffer_size = 64M
thread_cache = 8
query_cache_size = 32M
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
#skip—name-resolve
max_connections = 1000
max_connect_errors = 1000
open_files_limit = 51200
ft_min_word_len = 1
#low_priority_updates = 1
slave-skip—errors = 1032,1062,126,1114,1146,1048,1396,1030
server—id = 113406
#master-host = db1
#master-user = repl
#master-password = slavepass
#master-port = 3306
[mysqldump]
quick
max_allowed_packet = 16M
[mysql]
no-auto—rehash
# Remove the next comment character if you are not familiar with SQL
#safe—updates
[isamchk]
key_buffer = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M
[myisamchk]
key_buffer = 256M
sort_buffer_size = 256M
read_buffer = 2M
write_buffer = 2M
[mysqlhotcopy]
interactive—timeout
6、制作一份MySQL Slave供搜索引擎使用
⑴、找一台MySQL从库,停止同步进程(SQL语句:stop slave;);
⑵、查看同步位置(SQL语句:show slave status\G),记录以下几项值:
Master_Host: db1
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin。000117
Read_Master_Log_Pos: 822317949
⑶、可以使用导出、导入SQL的方法创建供搜索引擎使用的MySQL从库。对于MyISAM表,可以直接拷贝文件(此步骤略)。
⑷、启动搜索引擎专用MySQL数据库:
ulimit —SHn 500000
/bin/sh /usr/local/mysql—search/bin/mysqld_safe --defaults-file=/mysql/3406/my。cnf &
/bin/sh /usr/local/mysql—search/bin/mysqld_safe -—defaults-file=/mysql/3306/my。cnf &
⑸、从命令行登录MySQL服务器(此步骤略)。
⑹、设置同步点,并启动同步(SQL语句如下):
CHANGE master TO master_host=”db1", master_user="repl", master_password="slavepass", master_log_file=”mysql-bin。000125”, master_log_pos=111145646;
START SLAVE;
7、创建快捷启动、停止、重启、杀死MySQL进程的脚本(以db11的3306端口为例)
vi /mysql/3306/mysql
输入以下内容:
#!/bin/sh
mysql_port=3306
mysql_username="root”
mysql_password=”i0705tsstyl"
function_start_mysql()
{
printf "Starting MySQL。..\n”
/bin/sh /usr/local/mysql-search/bin/mysqld_safe ——defaults—file=/mysql/${mysql_port}/f 2〉&1 〉 /dev/null &
}
function_stop_mysql()
{
printf ”Stoping MySQL。。。\n"
/usr/local/mysql-search/bin/mysqladmin -u ${mysql_username} —p${mysql_password} —S /mysql/${mysql_port}/mysql.sock shutdown
}
function_restart_mysql()
{
printf ”Restarting MySQL。.。\n”
function_stop_mysql
function_start_mysql
}
function_kill_mysql()
{
kill —9 $(ps —ef | grep ’bin/mysqld_safe' | grep ${mysql_port} | awk ’{printf $2}’)
kill -9 $(ps -ef | grep 'libexec/mysqld' | grep ${mysql_port} | awk '{printf $2}')
}
if [ ”$1" = "start" ]; then
function_start_mysql
elif [ "$1” = "stop” ]; then
function_stop_mysql
elif [ "$1” = ”restart" ]; then
function_restart_mysql
elif [ ”$1” = ”kill" ]; then
function_kill_mysql
else
printf "Usage: /mysql/${mysql_port}/mysql {start|stop|restart|kill}\n"
fi
赋予脚本可执行权限:
chmod +x /mysql/3306/mysql
脚本执行方法:
/mysql/3306/mysql start
/mysql/3306/mysql stop
/mysql/3306/mysql restart
/mysql/3306/mysql kill
注:用同样的方法创建另一个shell脚本“/mysql/3406/mysql”,输入以上内容,将上文中用红色标注的MySQL端口3306换成3406
三、Sphinx配置:
1、生成Sphinx中文分词词库
mmseg -u unigram.txt
cp unigram。txt。uni /usr/local/sphinx/etc/uni.lib
⑴、词典的构造
mmseg -u unigram.txt
该命令执行后,将会产生一个名为unigram.txt。uni的文件,将该文件改名为uni。lib,完成词典的构造。需要注意的是,unigram。txt 必须为UTF—8编码.
⑵、词典文件格式
。..。
河 187
x:187
造假者 1
x:1
台北队 1
x:1
湖边 1
。。.。。.
其中,每条记录分两行.其中,第一行为词项,其格式为:[词条]\t[词频率].需要注意的是,对于单个字后面跟这个字作单字成词的频率,这个频率需要在大量的预先切分好的语料库中进行统计,用户增加或删除词时,一般不需要修改这个数值;对于非单字词,词频率处必须为1.第二行为占位项,LibMMSeg的用户只需要简单的在第二行处填"x:1”即可。
⑶、XX网搜索引擎的中文分词词库
XX网搜索引擎使用到的中文分词词库,为本人根据“百度早期中文分词库”+“搜狗拼音输入法细胞词库”+“XX网地标词库"+“LibMMSeg高频字库"综合处理而成。
(双击打开)
2、创建Sphinx主索引文件、增量索引文件存放目录
mkdir -p /usr/local/sphinx/var/data/beijing/house/
mkdir -p /usr/local/sphinx/var/data/shanghai/house/
mkdir —p /usr/local/sphinx/var/data/guangzhou/house/
mkdir —p /usr/local/sphinx/var/data/wuhan/house/
mkdir -p /usr/local/sphinx/var/data/nanjing/house/
mkdir -p /usr/local/sphinx/var/data/tianjin/house/
mkdir -p /usr/local/sphinx/var/data/shenzhen/house/
mkdir —p /usr/local/sphinx/var/data/qita/house/
mkdir —p /dev/shm/sphinx/var/data/beijing/house/
mkdir -p /dev/shm/sphinx/var/data/shanghai/house/
mkdir -p /dev/shm/sphinx/var/data/guangzhou/house/
mkdir -p /dev/shm/sphinx/var/data/wuhan/house/
mkdir —p /dev/shm/sphinx/var/data/nanjing/house/
mkdir -p /dev/shm/sphinx/var/data/tianjin/house/
mkdir -p /dev/shm/sphinx/var/data/shenzhen/house/
mkdir —p /dev/shm/sphinx/var/data/qita/house/
3、创建Sphinx配置文件(以db11为例)
vi /usr/local/sphinx/etc/sphinx。conf
输入以下内容(双击打开):
4、初始化sphinx.conf中配置的全部索引
/usr/local/sphinx/bin/indexer ——all
如果searchd处于运行状态,则执行
/usr/local/sphinx/bin/indexer --all —-rotate
5、创建两个shell脚本,一个用来创建主索引、一个用来创建增量索引。
⑴、主索引更新脚本
①、创建脚本build_main_index。sh:
vi /usr/local/sphinx/bin/build_main_index。sh
输入以下内容(双击打开):
②、赋予主索引更新脚本可执行权限:
chmod +x /usr/local/sphinx/bin/build_main_index。sh
③、每天凌晨定时重建主索引:
crontab -e
增加以下内容:
#每天凌晨4点19分重建一次搜索引擎的主索引
19 4 * * * /bin/sh /usr/local/sphinx/bin/build_main_index。sh
⑵、增量索引更新脚本
①、创建脚本build_delta_index.sh:
vi /usr/local/sphinx/bin/build_delta_index.sh
输入以下内容(双击打开):
②、赋予增量索引更新脚本可执行权限:
chmod +x /usr/local/sphinx/bin/build_delta_index.sh
③、每3分钟自动重建一次搜索引擎的增量索引:
crontab -e
增加以下内容:
#每3分钟自动重建一次搜索引擎的增量索引
0—57/3 * * * * /bin/sh /usr/local/sphinx/bin/build_delta_index。sh
6、启动Sphinx守护进程(searchd)
ulimit -SHn 500000
/usr/local/sphinx/bin/searchd
7、配置服务器开机启动时需要自动执行的命令(以db11为例)
vi /etc/rc.local
在最末尾添加以下内容:
#搜索引擎开机自动执行的命令(以下语句放在rc。local文件的最后)
ulimit -SHn 500000
/bin/sh /mysql/3406/mysql start
/bin/sh /mysql/3306/mysql start
/bin/sh /mysql/3307/mysql start
mkdir —p /dev/shm/sphinx/var/data/beijing/house/
mkdir —p /dev/shm/sphinx/var/data/shanghai/house/
mkdir —p /dev/shm/sphinx/var/data/guangzhou/house/
mkdir -p /dev/shm/sphinx/var/data/wuhan/house/
mkdir -p /dev/shm/sphinx/var/data/nanjing/house/
mkdir —p /dev/shm/sphinx/var/data/tianjin/house/
mkdir —p /dev/shm/sphinx/var/data/shenzhen/house/
mkdir —p /dev/shm/sphinx/var/data/qita/house/
#/usr/bin/nohup /bin/sh /usr/local/sphinx/bin/build_delta_index.sh 2>&1 > /dev/null &
#sleep 360
/bin/sh /usr/local/sphinx/bin/build_delta_index.sh 2>&1 > /dev/null
/usr/local/sphinx/bin/searchd
8、创建Sphinx存储引擎表:
⑴、设置/etc/hosts
vi /etc/hosts
添加以下内容:
192。168。113。209 db9
192。168。113。211 db11
⑵、登录运行在3306端口的MySQL服务器(提供“搜索查询服务”):
/usr/local/mysql-s
展开阅读全文