PHP结合Elasticsearch与MySQL实现搜索分离架构的完整方案,重点解决数据同步问题
以下是PHP结合Elasticsearch与MySQL实现搜索分离架构的完整方案,重点解决数据同步问题: 一、架构设计原则- 读写分离
- MySQL作为主数据库处理增删改操作(CRUD)
- Elasticsearch仅用于搜索(Search)
- 数据流向
MySQL数据变更 → 触发同步机制 → Elasticsearch索引更新 - 同步策略
- 定时任务增量同步(适用于中小规模数据)
- 实时监听MySQL binlog(高实时性要求)
二、核心实现步骤1. 环境配置
- // 安装Elasticsearch-PHP客户端
- composer require elasticsearch/elasticsearch
复制代码- MySQL需开启binlog(若选择实时同步)
- Elasticsearch需安装IK分词插件(中文搜索优化)
2. 数据同步方案对比[td]方案 | 实现方式 | 延迟 | 适用场景 | 定时任务同步 | 通过PHP脚本定期扫描MySQL | 分钟级 | 数据变更不频繁 | 触发器+消息队列 | MySQL触发器通知队列消费 | 秒级 | 中等规模系统 | Binlog监听 | 使用Canal/Maxwell监听变更 | 毫秒级 | 高实时性要求系统 | 3. 推荐实现代码(定时任务方案)
sync_mysql_to_es.php
- <?php
- require 'vendor/autoload.php';
- use Elasticsearch\ClientBuilder;
- // 初始化客户端
- $es = ClientBuilder::create()->setHosts(['localhost:9200'])->build();
- $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'password');
- // 获取上次同步时间(需持久化存储)
- $lastSyncTime = file_get_contents('last_sync.txt') ?: '1970-01-01';
- // 查询MySQL变更数据
- $stmt = $pdo->prepare("SELECT * FROM products WHERE updated_at > ?");
- $stmt->execute([$lastSyncTime]);
- $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
- // 同步到Elasticsearch
- foreach ($rows as $row) {
- $params = [
- 'index' => 'products',
- 'id' => $row['id'],
- 'body' => $row
- ];
- $es->index($params);
- }
- // 更新同步时间
- file_put_contents('last_sync.txt', date('Y-m-d H:i:s'));
复制代码需配置cronjob定期执行此脚本,例如每5分钟一次 三、关键问题解决方案- 数据一致性保障
- 失败重试机制:记录同步失败记录并重试
- 差异对比校验:定期全量对比MySQL与ES数据
- 性能优化
- 批量操作:使用Elasticsearch的bulk API提升同步效率
- 索引优化:合理设置分片数和副本数
四、典型应用场景示例商品搜索实现
- // 搜索接口示例
- $params = [
- 'index' => 'products',
- 'body' => [
- 'query' => [
- 'multi_match' => [
- 'query' => $_GET['q'],
- 'fields' => ['name^3', 'description'] // 权重设置
- ]
- ]
- ]
- ];
- $results = $es->search($params);
复制代码
- MySQL负责商品管理后台的增删改
- Elasticsearch提供前台搜索服务
五、监控与维护建议- 监控指标
- 灾备方案
- 定期备份ES索引快照
- 搭建MySQL从库避免单点故障
该方案通过松耦合设计,既保留了MySQL的事务特性,又利用Elasticsearch实现了高性能搜索,适合大多数Web应用场景。实际部署时需根据数据量和实时性要求选择合适的同步策略。
|