关于系统瓶颈的面试问题

2021-02-01 21:09:43 +08:00
 yyyfor

求教一下各位大佬,

面试老是被问到系统瓶颈的问题,如果现在正常运行的系统,要改造提高 10(甚至 100)倍的 qps,会遇到哪些问题、瓶颈?

关于这类的问题,应该如何去分析和描述?

4534 次点击
所在节点    程序员
45 条回复
Kirsk
2021-02-02 00:38:31 +08:00
鬼知道 具体问题具体分析 稀里糊涂的提问的人也不知道 走过场看面试者对不对自己胃口=你猜猜看我最爱吃什么
yyyfor
2021-02-02 09:08:43 +08:00
@Kirsk 昨天遇到的问题还算具体的。redis 每秒十万个 get 请求,会不会有问题? 如果没有问题,每秒请求量继续增加,问增加十倍或者一百倍,制约请求量增加的瓶颈因素是什么?
Kirsk
2021-02-02 09:20:35 +08:00
@yyyfor 假设是单纯承载容量 那就是集群横向扩展了
yyyfor
2021-02-02 09:23:47 +08:00
@Kirsk 面试官已经假设是在一台机器上了。我当时觉得应该从 cpu 、内存、io 去分析,但是具体分析的过程不知道如何表述比较准确
Kirsk
2021-02-02 09:27:31 +08:00
@yyyfor 有思路就行了 剩下是上手干活去解决的
yyyfor
2021-02-02 09:49:14 +08:00
@Kirsk 面试官想要具体的分析过程😂比如 cpu 、内存、io 哪个最有可能最先成为瓶颈? 然后卡了好久。感觉面试官想要从具体的数据量级去分析这个问题
lewis89
2021-02-02 10:02:00 +08:00
@yyyfor #4

问 redis,10 万请求的,这个时候制约 redis 的是单核心问题吧,因为单线程模型最多能打满一个 CPU,上集群就可以打满多个 CPU 实例,然后上集群就要涉及到热点 key 的问题,如果 100 万的 key get 操作 90%路由到一个 redis 实例上 ,那么又回到老问题,你的 hash 算法是否合理,真实的业务场景要不要解决热点 key 的问题,甚至可以在 redis 的路由上再开发一套 ip 随机 负载均衡的 分片,把 redis 的 get 操作路由到不同的 slave 节点上,此时多个 slave 副本又要考虑 CAP 的问题,是保证强一致性 所有的 slave 副本跟 master 节点保障 强一致性,那么就是 CP 系统 此时就是牺牲高可用,如果是要高可用,那就是异步复制 AP 系统,牺牲强一致性 来保障高可用 /高并发读,此时 master slave 副本肯定会存在数据不一致的问题,另外 redis 本身是写入内存的,如果你想通过写入硬盘 AOF 这种操作 将日志写入这些低速设备来保障最终一致性也是不可行的,因为低速设备(持久化)本身就会拖慢系统的响应速度。

另外瓶颈的问题,首先可以从网络层分析,是否存在 TCP SYN 超时大量 socket 描述符没有被回收的情况,因为 C10K 的问题我模拟过,默认的 ubuntu 设置 存在 fd 描述符数量上限以及 socket 超时描述符未被回收的情况,如果是大量的短连接频繁创建销毁会触发这个问题。

然后就是考虑 TCP 的拥塞问题,是否可以考虑使用快启动算法,来避免滑动窗口缩小,然后导致原本 2-3 个报文就搞定的事情,结果因为拥塞的问题 多好几个 ip 报文才发送出去。

其余的瓶颈可以查看机械硬盘的 IO 看是否有大量的随机读写 拖慢了机械硬盘的速度,导致大量的 CPU 空闲,然后所有进程都在等待磁盘 IO

内存方面可以排查页交换的问题,是否存在频繁的内存页从低速磁盘设备换出到物理内存,一般都是不建议服务器使用 swap 空间

CPU 飙升的话,可以看是不是 C10K 大量线程被频繁唤醒,然后频繁进入内核态上下文切换带来的非常大的开销


性能瓶颈的话其实还是从 X86 的存储体系结构来分析,或者从网络层去分析,就差不多了
qwer666df
2021-02-02 10:07:41 +08:00
@lewis89 #7 请教一下, 昨天有一个类似的问题, 关于一个活动用户发短信的场景 他意思一个线程只能处理 10w 个任务, 然后系统如果这个时候只开了 5 个线程, 也就是 50w 任务, 但是活动太过火爆了之后. 只能突然来了几百万的请求, 这时候怎么处理, 不考虑服务器手动加脚本的操作
lewis89
2021-02-02 10:12:29 +08:00
@qwer666df #8 一开始就要考虑复杂均衡跟平滑扩容吧,而且这种任务没有顺序依赖,很容易分片解决就好了
lewis89
2021-02-02 10:18:49 +08:00
@qwer666df #8 所有的并发, 如果没有数据竞争或者顺序依赖的情况,都可以通过平滑扩容以及负载均衡来解决,nginx 可以通过监测你服务的响应时间把 这些请求进行负载均衡处理的,实际上每台机器或者线程处理的数量不会太大

高并发读从来都不是问题,如果不要求强一致性,加副本 配合 分片路由算法,没有什么问题是加机器不能解决的,
真正的问题是 高并发读的时候 如何解决写的问题,写的话 如何保障副本跟主节点的数据同步问题,并发读写才是要命的,这个时候要么 要求主从强一致性 那就是选 CP ,要么要求主从弱一致性,或者存在延迟同步的情况,此时就是 AP
yyyfor
2021-02-02 10:24:08 +08:00
@lewis89 受教了,谢谢老哥
qwer666df
2021-02-02 10:30:24 +08:00
@lewis89 #10 如果是单机咋是不是就没办法了 昨天没有想过加机器的办法.... 我以为他是让我在单机上面考虑
lewis89
2021-02-02 10:34:11 +08:00
@yyyfor #6 另外 Redis 本身 AOF 也是会丢失数据的,如果每一个写操作 都 fsync 到硬盘,那么每次 redis 的写操作就退化到磁盘的写入速度了,虽然内核文件系统会 buffer 你的写操作,然后合并成连续写 来提升性能,但是也顶不住你每次写操作都 fsync 写入硬盘的操作,毕竟磁盘的磁头 寻道,要从外面的圈移动到里面的圈,从寻道的物理角度来讲,他的速度是很非常慢的,所以机械硬盘只适合连续读写,在 4K 随机读写的场景下,机械硬盘就是个渣渣,被 SSD nvme 硬盘吊打的
lewis89
2021-02-02 10:38:17 +08:00
@qwer666df #12 不可能单机的,单机 CPU 都打满了,你再怎么优化都没用,通常来讲,所有的服务都是无状态的,服务本身不存储任何状态,这样高峰的时候,我们可以通过扩展集群实例数量来提升吞吐量,但是大部分互联网的业务其实瓶颈都在数据库,所以一般都会采取 水平拆分的操作 来提升写的并发能力,因为写的话 会分片写入多个 MySQL 实例,此时单机写入的压力就会降低,总体的写入性能就会提升。
qwer666df
2021-02-02 10:40:09 +08:00
@lewis89 #14 受教了, 现在业务代码写的多, 还真不懂怎么 "扩展集群实例数量", 谢谢老哥
lewis89
2021-02-02 10:43:57 +08:00
@qwer666df 扩展集群实例很简单的,一开始考虑好怎么负载均衡 然后用 k8s 加实例就好了,现在基本上这些都是运维做的,但是程序员要考虑负载均衡的算法,避免单个实例负载很大的情况
lewis89
2021-02-02 10:49:24 +08:00
@qwer666df #15 要随时能扩充服务实例,首先还是要考虑 服务的无状态化,例如以前单机的 session 就不能用了,session 得存放到 redis 里面,不然你扩充的实例 不知道 session 在哪里,用 token 令牌的现在也只能存到 redis 里面去,所有的服务本身不保存任何状态,这样就可以平滑的加机器 减少机器的数量.. 当然这种集群扩充减少大多只能解决 CPU 密集型问题,对于瓶颈在数据库 IO 的问题 没法解决
liuxu
2021-02-02 10:58:59 +08:00
@qwer666df
@lewis89

#8 属于削峰问题,正确的方法是入消息队列,前端线程只做任务入消息队列,后端线程消费任务。前端 cpu 爆了的话只能横向扩展机器,由于只入消息队列,所以是可扩展的。
lewis89
2021-02-02 11:14:46 +08:00
@liuxu #18 如果我不削峰呢?我就要实时性,你这边 5 个线程,可能人家发送短信的 IO 可能根本都没打满,削峰只有 IO 被打满的情况下 不得已才考虑的一种情况,而且代码的主流程 是没法削峰的,发优惠券发金豆这种你削峰就削峰了,用户不会在意到账的及时性,像饿了么这种下订单的主流程,你怎么削峰?进消息队列?人家几秒钟的等待或者看到 提示错误就准备打开美团外卖了。
lewis89
2021-02-02 11:17:37 +08:00
@liuxu #18 另外饿了么下订单这种主流程 只能做分表去提升并发写的能力,然后做冷热分离去提升读的能力,否则用户一看,订单没下成功,饿肚子了 分分钟就打开你对手美团的 APP 去下单了

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

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

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

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

© 2021 V2EX