ES电商检索方案设计案例
一、整体检索方案选型
1. 为什么不能只用 MySQL 检索
- 多规格筛选:颜色、尺寸、配置组合查询,MySQL 字符串匹配 / 联表查询极慢;
- 模糊搜索:商品标题、详情、参数全文匹配,MySQL like % xx% 不走索引;
- 多条件组合筛选:分类 + 品牌 + 价格区间 + 多个规格值 + 属性参数混合过滤;
- 排序加权:销量、价格、匹配度、新品综合排序;
- 分页、高亮、同义词、拼音搜索、分词能力数据库原生不支持。
标准架构:MySQL 存业务源数据,Elasticsearch 做商品检索引擎
MySQL 负责增删改、库存、订单、事务;ES 承接所有前台商品列表、搜索、筛选。
2. 数据同步两种主流方案
方案 1:Canal binlog 实时同步(生产最常用)
- MySQL 开启 binlog=ROW;
- Canal 监听 MySQL binlog,捕获 spu/sku/spec/attr 增、改、删事件;
- Canal 把变更数据推送至 MQ (RocketMQ/Kafka);
- 消费服务拉取消息,组装完整商品文档,写入 / 更新 ES 索引;
- 延迟极低(几十 ms 级),准实时检索。
方案 2:定时全量 + 增量补偿(小型商城)
- 凌晨全量一次性把所有 SPU、关联 SKU、规格、属性查出来批量灌入 ES;
- 业务更新时,代码里同步调用 ES 更新接口(双写);
- 定时增量任务每 5 分钟比对更新时间戳,补发遗漏数据;
缺点:有代码侵入,容易出现 MySQL 与 ES 数据不一致。
二、ES 索引文档结构设计(扁平化大文档,一次查询全带出)
不拆多个 ES 索引,一个 spu 对应一个 ES 文档,把所有关联数据平铺嵌入 JSON,避免 ES 多表 Join(ES 不擅长关联)。
索引名:goods_spu_index
|
json |
字段类型关键配置
- spuName、searchContent:text 类型,ik 分词器,支持模糊全文检索;
- brandId、categoryId、status:keyword 精确匹配;
- minSalePrice、marketPrice:double,区间范围筛选;
- allSpecValues、specCombine:keyword,规格多选过滤;
- attrList.attrName/attrValue:嵌套 nested 类型,用于参数精准筛选;
- skuList:nested 嵌套结构,可过滤有库存、价格区间 SKU。
三、常见商城检索场景 ES DSL 实现
场景 1:关键词模糊搜索(首页搜索框)
输入:苹果手机黑色
|
json |
场景 2:分类 + 品牌 + 价格区间基础筛选
分类 = 手机,品牌 = Apple,售价 4000~6000
|
json |
场景 3:规格多选筛选(核心难点)
筛选:内存 = 256G + 颜色 = 黑色
利用allSpecValues多关键词同时命中文档:
|
json |
|
精准匹配 SKU 存在该组合:如需严格校验组合存在,改用 nested 查 skuList 内 specCombine。 |
场景 4:公共属性筛选
筛选:适配车型 = 享道 E7
attrList 是 nested 嵌套,必须嵌套查询:
|
json |
场景 5:只展示有库存的商品
过滤 skuList 里任意 sku 库存 > 0:
|
json |
四、同步更新逻辑(增 / 改 / 删)
- 新增 SPU
MySQL 插入 spu、sku、spec、attr → Canal 捕获 binlog → 组装完整大文档 → ES index 创建文档。 - 修改 SPU 基础信息(标题、图片、详情)
局部更新 ES 对应字段,使用_update部分更新,不用全量覆盖。 - 修改 SKU 价格 / 库存
只更新 ES 内 skuList 数组对应 sku 节点;库存高频变动场景:可 MQ 高频小粒度更新,不会重建整个文档。 - 新增 / 修改规格、属性
重新拉取该 SPU 全部关联数据,全量覆盖更新整条 ES 文档(单 SPU 数据量很小,性能无压力)。 - 商品下架删除
逻辑删除优先:status 置 0,ES 过滤直接屏蔽;物理删除执行 ES delete。
五、大小两套架构适配
1)小型内部商城(轻量)
- 不用 Canal,业务代码双写 MySQL+ES;
- 每日一次全量重刷兜底一致性;
- ES 单节点即可,文档量几万以内毫无压力。
2)C 端公域大电商(高并发百万商品)
- Canal + Kafka 解耦同步,削峰填谷;
- ES 集群 3 节点以上,分片合理拆分;
- 冷热分离:新品热分片、滞销老商品冷分片;
- 增加搜索限流、结果缓存(Redis 缓存热门搜索页);
- 定时一致性校验任务:对比 MySQL 统计值与 ES 数量,修复差异数据。
六、避坑关键点
- 禁止 ES 做事务、库存扣减
库存、下单、价格锁定必须以 MySQL 为准,ES 只做展示检索;库存变动 ES 仅做同步展示用。 - 文档扁平化,杜绝多索引关联查询
ES Join 性能极差,把所有子数据内嵌到 SPU 主文档是行业标准写法。 - nested 嵌套不宜过深
skuList、attrList 两层嵌套足够,层级越多查询性能越低。 - 分词器统一用 IK-Analyzer
中文商品名称、搜索词必备,自带热词可扩展品牌、车型自定义词库。 - 不要实时依赖 ES 做精确库存判断
用户下单前页面展示库存看 ES,下单扣减锁库存严格走 MySQL。
更多推荐




所有评论(0)