Sphinx+Scws 搭建千万级准实时搜索&应用场景详解

时间:2022-06-04 08:15:31

目标:
一、搭建准确的千万级数据库的准实时搜索(见详情)
二、实现词语高亮(客户端JS渲染,服务器端渲染,详见7.3)
三、实现搜索联想(输入框onchange,ajax请求搜索,取10条在层上展示方可)
四、实现词库管理(仅需管理scws下的自定义词库dd.txt即可)
五、实现全文搜索(提供了两种方案,详见8)

案例:
本文第五部分,针对实际应用场景,典型案例分析。

软件:
sphinx: sphinx-2.0.2-beta
scws: scws-1.2.0
===========================================================================

一、Sphinx安装
1、安装

2、配置
见sphinx.conf
详见下文,多索引增量索引方案

3、php 扩展
性能方面,扩展和直接使用API文件,差别不大;可以做选择;都在源码API中;
个人建议使用API文件,系统更稳定

3.1 sphinx客户端libsphinxclient

3.2 扩展
下载 http://pecl.php.net/package/sphinx

使用手册
http://docs.php.net/manual/zh/book.sphinx.php

4、索引 启动服务

二、php 分词 scws
官网 http://www.ftphp.com/scws/
1、 安装

2、 词库
scws-dict-chs-utf8.tar.bz2 解压放入 /opt/server/scws/etc
词库 dict.utf-8.xdb
规则 rules.utf-8.ini

3、 php 扩展
源码在phpext下

4、 分词测试
http://www.ftphp.com/scws/docs.php
详见测试文件 test_all.php

三、 索引

1、 增量索引方案

索引策略
1、搜索时,同时从主索引和增量索引取数据
2、每5分钟,运行一次增量索引;满足新数据搜索需求
3、每晚,运行一次主索引,同时会更新索引标示;再运行增量索引,实质为清空增量索引,避免与主索引重复索引
4、好处:避免开合并索引,合并索引效率较差
5、如数据量特别大,可考虑合并索引的方案

索引策略shell

四、 多个表独立索引方案
场景:如有用户搜索、商品搜索等多个索引需求
策略:配置一个多索引方案,每个表单独建立索引
前端根据不同类型选择不同的查询索引;全部,即选择所有索引
===========================================================================

五、性能及应用场景总结
1、基础数据、假如我们是一家商城;有用户user,商品goods,以及增量索引计数表search_counter。

2、编写配置文件 sphinx.conf

3、索引,启动服务

4、索引方案
索引策略
1、搜索时,同时从主索引和增量索引取数据
2、每5分钟,运行一次增量索引;满足新数据搜索需求
3、不同表的索引,分别执行方可
4、每晚,运行一次主索引,同时会更新索引标示;再运行增量索引,实质为清空增量索引,避免与主索引重复索引
5、好处:避免开合并索引,合并索引效率较差
6、如数据量特别大,可考虑合并索引的方案

索引策略shell

5、测试程序

5.1 加入用户信息测试

5.2 类别商品 多个关键字对比

6、小结
通过分词 和 采用 SPH_MATCH_EXTENDED (Sphinx内部查询语言的表达式) 模式;
能获取较好的搜索结果,排序和权值都是比较理想的。

7、优化扩展
7.1
如访问量较大,可将分词结果添加一层memecache,避免每次调用分词接口。

7.2
本文的的准实时索引,只对新增数据有效,如修改了老数据的内容则不能及时索引。
补充方案:(基于性能,不推荐)
7.2.1 全文重新索引
7.2.1在启一个索引为 updategoods,当数据发生改变时候,将来变化数据ID存如数据库,动态读取更新;
定时将更新的数据merge到主索引

7.3 词语高亮
利用API,SphinxClient::buildExcerpts可实现对关键词加入标签高亮

$opts 可实现对索引ID,搜索出的详情数组;进行匹配处理,得出理想的搜索结果。具体参数,见PHP手册。

8、全文搜索
由于sphinx索引ID唯一的问题,跨表的全文搜索不能直接实现;即,不能简单通过查询多个索引而获得结果;
不过通过如下方式,亦可实现全文搜索。

方案A
可在索引时对每个表的ID进行处理;
如:SELECT (id+1000000) AS id,name,price FROM goods;
在提供外部使用时,根据规则(如:ID > 1000000 为商品类)还原相应ID即可。

方案B
将数据来源存储为一个属性,将类比在属性中返回;获得的结果集中,可通过source_id进行类别区分了;如下:

转自:http://www.wubiao.info/314