Skip to content

🎤 面试官:你做过购物车功能吧?说说你们是怎么实现的?

: 做过,我们平台的购物车其实分两种情况:

  • 一种是没登录的时候,你想逛逛、先加个商品看看;
  • 一种是登录之后,要把你之前加的东西合并进来,还能跨设备同步。

所以我们是“前端存一部分,后端存一部分”,两边配合着来。


🎤 面试官:没登录的时候,购物车存哪儿?

: 存浏览器里,用 localStorage

比如用户打开网页,点了“加入购物车”,我们就往 localStorage 里写一条:

json
{ "productId": 1001, "count": 2 }

这样就算他关了浏览器再进来,东西还在。

但有个问题——换手机、换浏览器就没了,毕竟数据只在本地。 所以我们一直提醒用户:“登录后购物车更安全”。


🎤 面试官:那登录之后呢?怎么把本地的和服务器的合并?

: 这是个挺常见的场景,我们是这么处理的:

用户一登录,前端就把 localStorage 里的购物车数据发给后端,比如:

json
[{ "productId": 1001, "count": 2 }]

后端收到后,做三件事:

  1. 查 Redis:看这个用户的购物车里有没有这个商品;
  2. 去重 + 数量叠加:比如 Redis 里已经有 1001:1,本地又加了 1001:2,那就变成 3
  3. 保存到 Redis,同时清掉 localStorage

这样就完成了“本地购物车 → 云端同步”。

而且这个过程对用户是无感的,他登录完刷新一下页面,发现之前加的东西都在,体验就很好。


🎤 面试官:购物车数据存在 Redis,那 Redis 挂了怎么办?

: 确实怕,但我们也没啥特别高大上的办法,主要是靠“兜底 + 告警”。

  • Redis 我们用的是主从 + 哨兵,挂一台机器能自动切,一般小故障扛得住;
  • 如果整个 Redis 集群崩了(比如机房断电),那确实购物车数据会丢;
  • 但我们做了个降级方案:
    • 临时把购物车读写切到数据库(MySQL),虽然慢点,但能用;
    • 同时发告警,运维赶紧救火;
  • 等 Redis 恢复了,再把数据库里的数据同步回去。

说白了,Redis 不是数据库,我们不指望它 100% 不丢数据,但要有应对预案。


🎤 面试官:购物车里的商品价格变了,或者库存没了,怎么处理?

: 这个太常见了,尤其是大促的时候,价格调来调去,库存一会儿有、一会儿没。

我们的做法是:

  • 购物车里存的是快照信息,不是实时数据。 比如你加商品时价格是 99,哪怕后来涨到 199,购物车里还是显示 99;
  • 下单的时候必须重新校验! 不能说“我加的时候是 99,现在就得按 99 卖”,那商家就亏死了。

所以下单时我们会:

  1. 查最新价格 —— 如果变了,弹个提示:“亲,价格有调整,是否继续?”
  2. 查库存 —— 如果没货了,直接提示“该商品已售罄,无法下单”

说白了:购物车可以“骗人”,但下单必须真实


🎤 面试官:购物车怎么支持批量操作?比如全选、删多个?

: 我们后端提供了几个接口:

  • GET /cart:拉整个购物车
  • POST /cart/add:加商品
  • POST /cart/update:改数量
  • POST /cart/delete:支持传多个商品 ID,批量删
  • POST /cart/empty:清空

前端点“全选删除”,就调 delete 接口,传个数组 [1001, 1002, 1003]

后端用 Redis 的 HDEL cart:12345 1001 1002 1003 一条命令搞定,很快。

而且我们还加了个“最近删除”功能,删了的东西保留 5 分钟,可以一键恢复,防止手滑。


🎤 面试官:购物车数据量大了会不会慢?怎么优化?

: 确实会,尤其是有些用户往购物车里加了几百个商品,一进页面卡半天。

我们做了几个优化:

  1. 分页加载:不一口气拉全部,先加载前 20 个,用户往下拉再加载;
  2. 商品信息缓存:购物车里只存 商品ID + 数量,商品标题、图片、价格这些从 Redis 缓存里批量查,避免反复查数据库;
  3. 过期策略:设置 cart:userId 过期时间 30 天,用户 30 天没登录,自动清理,省资源;
  4. 本地缓存加速:用 Caffeine 缓存热点用户的购物车,减少 Redis 访问。

现在平均响应时间在 100ms 以内,基本感觉不到卡。


🎤 面试官:有没有遇到过什么坑?

: 有啊,最惨一次是——

我们一开始用 Redis 的 HGETALL 把整个购物车拿出来,然后在 Java 里遍历改数据,再 HSET 写回去。

结果有个用户加了 800 多个商品……每次一访问购物车,Redis 直接被打满,CPU 100%,整个系统卡住。

后来我们改了:

  • 改成用 HINCRBY 直接在 Redis 里加数量;
  • 删商品用 HDEL 传多个 key;
  • 能在 Redis 里做的操作,绝不拉到 Java 里算。