将sphinx配置为更好的实时搜索引擎

本文基于sphinx 2.2.11。


sphinx以它的简单、快速吸引着我。但它的plain增量索引有两大问题一直困扰着我:

一是增量索引只能定时创建,必须会造成数据到主索引时存在一个时间差,而且经测试,增量索引merge到主索引时还经常会被阻塞一段时间(--rotate);

二是在增量索引中无法对字符串属性进行修改UPDATE,所以发布的物品修改了名称就甭想搜索到了。


sphinx也实现了一个rt(实时)索引,可以在生产环境中使用。但是,它也有几个缺点:

1. 搜索性能差很多,见下图:


红色为rt索引,蓝色为plain索引。主要差距来自于rt实时索引在超出rt_mem_limit 之后就会将内存中的内容RAM CHUNK写入磁盘块DISK CHUNK,当多次写入磁盘块后,每次搜索的结果都需要从多个磁盘块中读取,然后再合并结果。当然这可以通过加大rt_mem_limit来解决:


2. 如果加大了rt_mem_limit,那么rt索引会在内存中保留大量数据,为了从崩溃中恢复,可能需要flush加binlog获取更好的恢复效果,然而大数据量flush时会有些卡顿。

3. 高频的DELETE/REPLACE会引起碎片,当然可以用OPTIMIZE命令来整理。

searching

但OPTIMIZE不但需要大量IO,也需要大量CPU时间,因为它需要读取多个CHUNK,然后再合并结果。

4. 一旦修改了数据库表结构,那要修改rt索引中的数据也是比较麻烦的,需要手工修改。


综上所述,纯使用sphinx的rt索引还是比较娇贵的。我一直想把rt索引的实时和可修改字符串优势与plain索引的快速创建优势结合起来,经过不断查看官方文档,我找到了一个兼顾两者优点的方案。


简而言之就是:创一个每日定时任务,在夜里创建全量plain索引,然后将全量索引TRUNCATE,同时将plain索引ATTACH 到rt实时索引,随后只在rt索引中搜索和修改(在修改DB中的数据后)。


这样做的优点我们最后来看。下面先用实例来演示一遍---------------:

假设我们有一个求购表,叫ask_buy,简化的表结构为:

CREATE TABLE `ask_buy` (
	`id` INT(11) NOT NULL AUTO_INCREMENT,
	`title` VARCHAR(200) NOT NULL,
	`deleted` TINYINT(1) NOT NULL DEFAULT '0',
	PRIMARY KEY (`id`),
)
COMMENT='求购'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;

首先我们创建一个全量plain索引(片断):

source ask_buy_src
{
        type			= mysql

	sql_host		= localhost
	sql_user		= root
	sql_pass		= root
	sql_db			= taoquan
	sql_port		= 3306	# optional, default is 3306

	sql_query_pre		= SET NAMES utf8
	sql_query_pre           = SET SESSION query_cache_type=OFF
	
	sql_query		= SELECT id, title, deleted FROM t_ask_buy
  
        sql_attr_uint    = deleted
	sql_field_string = title
	sql_query_post_index	= REPLACE INTO search_counter SELECT 'ask_buy',MAX(id) FROM ask_buy
	
	sql_ranged_throttle	= 0
}

index ask_buy
{
        type			= plain
	source			= ask_buy_src

	path			= /usr/local/sphinx/data/ask_buy
	docinfo			= extern
        dict			= keywords
	mlock			= 0
	morphology		= none
	min_word_len		= 1

	ngram_len		= 1
	ngram_chars		= U+3000..U+2FA1F
	html_strip		= 0
}

index rt_ask_buy
{  
    type            = rt  
    path            = /usr/local/sphinx/var/data/rt_ask_buy
    rt_mem_limit        = 512M  
    rt_field            = title  
    rt_attr_uint        = deleted  
} 


然后创建一个脚本index.sh来创建plain全量索引并ATTACH到rt索引:

#!/bin/bash
/usr/local/sphinx/bin/indexer goods --rotate --all >> /usr/local/sphinx/var/log/index_rt.log
mysql -P 9306 -h 127.0.0.1 -e"TRUNCATE RTINDEX rt_ask_buy;ATTACH INDEX ask_buy TO RTINDEX rt_ask_buy;"

然后在每天夜里2点30创建:

30 2 * * * sudo ~/index.sh

最后来检验结果了:

优点:

1. 这样rt索引就无需定期flush到磁盘,因为即便它丢失了也可以直接进行重建,而且重建后还没有碎片。

2. 还测试了,如果修改了表结构,只要修改sphinx配置文件,然后重启searchd进程,最后再执行index.sh即可。

3. 如果sphinx崩溃,只需要再执行index.sh即可,无需从binlog或dump中恢复到rt索引,直接从数据源重建索引的速度是很快的:

insert

4. 这种方案的检索速度比plain方案相当,因为全量索引的DISK CHUNK只有一个,而只要rt_mem_limit设置合理,每天新增的DISK CHUNK也不会很多,这样在一两个CHUNK之间合并,速度只比纯plain方案略低。参考下图的2048M(5+1),重点不在2048M,而在后面的5+1,即5个DISK CHUNK+1个RAM CHUNK。

searching

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值