PHP 运用 Redis 构建高性能的实时搜索

来源:互联网 发布:apache beam 实时流 编辑:程序博客网 时间:2024/06/07 06:00

需求

  • 能够在键盘输入的瞬间响应搜索结果;
  • 不需要太复杂的查询,单个字段作为搜索条件;
  • 分词、模糊匹配;
  • 实时更新;

一、安装Redis

wget http://dl.fedoraproject.org/pub/epel/7/x86_64/r/redis-3.2.3-1.el7.x86_64.rpmrpm -ivh redis-3.2.3-1.el7.x86_64.rpmsystemctl start redis

出现 libjemalloc.so.1()(64bit) 被 redis-3.2.3-1.el7.x86_64 需要, 默认用jemalloc管理内存

wget http://dl.fedoraproject.org/pub/epel/7/x86_64/j/jemalloc-3.6.0-1.el7.x86_64.rpmrpm -ivh jemalloc-3.6.0-1.el7.x86_64.rpm

外网访问

vim /etc/redis.conf # 取消 bind 127.0.0.1  修改 protected-mode no

二、PHP程序实现(基于laravel5.1)

1. 基础表数据
CREATE TABLE `article` (  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,  `title` varchar(100) DEFAULT NULL,  `score` int(10) unsigned DEFAULT '0',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2. PHP 分词程序 SCWS
wget http://www.xunsearch.com/scws/down/scws-1.2.3.tar.bz2tar xvjf scws-1.2.3.tar.bz2    # 如果缺少bzip2 请 yum install bzip2cd scws-1.2.3./configure --prefix=/usr/local/scwsmakemake install# 下载字典cd /usr/local/scws/etcwget http://www.xunsearch.com/scws/down/scws-dict-chs-gbk.tar.bz2wget http://www.xunsearch.com/scws/down/scws-dict-chs-utf8.tar.bz2tar xvjf scws-dict-chs-gbk.tar.bz2tar xvjf scws-dict-chs-utf8.tar.bz2# 安装PHP扩展cd scws-1.2.3  # 下载目录打开phpize./configure --with-scws=/usr/local/scws  # 若 PHP 安装在特殊目录, 则请在 configure 后加上 --with-php-config=$php_prefix/bin/php-configmakemake install# php.ini 配置[scws]extension = scws.soscws.default.charset = utf8scws.default.fpath = /usr/local/scws/etc# 注意请检查 php.ini 中的 extension_dir 的设定值是否正确, 否则请将 extension_dir 设为空,# 再把 extension = scws.so 指定绝对路径。
3. laravel 安装 predis 包
composer require "predis/predis:1.0.*"
4. 基础 models
namespace App\Models;use Illuminate\Database\Eloquent\Model;class Article extends Model{    protected $table = 'article';    public $timestamps = false;}
5. 数据添加时建立索引
use App\Models\Article;$server = [    'scheme' => 'tcp',    'host'   => '127.0.0.1',    'port'   => 6379,];$redisClient = new \Predis\Client($server);Article::created(function ($article) use ($redisClient) {    $so = scws_new();    $so->send_text($article->title);    while ($tmp = $so->get_result()) {        foreach ($tmp as $value) {            $redisClient->sadd('search:key:'.$value['word'], $article->id);            $redisClient->set('search:score:'.$article->id, $article->score);            $redisClient->hmset('search:data', [$article->id => $article->title]);        }    }    $so->close();});
6. 数据删除时删除索引
Article::deleted(function ($article) use ($redisClient) {    $so = scws_new();    $so->send_text($article->title);    while ($tmp = $so->get_result()) {        foreach ($tmp as $value) {            $redisClient->srem('search:key:'.$value['word'], $article->id);            $redisClient->del('search:score:'.$article->id);            $redisClient->hdel('search:data', $article->id);         }    }    $so->close();});
7. 数据修改时自己改吧!!!
8. 数据搜索实现
namespace App\Http\Controllers;use Illuminate\Http\Request;class SearchController extends Controller{    public function index(Request $request)    {        $server = [            'scheme' => 'tcp',            'host'   => '127.0.0.1',            'port'   => 6379,        ];        $redisClient = new \Predis\Client($server);        $key = 'search:key:';        $title = $request->input('title');         $so = scws_new();        $so->send_text($title);        while ($tmp = $so->get_result()) {            foreach ($tmp as $value) {                $aTitle[] = $key . $value['word'];                $aTitleVal[] = $value['word'];            }        }        $so->close();        if (isset($aTitle)) {            $mergeKey = 'search:key:' . implode('+', $aTitleVal);            $redisClient->sinterstore($mergeKey, $aTitle);            $interstore = $redisClient->sort($mergeKey, ['BY' => 'search:score:*', 'sort' => 'desc']);            $result = $redisClient->hmget('search:data', $interstore);            print_r($result);        }    }}
原创粉丝点击