Skip to content

Commit 6f60b17

Browse files
committed
2026-03-20 00:58
1 parent 4582987 commit 6f60b17

1 file changed

Lines changed: 72 additions & 114 deletions

File tree

src/p/interview-checklist/index.rst

Lines changed: 72 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ P(分区容错性)是说这个系统要允许分区?
590590

591591
网络分区(P)是必然发生的,所以通常是在CP(如ZooKeeper,牺牲可用性)和AP(如Eureka,牺牲强一致性,保证最终一致)之间权衡。
592592

593-
分布式锁 |_|
593+
分布式锁 |o|
594594
------------
595595

596596
场景
@@ -607,16 +607,21 @@ P(分区容错性)是说这个系统要允许分区?
607607
实现
608608
- mysql psql 关系型数据库:事务
609609
- redis redlock codis 非关系型数据库:SETNX (set if not exist)
610-
- etcd/zookeeper 集群协同:CAS
610+
- etcd:CAS + Lease
611611
- chubby 专用的锁服务
612612

613-
分布式定时器 |_|
613+
分布式定时器 |o|
614614
----------------
615615

616616
实现
617617
- 公平的分布式锁实现:etcd
618618
- 环形队列/时间轮
619619

620+
时间轮
621+
高效的定时器实现,适用于海量定时任务。
622+
623+
结构是多个不同时间级别(分钟级、秒级、毫秒级)的环状队列。
624+
620625
一致性级别 |o|
621626
--------------
622627

@@ -634,43 +639,6 @@ P(分区容错性)是说这个系统要允许分区?
634639

635640
读操作未必能够及时得到此前其他进程对同一数据的写更新,但是每个进程读到的该数据不同值的顺序却是一致的。
636641

637-
两阶段提交
638-
----------
639-
640-
Paxos
641-
-----
642-
643-
一种基于消息传递且具有高度容错特性的共识(consensus)算法。
644-
645-
—— :zhwiki:`Paxos算法`
646-
647-
分布式系统通信模型
648-
- 共享内存(Shared memory)
649-
- 消息传递(Messages passing)
650-
651-
好复杂…… 看看就行吧,不强求懂了。
652-
653-
Raft |_|
654-
--------
655-
656-
Raft能为在计算机集群之间部署有限状态机提供一种通用方法,并确保集群内的任意节点在某种状态转换上保持一致。
657-
658-
659-
660-
集群内的节点都对选举出的领袖采取信任,因此Raft不是一种拜占庭容错算法。
661-
662-
—— :zhwiki:`Raft`
663-
664-
子问题
665-
- 领袖选举(Leader Election)
666-
- 记录复写(Log Replication)
667-
- 安全性(Safety)
668-
669-
看 Wiki 即可,好懂多了。
670-
671-
外部排序
672-
--------
673-
674642
关系型数据库
675643
============
676644

@@ -846,9 +814,6 @@ MVCC
846814
架构
847815
====
848816

849-
服务降级
850-
--------
851-
852817
服务重试
853818
--------
854819

@@ -858,19 +823,20 @@ MVCC
858823

859824
重试策略:指数退避
860825

861-
限流器 |_|
826+
限流器 |o|
862827
----------
863828

864829
:URL: https://www.infoq.cn/article/qg2tx8fyw5vt-f3hh673
865830

866831
- 固定时间窗口计数
867832
- 滑动时间窗口计数
868-
- Token Bucket:水 = 令牌
869-
- Leaky Bucket:水 = 请求
833+
- 滑动日志 / Sliding log: 记录具体的时间戳,精度比滑动时间窗口好,可用 Redis zset 实现
834+
- Token Bucket:令牌规律放入桶中,请求消耗令牌,令牌可以攒着应对突发流量
835+
- Leaky Bucket:请求放入桶中,以固定速率漏出
870836

871837
.. seealso:: 流量整形
872838

873-
负载均衡 |_|
839+
负载均衡 |o|
874840
------------
875841

876842
方向
@@ -903,51 +869,39 @@ MVCC
903869

904870
查找距离这个对象的 hash 值最近的节点的 hash(在排好序的哈希数组里二分),即是这个对象所属的节点
905871

906-
灰度测试
907-
--------
908-
909-
A/B Test
910-
911-
实现
912-
913-
并发和吞吐
914-
----------
915-
916-
协程 异步 读写分离
917-
918-
故障转移
919-
--------
920-
921872
Golang
922873
======
923874

924-
调度问题 |_|
925-
------------
875+
`Changkun Ou | Go 语言原本 <https://golang.design/under-the-hood/>`_
926876

927-
:URL: https://www.douban.com/note/300631999/
877+
MGP 模型 |o|
878+
------------
928879

929880
线程模型
930881
:N:1: 可以很快的进行上下文切换,但是不能利用多核系统(multi-core systems)的优势
931882
:1:1: 能够利用机器上的所有核心的优势,但是上下文切换非常慢,因为不得不使用系统调用
932883
:M:N: 可以快速进行上下文切换,并且还能利用你系统上所有的核心的优势。主要的缺点是它增加了调度器的复杂性
933884

934885
M.P.G
935-
:M: OS 线程
936-
:P: Processor,可以把它看作在一个单线程上运行代码的调度器的一个本地化版本,携带一个 Goroutine 的 runqueue
886+
:M: Machine,OS 线程
887+
:P: Processor,逻辑处理器,可以把它看作在一个单线程上运行代码的调度器的一个本地化版本,携带一个 Goroutine 的 runqueue
937888
:G: Goroutine
938889

939890
P 就是 `runtime.GOMAXPROCS` 里的 *P*\ ROCS.
940891

941-
M 为什么不是 P
942-
如果正在运行的 M 为某种原因需要阻塞的时候,我们可以把 P 移交给其它 M
892+
为什么 M 和 P 要分开?
893+
**解耦了"执行能力"和"调度上下文"**
943894

944-
Go 程序要在多线程上运行的原因就是因为要处理系统调用,哪怕 `GOMAXPROCS` 等于 1
895+
如果正在运行的 M1 为某种原因需要阻塞的时候,可以把 P 和当前的 M2 解绑,让 P 去找新的 M2 来继续执行其他 G。
945896

946-
偷取 runqueue
947-
..
897+
Go 程序要在多线程上运行的原因就是因为要处理系统调用,哪怕 `GOMAXPROCS` 等于 1
948898

949-
为了保持运行Go代码,一个上下文能够从全局runqueue中获取goroutines,但是如果全局runqueue中也没有goroutines了,那么上下文就不得不从其它地方获取goroutines了。
899+
G 队列
900+
每个 G 拥有自己的无锁本地队列,仅在 Stealing 时需要加锁。Runtime 另有一个带锁的全局队列。
950901

902+
Runqueue stealing
903+
当 P 本地队列空时,从其他 P 偷取或者从全局队列偷取。
904+
951905
垃圾回收
952906
--------
953907

@@ -1048,7 +1002,17 @@ Dive in to code
10481002
:gcBgMarkStartWorkers: 为每个 P(线程上的本地调度器)启动一个 gcMarkWoker
10491003
:gcDrain: Mark 阶段的标记代码主要实现
10501004

1051-
.. todo:: GreenTea
1005+
GAB
1006+
`Go 生态下的字节跳动大规模微服务性能优化实践 - 文章 - 开发者社区 - 火山引擎 <https://developer.volcengine.com/articles/7317093617242210342>`_
1007+
1008+
GAB: 为 noscan 对象新增一个 Per-G 的 Bump pointer 风格的分配路径,GAB bucket 本身可以给 GC 跟踪和回收。为处理少量活跃对象需要额外实现 Copy GC
1009+
难点可能在处理栈扩展和 map 扩容等 reallocte 的场景。
1010+
1011+
1.26 GreenTea
1012+
`The Green Tea Garbage Collector - The Go Programming Language <https://go.dev/blog/greenteagc>`_
1013+
1014+
Track by page, not by object.
1015+
优化了空间局部性,对缓存友好,更容易被现代 CPU 优化。
10521016

10531017
内存管理
10541018
--------
@@ -1063,11 +1027,6 @@ Dive in to code
10631027
:mcentral: 全局 cache,mcache 不够用的时候向 mcentral 申请。
10641028
:mheap: 当 mcentral 也不够用的时候,通过 mheap 向操作系统申请。
10651029

1066-
Channel |_|
1067-
-----------
1068-
1069-
:URL: https://golang.design/under-the-hood/zh-cn/part2runtime/ch09lang/chan/
1070-
10711030
`sync.Mutex` |_|
10721031
----------------
10731032

@@ -1157,18 +1116,6 @@ Golang 的实现是写的互斥锁 + 读计数器,感觉有点别扭。
11571116
}
11581117
11591118
1160-
`sync.Map` |_|
1161-
--------------
1162-
1163-
:URL: - https://golang.org/src/sync/map.go
1164-
- https://colobu.com/2017/07/11/dive-into-sync-Map/
1165-
1166-
检测 "concurrent map read and map write"
1167-
用 `hashWriting`_ bit 表示当前是否在进行写操作
1168-
1169-
.. _hashWriting: https://github.com/golang/go/blob/master/src/runtime/map.go#L102
1170-
1171-
11721119
Defer
11731120
-----
11741121

@@ -1180,26 +1127,17 @@ Defer
11801127
:>=1.13: 栈上分配
11811128
:<1.14: Open coded
11821129

1183-
`&^` 操作符 |_|
1130+
`&^` 操作符 |o|
11841131
---------------
11851132

11861133
日常是很少用上,标准库代码里见得多。
11871134

11881135
Bit clear,`a &^ b == a & ^b`。
11891136

1190-
`interface{}`
1191-
-------------
1192-
1193-
内存泄漏
1194-
--------
1195-
1196-
死锁检测 |_|
1197-
------------
1198-
11991137
数据竞争
12001138
--------
12011139

1202-
`sync.Cond` 的虚假唤醒 |_|
1140+
`sync.Cond` 的虚假唤醒 |o|
12031141
~~~~~~~~~~~~~~~~~~~~~~~~~~
12041142

12051143
因为 condition 的判断是用户代码,在 `Wait()` 返回之后,因此只能要求用户用忙等的方式等到 condition 满足的时刻:
@@ -1215,16 +1153,41 @@ Bit clear,`a &^ b == a & ^b`。
12151153
// ... make use of condition ...
12161154
c.L.Unlock()
12171155
1218-
泛型
1219-
----
1156+
.. seealso:: `为什么条件锁会产生虚假唤醒现象(spurious wakeup)? - 知乎 <https://www.zhihu.com/question/271521213>`_
12201157

1221-
版本变更
1222-
--------
1158+
版本变更 |o|
1159+
------------
12231160

1224-
云原生
1225-
======
1161+
1.18
1162+
PDQSort
1163+
1164+
1.19
1165+
SetMemoryLimit
1166+
1167+
1.24
1168+
"Remove" Core Types
1169+
https://go.dev/blog/coretypes
1170+
1171+
让 ``[]byte`` 和 ``string`` 共享操作成为可能。
12261172

1227-
Docker |_|
1173+
Swiss Table
1174+
https://go.dev/blog/
1175+
1176+
SIMD 友好
1177+
1178+
1.25
1179+
GreenTea GC
1180+
...
1181+
1182+
JSONv2
1183+
https://go.dev/blog/jsonv2-exp
1184+
1185+
Steam-friendly,支持 Options
1186+
1187+
云原生/虚拟化
1188+
=============
1189+
1190+
Docker |o|
12281191
----------
12291192

12301193
共享内核
@@ -1263,11 +1226,6 @@ OverlayFS
12631226
:containerd: 管理容器
12641227
:container-shim: 通过 runC 运行容器
12651228

1266-
隔离
1267-
~~~~
1268-
1269-
:网络: namespace
1270-
12711229
流处理
12721230
======
12731231

0 commit comments

Comments
 (0)