Skip to content

Daily Study

更新: 12/27/2025 字数: 0 字 时长: 0 分钟

Daily Plan

#todo

  • [ ]

八股回顾

一些问题

Go 语言基础:

  • GMP 模型调度原理(尤其是 P 和 M 的关系,Goroutine 泄漏怎么排查)。
  • Channel 的底层实现,有缓冲和无缓冲的区别。
  • Context 的使用场景(超时控制、链路追踪)。

数据库与中间件:

  • MySQL 索引失效场景、B+树结构、事务隔离级别(MVCC 原理)。
  • Redis 跳表(SkipList)、持久化(RDB/AOF)、分布式锁实现(Redlock)。
  • Kafka 消息积压怎么处理?如何保证顺序消费?

网络与系统:

  • TCP 三次握手/四次挥手状态机(TIME_WAIT 状态过多的原因及危害)。
  • HTTP/2 和 HTTP/3 (QUIC) 的区别(因为 PCG 涉及视频业务,QUIC 很重要)。
  • Linux 内核态/用户态的问题,eBPF 原理

介绍一下go中的GMP模型

GMP首先代表三个核心结构:

核心调度策略:

  • 两个队列:
    • 本地队列:每一个P都有一个队列,存放待运行的G。M 优先从绑定的 P 的本地队列获取 G,无锁(或极少锁)速度极快。
    • 全局队列:存放所有 P 都能获取的 G。当 P 的本地队列满时,多出来的 G 会放到全局队列(需要加锁)
  • 工作窃取:当一个 P 的本地队列空了,且全局队列也空了。M 会尝试从其他 P 的本地队列中偷走一半的 G 到自己的队列中执行。充分利用多核 CPU,避免某些线程忙死,某些线程闲死。

追问1:为什么要有 P?直接 M 和 G 对应不行吗?

  • 全局锁竞争(Global Lock Contention):所有 M 都去同一个全局队列取 G,锁竞争极其严重,限制了并发扩展。
  • M 的内存缓存差:M 频繁切换 G,导致 CPU Cache 命中率低。
  • 线程创建/销毁开销:没有 P 作为缓冲,M 容易频繁创建和销毁。 P 的引入带来了本地队列(减少锁)和 Work Stealing(负载均衡),解决了这些问题。

追问2:Go 的抢占式调度是怎么实现的? 基于信号的抢占:引入了 sysmon(系统监控线程),它独立于 GMP 之外。sysmon 会监控运行时间过长的 G(超过 10ms)。 sysmon 向该 M 发送 SIGURG 信号。M 收到信号后,中断当前的 G,将其放回全局队列,从而调度下一个 G。

菜就多练

本站访客数 人次 本站总访问量