昨天面试的几个 MySQL 和 Redis 的题目,来请教一下

204 天前
 dumbbell5kg

1.MySQL 里的记录有这么两个字段:
课程 id课程余额
同时间大量学生抢同一门课,如何设计这个功能?

2.线上 Redis 内存满了,应该如何处理?

3.你认为解决高并发问题的本质是什么?

求大佬赐教 orz

8045 次点击
所在节点    数据库
63 条回复
isno
204 天前
1. 大概率是是想问你悲观锁、乐观锁的区别
1.1 使用悲观锁,串行阻塞,资源占用大
1.2 乐观锁,CAS 机制,失败了再增加个重试机制

3. 解决高并发的本质是需求与资源的不对等
3.1 有钱增加资源:分布式、横向/竖向扩容
3.2 没钱增加资源:限流、部分服务不可用
lsk569937453
204 天前
1.秒杀直接上 redis ,把课程 Id 和对应的数量放到 redis 里,抢到后往消息队列发消息,然后通过消费者处理后续的流程。
2.redis 满了之后可以设置过期策略。把策略设置一下就好。
3.这是扩展题。发现性能瓶颈,然后通过削峰、限流、扩容、分表等手段让系统平稳的处理流量。
8355
204 天前
1.2 个方向 redis decr 或着 队列消费 应该规避回答 mysql 锁相关的回答,我认为是陷阱问题。
2.扩容+监控,实际上不可能满。这种题的预设本身就比较失败
猜测是想问内存碎片相关,或着排查流程类似找大 key ,要么就是集群分片方案。
3.通过优化响应速度提高并发量,应用场景包括不限于缓存/消息队列削峰/部分操作提前等等
whahuzhihao
204 天前
估计面试官看过《高并发的哲学原理》才会问第三个问题。https://pphc.lvwenhan.com/
japeth
204 天前
@imokkkk 请教一下 第一个问题的这种解法,放内存不合适吧,如果有多个实例同时运行可能会不一致,合并成一次批量扣减,如果在用户提交的时候反馈结果呢
@lsk569937453 请教一下 第一个问题的这种解法 是不是也是不能在用户提交的时候反馈结果呢
mightybruce
204 天前
@whahuzhihao 我也看过这个,写得非常好。

前三个问题上来就谈具体方案的人基本都是缺少架构设计经验,上面 V2EX 回答大多数都基本上都是具体方案,

同一的问题不同复杂度和需求下设计是不一样的, 不少架构师照搬别人或自己原来公司架构导致崩盘的事件不少。
yangxiaopeipei
204 天前
抢课做成拼多多的砍单怎么样
22yune
204 天前
1 、采用摇号机制,报名同一课程的同学都进一个池子,随机选择。5 分钟一轮。
2 、线上 redis 应该有监控,预警了可以先试着清理:查看内存主要消耗在哪里,是否有必要(数据结构、过期策略)。还是内存不足就扩容,加内存。
3 、高并发的本质是资源共享、导致要争抢(竞争)。
zhao8681286
204 天前
解决高并发的本质就是在业务上避免高并发的场景的产生,看看早年的双十一和现在的双十一。
iosyyy
204 天前
@8355 #23 2 应该是想问如果满了怎么排查 big key 以及 redis 的内存清理机制吧 包括可能一些过期时间的实际问题
3 我觉得应该答本质是拿空间换时间
iosyyy
204 天前
@iosyyy 内存淘汰机制太久没看给忘了
killva4624
204 天前
1 其实用队列感觉更简单,一个人只运行提交一次,按提交时间先后消费占课。
twofox
204 天前
我还真做过教务系统。首先抢课是肯定要先开设课程的,然后每个课程就是有限定选课学生数量。
也就是
课程 id ,课程余额

实际业务不单止会判断学生数量而已。
按照判断条件的先后排列的话,我们需要判断这些条件

1. 面向的选课学生范围(一门课首先要设置上课学生的年级、专业范围)
2. 课程类型是否满足(公选课、专业选修课)
3. 是否设置了课程类型的学分上限?(例如专业选修课本次选课只能选 5 个学分的)
4. 上课时间是否冲突?(要判断已经排好的专业课、本次选课的其它课程、实习周、军训时间)
5. 最后才是容量问题

所以针对这种场景,前东家是这么做的
1. 选课需要缓存好各类数据(就上面的那些判断条件,数据量大、硬件差的学校需要缓存一二十分钟的)
2. 选课的相关条件都从缓存取(避免大 key ,redis 多部署几个节点做集群)
3. 打开选课界面的时候,获取的可选课程也是从缓存取
4. 选择课程提交的时候,把课程 id 用 redisson 锁起来,然后进行条件判断
5. 如果成功之后就把选课的相关数据写进数据库
6. 缓存里的数量-1 ,释放锁

这一套下来,几千人抢课还是可以的。
但是实际上我当初提过用消息队列去缓解压力,leader 没用过,不敢用。怕消息队列崩了

当时选课真的一团糟,包括不限于数据库锁表了,jvm oom 了,redis 超时了
因为当时判断条件,真就硬从 Oracle 里面查询啊
twofox
204 天前
选课还有个业务场景的,就是退选

退选的情况下,又要考虑数据库和缓存的一致性。
fkdog
204 天前
我对问题本身兴趣不大。
倒是对楼下的回复挺感兴趣的。
可以看出,虽然本质都是 CRUD ,但是工程师思考的角度和普通开发思考的角度还是差别挺大的。
admol
204 天前
第一问,实际上是在问你系统设计问题
而你只是直接回答了其中很小的一个点(做法),也不能说不对,只能说不完全对。


尝试从下面几个步骤回答下:
1. 多问
- 学校总的有多少学生需要抢课
- 学校大概总的有多少非常热门的课程
- 平均到每门热门课程大概有多少学生会同一时刻抢
- 给出一些人数,然后是否可以估算出 QPS
假设:需要抢课的学生 1000 人,
假设查询课程 QPS 粗略估算:1000QPS ,峰值*2 ,算 2000QPS

- 其他开放性问题,是否有其他要求
2.初步方案
分为两部来进行涉及:
1. 查询课程(查询并发最大)
设计一个高效的索引和缓存机制,以应对高并发查询需求。方案有:缓存、读写分离等
2. 提交抢课
设计一个分布式锁机制,确保同一时间只有一个学生可以成功抢课。方案有:Redis 、ZK 分布式锁、消息队列等

3.详细方案
- 开始抢课之前,提前将课程-课程余额缓存到 Redis 中
- 使用读写分离,分散查询课程和抢课程写结果时数据库的压力
- 使用 Redis 进行扣减余额
- 扣减成功,记录抢课结果(学生-课程)
4.总结
- 缓存、锁、读写分离、其他方案
admol
204 天前
线上 Redis 内存满了,应该如何处理?

思路:
1. 解决线上问题,快速恢复线上功能正常访问
- Redis 扩容
- 手动清理不必要的缓存数据,释放内存

线上功能恢复后再做
2. 找出为什么满问题
- 分析 Redis key ,是否是热点数据访问量暴增?
- 是否是 缓存 key 设计不合理
- Redis 配置参数不合理,导致内存使用效率低下
3. 避免为什么满问题
- 针对 2 进行优化,增加监控告警等措施
admol
204 天前
3.你认为解决高并发问题的本质是什么?
- 本质就是在大量的请求和有限的资源情况下,如何来保持系统的性能和可用性等。
- 手段很多:增加资源、减小开销、缓存、服务化、冗余、异步、队列、限流、熔断等
admol
204 天前
推荐看下这个:
系统设计面试:内幕指南 https://learning-guide.gitbook.io/system-design-interview
mightybruce
204 天前
@admol 学校 qps 很低的, 到不了 1000 , 另外学校也不会就只开放几个小时不到一天去选课
你实在太高估学校了。

除非这个学校很特殊,哈哈。面试官假想的学校。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1035477

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX