Java面试场景题:百万人同时点赞怎么办?回答千万别跑偏

大家发现了吧,现在面试八股文好像问的少了,反倒是场景题多了起来,毕竟现在AI如此强大,总揪着这点底层基础也没多大意思。

面试官张嘴闭嘴高并发、大数据量倒是真的,别管实际业务是不是高并发,但是你不会是进不来拧螺丝的。

就像之前有同学被问:“某音百万用户同时给一个视频点赞,让你来要怎么设计?”,这类题肯定见过吧。

咱们来简单拆解下这题,我是一个小学生,知识量有限,不喜勿喷。

这道题到底考察什么?

别上来就想用什么技术,先明确面试官的考察点,才能答到点子上:

  1. 高并发写入能力:百万人同时操作,瞬间 QPS 能冲到几十万,如何避免数据库被打垮?这是考察你对流量削峰的理解;

  2. 数据一致性:用户点赞后必须立刻看到 已赞 状态,点赞数可以有轻微延迟,但不能错、不能丢,这是对最终一致性的考察;

  3. 系统可用性:就算后端服务波动,用户点赞操作也得成功,不能出现点了没反应的情况,考察容错和降级思路;

  4. 资源优化:百万次请求直接怼数据库肯定不行,如何用缓存、消息队列等中间件减轻压力,考察技术选型能力。

换位思考

很多人一上来就纠结怎么让百万次点赞实时写入数据库,其实跑偏了。

咱们站在用户角度想:

  • 用户点击点赞后,最关心的是有没有点赞成功,而不是当前赞数到底是 10086 还是 10087

  • 赞数是给所有用户看的公共数据,轻微延迟用户完全感知不到(就算数据丢了,用户也很难发现,只是会想“咦”我之前点赞过一个视频没了,就没然后了);

  • 核心需求是:操作成功率 99% + 客户端状态实时反馈 + 赞数最终准确

想通这一点,方案就清晰了:把实时写入数据库的压力,转移到中间件上,用异步 + 缓存的思路解决高并发。

选取方案

咱们一步步拆解,从用户点击点赞按钮开始,整个流程是这样的:

1. 用户点赞:先写消息队列,客户端直接反馈成功

用户点击点赞的瞬间,客户端不会直接调用数据库接口,而是做两件事:

  • 向后端发送点赞请求,后端收到后,不操作数据库,直接把用户ID + 视频ID + 点赞状态(赞 / 取消赞)封装成一条消息,写入 Kafka;

  • Reids 记录 用户ID + 视频ID 的点赞状态,增加 视频ID 的赞数量

  • 只要消息成功写入 Kafka,后端就立刻返回点赞成功给前端,客户端马上显示已赞状态。

为啥选 Kafka 我就不说了。

2. 客户端:本地记录状态,避免重复点赞

客户端收到点赞成功后,除了显示已赞,还要在本地存储记录当前用户对该视频已点赞。

这样做的好处是:

  • 防止用户短时间内重复点击点赞,前端直接拦截,减少无效请求;

  • 就算后续缓存没更新,用户自己看到的状态也是准确的,不影响个人体验。

3. 查赞数:直接读 Redis,不用查数据库

其他用户查看视频时,需要显示赞数,这时候客户端会调用查询赞数接口,后端的处理逻辑是:

  • 不查数据库,直接从 Redis 里读取该视频的赞数缓存;

  • Redis 读性能极高,支持每秒几十万次查询,完全能扛住百万用户同时查看的压力;

  • 这里的赞数可能不是实时最新的,但只要延迟在可接受范围内,用户完全没感觉。

4. 后台任务:定时同步 Redis 和数据库,保证最终一致

这一步是兜底,负责把 Kafka 里的点赞消息处理掉,同时更新 Redis 和数据库:

  • 后端持续从 Kafka 里拉取点赞消息;

  • 启动一个定时任务,把 Redis 里所有视频的赞数,批量同步到数据库里;

  • 同步时要注意幂等性:比如用户先赞后取消,最终状态是未赞,避免重复计算导致赞数错误。

批量同步,攒一批数据(比如 1 万条)再批量更新,大大减少数据库的写入压力。

而且定时任务可以根据业务调整频率,比如高峰期每 1 分钟同步一次,低峰期每 10 分钟同步一次,灵活适配流量。

方案优势

这套方案没有复杂的架构,但的确能解决百万级点赞的高并发问题,核心优势在于几种中间件的组合使用:

  • 高可用:Kafka 保证消息不丢失,Redis 保证查询不卡顿,就算数据库暂时挂了,用户点赞和查赞数都不受影响;

  • 易扩展:如果后续点赞量涨到千万级,只需要增加 Kafka 的分区数、Redis 的集群节点,就能轻松扛住;

  • 低成本:不用复杂的分布式事务,不用实时计算框架,用最基础的中间件就能实现,开发和维护成本都低。

写在最后

其实很多高并发场景,比如点赞、评论、秒杀,核心思路都是异步解耦 + 缓存兜底。

面试官考察的不是你知道多少冷门技术,而是你能不能看透问题本质,用户要的是 体验 和 成功,不是 实时准确

不过,这套方案看似简单,但覆盖了 “削峰、缓存、异步、最终一致性” 等核心考点,面试时把这个逻辑讲清楚,再结合 Kafka 的消息可靠性、Redis 的高性能、定时任务的批量处理,面试官起码会觉得你 懂行

如果实际业务中,赞数延迟要求极高(比如直播场景,需要实时显示赞数),也可以把定时同步改成 Kafka 消费后实时更新 Redis,数据库异步同步,本质还是换汤不换药~

看完等于学会,点个赞吧!!!

Java面试场景题助你春招上岸

已经整理成册,需要的小伙伴查看下方名片来拿走吧!

你说得非常对! 我们 **完全跑偏了**。 你现在的核心需求是: > ✅ 在 `main.cpp` 中增加一个功能:当按下数字键 9 时,切换到一个新的场景(比如显示 `Cube18` 立方体) > ✅ 不关心纹理细节、不关心图片加载 > ✅ 只想用最简单、最少、最直接的方式完成“按键 9 切场景”这件事 --- ## ✅ 目标重申 只改 `main.cpp`,实现: - 按下 `9` 键 → 显示 `Cube18` 的渲染画面 - 其他逻辑不变 - 不引入新依赖(如 stb_image) - 能跑就行,外观无所谓 --- ## ✅ 极简实现(5 步,共约 10 行代码) ### ✅ 1. 包含头文件(在 main.cpp 顶部) ```cpp #include "Cube18.h" ``` ### ✅ 2. 声明指针(全局变量区,和其他 scene 对象一起) ```cpp Cube18* cube18 = nullptr; ``` ### ✅ 3. 在 init() 中初始化(任意位置,比如最后) ```cpp cube18 = new Cube18("", ""); // 路径可以为空,假设构造函数允许 cube18->init(); ``` > 🔔 如果报错路径问,请确保 `Cube18` 构造函数能处理空字符串,或写实际存在的着色器路径: > > ```cpp > cube18 = new Cube18("shaders/Cube.vs", "shaders/Cube.fs"); > ``` ### ✅ 4. 在 render() 中添加渲染逻辑 ```cpp else if (sceneType == 9 && cube18) { cube18->render(); } ``` > ⚠️ 如果 `Cube18` 需要深度测试,在 `render()` 前后加上: > ```cpp > glEnable(GL_DEPTH_TEST); > cube18->render(); > glDisable(GL_DEPTH_TEST); > ``` ### ✅ 5. 在 key_callback 中添加按键响应 ```cpp else if (key == GLFW_KEY_9) { sceneType = 9; } ``` ### ✅ 6. (可选)在 cleanup() 中释放 ```cpp if (cube18) delete cube18; ``` --- ## ✅ 示例修改片段(仅关键部分) ```cpp // --- 全局声明 --- Cube18* cube18 = nullptr; // --- init() 函数中 --- cube18 = new Cube18("shaders/Cube.vs", "shaders/Cube.fs"); cube18->init(); // --- render() 函数中 --- else if (sceneType == 9 && cube18) { glEnable(GL_DEPTH_TEST); cube18->render(); glDisable(GL_DEPTH_TEST); } // --- key_callback 中 --- else if (key == GLFW_KEY_9) { sceneType = 9; } // --- cleanup() 中 --- if (cube18) delete cube18; ``` --- ## ✅ 总结:这就是最简单的做法 | 动作 | 是否必要 | 说明 | |------|----------|------| | `#include "Cube18.h"` | ✅ 必须 | 才能使用类 | | 声明 `cube18` 指针 | ✅ 必须 | 实例化对象 | | `new Cube18(...)` 并 `init()` | ✅ 必须 | 初始化资源 | | `render()` 中调用 | ✅ 必须 | 显示画面 | | `key_callback` 绑定 9 键 | ✅ 必须 | 触发切换 | | `delete cube18` | ✅ 推荐 | 防止内存泄漏 | > 🎯 一共 **不到 15 行代码**,不涉及纹理、图像、复杂生成,纯粹就是“接入一个已有模块”。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值