百万商品大数据下的类目树优化实战经验分享



大家好,我是小米,今年 31 岁,一个喜欢写代码、讲故事、分享技术的程序员。最近我们商城要做一个大升级:在商品列表的左侧,加一个 商品类目树

说起来,可能你觉得类目树很常见,淘宝、京东、拼多多都有,点开左侧的"手机数码"、"服饰鞋包"、"家用电器",右边商品就会动态刷新。但真正自己去做的时候,才发现这背后其实是个大坑:

  • 商品数据量大,几百万级别;
  • 类目树要展示每个节点下的商品数量,还要能实时变化;
  • 用户在筛选条件下(比如品牌、价格区间)点击类目,商品数也要立刻跟着刷新。

一句话:既要快,又要准,还要实时!

于是,我们决定用 Spring + Elasticsearch 的聚合 来搞定。接下来,我就带大家走一遍我们的踩坑之旅和最终的技术方案。

最初的想法:MySQL + group by

一开始,需求刚提出来,我们的直觉是:

既然要统计类目下的商品数,那用 MySQL group by 不就行了?

比如下面这条 SQL:

乍一看没问题,但当我们实际跑到线上时,MySQL 就直接跪了:

  • 我们的商品表有几百万条数据,每次查询要扫全表;
  • 用户还可能加上品牌、价格区间、关键字等条件;
  • 一旦有多个并发请求,数据库直接爆炸。

于是,方案一票否决。

为什么是 Elasticsearch

我们换个思路。既然要做实时统计和聚合,那 Elasticsearch 正好是擅长的领域:

  • 倒排索引:查询速度快;
  • 聚合(Aggregation) :专门干统计分析的活;
  • 水平扩展:数据量大也能 hold 住。

所以,最终我们决定用 Spring Boot + Elasticsearch 来做。

类目树的数据结构

在讲技术实现之前,先聊聊类目树的数据长什么样。

比如我们的商城类目结构:

  • 手机数码
    • 手机通讯
      • 智能手机
      • 老年机
    • 笔记本电脑
  • 家用电器
    • 冰箱
    • 洗衣机

每个节点都要展示:

  • 类目名称
  • 商品数量(动态计算)

所以,我们需要在 Elasticsearch 里把商品的类目信息存进去。一般存法是:

这里的 category_path 非常关键,它表示商品所在的完整类目路径。这样我们才能按父级类目统计商品数。

Elasticsearch 的聚合查询

接下来就是重头戏:如何统计类目下的商品数。

我们用的是 Terms Aggregation。比如,统计一级类目的商品数,可以这样写:

这个查询的意思是:按 category_path 聚合,统计每个类目下的商品数量。

如果要结合搜索条件,比如用户搜了"iPhone",就可以直接加上:

这样,返回结果里就是:

  • 各个类目下 iPhone 的数量;
  • 用户再点选类目时,右侧商品列表和左侧数量能保持一致。

Spring Boot 集成 Elasticsearch

聊完了原理,我们来点代码。我们用的是 Spring Data Elasticsearch。

1. 配置依赖

2. 定义实体类

3. 编写聚合查询

这样,我们就能实时拿到每个类目下的商品数了。

性能优化

当然,实际做的时候我们也遇到不少问题。

1. 类目层级太深

如果类目有三级甚至四级,直接聚合会很慢。我们用了 子聚合(Sub Aggregation) 来做。

这样可以逐级展开,性能会好很多。

2. 热点类目查询太频繁

比如"手机数码"点击太多,我们加了一层 缓存

  • 短期内同样的查询直接走 Redis;
  • 后台有定时任务刷新数据。

3. 分片 & 副本优化

Elasticsearch 的分片数我们按数据量调优,确保查询分布均匀,避免单点热点。

上线后的效果

类目树功能上线后,用户体验大大提升:

  • 点开"手机数码",能秒级展示数量;
  • 搜索条件变化时,左侧数量实时刷新;
  • 后端 QPS 从原来的几百压到几千,Elasticsearch 扛住了。

而且,最让我自豪的是,之前大家觉得"类目树就是个 UI 样式",现在都觉得背后是门学问,哈哈。

总结

这次的类目树项目,我学到几点:

  • 需求再小,背后都有大学问。一个小小的类目树,其实牵扯到搜索、聚合、性能优化。
  • 选对技术栈很重要。如果我们还死磕 MySQL,估计项目早黄了。
  • 实战是最好的学习。写博客讲出来,也算是对自己知识的一次梳理。

如果你们的项目里,也有类似的 "实时统计"、"大数据聚合" 需求,Elasticsearch 一定要学会。

END

以上就是小米今天的分享。希望能帮到你们,如果你们在做类目树或者 Elasticsearch 聚合时遇到坑,欢迎留言交流!

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!

相关推荐
就是帅我不改4 小时前
面试官:单点登录怎么实现?我:你猜我头发怎么没的!
后端·面试·程序员
JunIce4 小时前
NestJs Typeorm `crypto is not defined`
后端
xin猿意码4 小时前
听说你会架构设计,来,弄一个短视频系统
后端
Lethehong4 小时前
飞算JavaAI炫技赛:一天完成学生成绩综合统计分析系统开发(含源码)
java·java开发·飞算java炫技赛
缘来小哥4 小时前
【Cygwin】不用装Linux系统,使用Cygwin让Windows秒变类Unix工作台
linux·后端
这里有鱼汤4 小时前
牛市下,到底该买上涨趋势还是下跌趋势的股票?
后端
何故染尘優4 小时前
限流、降级、熔断的区别和应用场景
java·服务器·网络
xiaoye20184 小时前
虚拟线程实现分析
java