Appearance
商城检索服务和 ES 同步链路怎么做
先说结论
- MySQL 仍然是商品主数据源,ES 负责搜索和筛选,不要反过来
- 商品变更优先走异步同步链路,不要在写商品事务里强依赖 ES
- 同步链路必须支持幂等、重放、补数和全量重建,否则后面越用越难维护
一、先把三层角色拆开
1. 商品中心
负责维护商品主数据,比如标题、价格、品牌、类目、上下架状态。
2. 搜索服务
负责搜索接口、筛选、排序、聚合、搜索兜底和索引版本切换。
3. 同步链路
负责把商品变更可靠地送到 ES,并提供失败补偿和数据校准能力。
二、为什么不要同步写 ES
最容易踩的坑是:商品服务更新数据库后,立刻同步请求 ES。
这样做短期看起来简单,但问题很多:
- ES 抖动会拖慢商品写链路
- 商品事务和索引写入耦合过深
- 一旦部分成功、部分失败,很难补偿
- 后面做批量导入和全量重建时很难扩展
更稳的方式通常是:
- 商品中心提交本地事务。
- 通过 outbox、binlog 或消息把变更事件发出去。
- 搜索索引消费端异步写 ES。
三、商品索引建议怎么建
商品索引通常会拆成:
- 基础搜索字段:标题、品牌、类目、规格词
- 过滤字段:价格区间、库存状态、上下架状态、店铺状态
- 排序字段:销量、时间、热度、价格
- 展示字段:图片、卖点、标签
不要把数据库每一个字段都原样搬过去。
ES 文档更像“为搜索场景裁剪后的搜索视图”。
四、同步链路至少要具备四个能力
1. 幂等写入
同一商品重复消费多次不能造成索引状态混乱。
2. 顺序控制
商品先上架后改价,和先改价后上架,最终状态不能错。
如果顺序可能乱,就要用版本号或更新时间兜底。
3. 补数能力
消息丢了、消费失败了、索引写坏了,都要能按商品 ID、时间段、店铺维度重放。
4. 全量重建能力
索引 mapping 变化、分词策略变化或字段结构升级时,不能只靠增量同步顶过去。
五、线上最常见的几个坑
1. 商品改动同步太碎
商品基础信息、价格、库存、上下架分别从不同链路打 ES,最后一个商品状态常常对不上。
2. 搜索结果和详情页价格不一致
这是因为 ES 里的价格是异步同步的,真正成交仍应以商品中心和结算链路为准。
所以详情页和下单页都要有最终校验。
3. 索引变更没有灰度方案
mapping 改了就直接覆盖,线上很容易出现查询兼容问题。更稳的做法是新索引写入、校验后再切 alias。
4. 只做增量,不做对账
消息链路再稳,也不能假设永远零丢失。搜索类系统最好定期做增量校验或全量对账。
总结
商城检索服务的核心不是“把数据库同步到 ES”这么简单,而是把主数据、搜索视图和同步链路三层职责拆清楚。数据库管真相,ES 管查询体验,同步链路负责可靠搬运,这样系统才好扩展也好排障。