面灵AI

上海某公司后端面试:Spring、消息可靠性与秒杀库存

base
上海
时间
2026-09
来源
牛客网

《面试题目》

  1. 如何介绍自己的技术背景,做过哪些项目?
  2. 项目前端使用了什么技术?
  3. GET 与 POST 有什么区别?
  4. 如何设计用户登录状态的判断?
  5. 用户密码能否以明文保存,应该怎样处理?
  6. Spring 的核心是什么,怎样理解 IoC 和 DI?
  7. Spring 与 Spring Boot 有什么区别?
  8. Bean 有哪些作用域,Spring MVC 中的 Bean 默认是单例吗?
  9. Bean 的生命周期有哪些主要阶段?
  10. 常用的两种代理方式是什么?
  11. AOP 有哪些通知类型?
  12. 秒杀抢徽章功能怎样保证不会超额发放?
  13. RabbitMQ 有哪些关键机制,消息怎样从生产者到达消费者?
  14. 项目中是否遇到消息丢失,怎样定位和解决?
  15. 为什么在项目里选择 Bitmap?
  16. 第二个项目怎样在网关实现统一鉴权?
  17. 常用的 Linux 命令有哪些?
  18. MySQL 有哪些事务隔离级别?
  19. 除 MySQL 外,还了解哪些国产数据库?
  20. Java 常用集合和数据结构有哪些?
  21. Java 面向对象的三大特性是什么,怎样理解?
  22. 使用过哪些 Java 版本,了解哪些新特性?
  23. 编写项目时,辅助编程工具参与了哪些工作,占比如何?

《参考解析》

IoC 讲对象由谁管理,DI 讲依赖怎样交给它

容器负责创建、装配和管理对象,业务对象通过构造器等方式接收依赖,不必在内部把所有依赖都直接创建出来。Spring Boot 在 Spring 的基础上提供自动配置和配套依赖组织等能力,减少常见应用的启动配置工作。

单例是 Spring Bean 的默认作用域,其边界是容器内的一份 Bean 定义。Web 环境还可以使用 request、session 等作用域。Controller 通常也是单例,把某次请求的数据放进可变实例字段会造成并发干扰;方法局部变量与每个请求独立的数据对象更合适。参见 Spring Bean 作用域

库存判断和扣减要作为一个整体

“先读剩余数量,再单独扣减”会让多个请求同时看到库存充足。使用数据库时,可以把条件写进更新语句,只在库存大于零时扣减,并检查受影响行数。还要为领取记录设置合适的唯一约束,处理同一用户重复点击和请求重试。

如果先在 Redis 预扣,再异步落库,需要说明两边失败时如何恢复一致:预扣成功但消息没有发出、消息重投、落库失败,分别怎样处理。仅仅加一把锁,并不能自动解决这些情况。

消息丢失分发送、存储、消费三段看

生产者确认用于判断消息是否被 RabbitMQ 接收并承担责任,消费者确认则表示消费端已完成相应处理,两者互不替代。业务尚未写入成功就确认消费,会留下处理丢失的窗口;连接故障后的重发又可能形成重复消息,因此消费者必须考虑幂等。参见 RabbitMQ 确认机制

实际排查可以从一条业务消息的标识出发,依次查看发送记录、路由结果、队列状态和消费结果。持久化、队列副本与失败重试也需要匹配可靠性要求,而不是只看客户端调用有没有抛异常。

Bitmap 适合回答“有没有”

签到、是否领取等二值状态可以映射成一个个 bit,用少量空间表示大量状态。但要先说明用户标识如何映射到位置:编号极度稀疏时,直接把最大用户编号当偏移量会浪费空间。需要保存领取时间、次数或详细记录时,单个 bit 就不够,仍需其他结构配合。

网关认证后,资源权限仍要核对

网关可以统一检查会话或令牌的有效性,并把可信的用户身份传给后端。业务接口仍需判断这个用户是否有权操作当前订单、文件等资源。后端不能直接相信客户端传来的用户编号,也不能让客户端伪造的身份头绕过网关认证。