Skip to content

Commit 17c3d1a

Browse files
committed
add notes
1 parent 0514e01 commit 17c3d1a

40 files changed

+891
-0
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,25 @@
22

33
这是我过往面试时总结的经验,从个人的Git repo里整理,公开出来,希望能帮助到更多的人。
44

5+
ref: https://jiajunhuang.com/articles/2018_08_29-become_a_better_programmer.md.html
6+
57
版权声明:本repo所有内容遵守CC BY 3.0协议。请注明来源:https://jiajunhuang.com
8+
9+
- [自我介绍,以及我和面试官的关系]()
10+
- [缓存相关](./cache.md)
11+
- [编译相关](./compile.md)
12+
- [协程](./coroutine.md)
13+
- [数据库索引设计及其优化](./database.md)
14+
- [Docker相关](./docker.md)
15+
- [GC,垃圾回收算法](./gc.md)
16+
- [Golang GMP](./golang_gmp.md)
17+
- [gRPC相关](./grpc.md)
18+
- [HTTP(s)和HTTP/2协议](./http_https_http2.md)
19+
- [Kubernetes相关](./k8s.md)
20+
- [Nginx相关问题](./nginx.md)
21+
- [操作系统相关](./os_components.md)
22+
- [内存模型](./os_mem_layout.md)
23+
- [Python 2字符编码问题](./python2_coding.md)
24+
- [Redis相关问题](./redis.md)
25+
- [操作系统系统调用](./syscall.md)
26+
- [TCP/IP协议相关](./tcp_ip.md)

cache.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# 缓存相关
2+
3+
- 缓存算法
4+
5+
- FIFO: first in first out
6+
- LRU: least recent used -> 很好用,但是实现很复杂
7+
- LFU: least frequency used -> 同上
8+
9+
- 缓存更新策略
10+
11+
- cache aside: 更新数据删缓存,读取数据加缓存/如果缓存有,则直接从缓存读
12+
- read/write through: 读时由服务端自己将缓存载入,更新时如果没有命中缓存,则直接更新DB,若命中,则更新缓存,由DB自己
13+
从缓存刷到DB
14+
- write behind cache:读和写都在cache上,由server自己刷数据回DB。例如:mmap。
15+
16+
> 参考:https://coolshell.cn/articles/17416.html
17+
18+
- redis vs memcached
19+
20+
- 读写速度两者相当
21+
- redis更省内存
22+
- disk i/o dumping: redis更好因为可以配置
23+
- scaling: 有很多工具
24+
- redis有更加丰富的数据结构和原子操作

compile.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# 编译相关
2+
3+
- 过程
4+
5+
- 预编译:展开所有宏定义,条件包含等
6+
- 编译:词法分析,语法分析,生成汇编码
7+
8+
- 词法分析
9+
- 语法分析
10+
- 中间码:三元操作符
11+
- 目标码生成及优化
12+
13+
- 汇编:汇编器将汇编码生成接近可执行文件的二进制文件
14+
- 链接:将一大堆文件链接,解决其中未明确定义的地址,生成最终的可执行文件
15+
16+
- 装载
17+
18+
动态链接库是运行时确定地址的。确定地址的这一步就叫装载。

coroutine.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# 协程
2+
3+
ref: https://jiajunhuang.com/articles/2018_04_03-coroutine.md.html
4+
5+
- https://en.wikipedia.org/wiki/Coroutine
6+
7+
协程是用户空间的“线程”,由程序员自己控制代码跳转。
8+
9+
协程分为有栈(stackful)协程和无栈(stackless)协程:
10+
11+
- 有栈协程:
12+
13+
- 如goroutine和greenlet。每个G都有自己的栈指针SB,SP等。切换到某个G执行时,将SP和SB刷到寄存器,
14+
使用G自带的栈。
15+
- 优点是更加灵活,可以整栈切换。
16+
17+
- 无栈协程:
18+
19+
- 如Python中的generator(带yield的函数就是generator),只把该函数执行时的帧带上,
20+
执行时,使用调用者的栈。
21+
- 无栈协程职能拿最上面的帧。因此优点是要保存的数据较少。缺点是没有有栈协程灵活,
22+
可以一锅端。通常性能也比有栈协程差一点。
23+
24+
---------------------
25+
26+
- goroutine: https://github.com/jiajunhuang/go/blob/718d6c5880fe3507b1d224789b29bc2410fc9da5/src/runtime/runtime2.go#L330-L400
27+
28+
- greenlet: https://github.com/python-greenlet/greenlet/blob/2032971562ac6d89bc5ef09af7c0d4eeb30a8079/greenlet.h#L16-L32
29+
30+
- Generator: https://github.com/jiajunhuang/cpython/blob/f62415324ce64c5e7a94719f7d5aae93dfc144be/Include/genobject.h#L15-L33

database.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# 数据库索引设计及其优化
2+
3+
## 索引设计
4+
5+
- 三星索引(JOIN, where/order by, select xxx)
6+
7+
- 索引的本质是用写入时间换取查询时间
8+
9+
- 索引一般有哈希表和B树家族,还有bitmap
10+
11+
- B树把KV都放在节点上
12+
- B+树把K放在节点上,V放在叶子节点上
13+
14+
- 选择索引应当选择区分度大的列
15+
16+
- https://tech.meituan.com/mysql-index.html
17+
- 最左前缀匹配原则
18+
- =和in可以乱序
19+
- 尽量选择区分度高的列作为索引
20+
- 索引列不能参加计算
21+
- 尽量的扩展索引,不要建新的索引
22+
23+
## 相关概念
24+
25+
- 连接
26+
27+
- [数据库连接](https://zh.wikipedia.org/zh-hans/%E8%BF%9E%E6%8E%A5_(SQL))
28+
- [JOIN和INNER JOIN的区别](https://stackoverflow.com/questions/565620/difference-between-join-and-inner-join)
29+
30+
- INNER:内连接。JOIN默认就是INNER JOIN。这两个没有任何区别,除了读法不一样。
31+
32+
- 相等连接:`SELECT * FROM A JOIN B ON A.some_id = B.some_id``SELECT * FROM A JOIN B USING (some_id)`
33+
- 自然连接: 自然连接比相等连接的进一步特例化。两表做自然连接时,两表中的所有名称相同的列都将被比较,这是隐式的。
34+
自然连接得到的结果表中,两表中名称相同的列只出现一次。`SELECT * FROM employee NATURAL JOIN department`
35+
- CROSS: 交叉连接,笛卡尔积。 `SELECT * FROM employee, drpartment`。从A表for循环B表。
36+
37+
- FULL OUTER: 全外连接
38+
39+
- LEFT OUTER: 左外连接,LEFT OUTER JOIN,简写成LEFT JOIN
40+
- RIGHT OUTER: 右外连接,RIGHT OUTER JOIN,简写成RIGHT JOIN
41+
- 全连接:全连接是左右外连接的并集. 连接表包含被连接的表的所有记录, 如果缺少匹配的记录, 即以 NULL 填充。
42+
43+
- `self-join`:在特定的情况下,一张表可以和自身进行连接,称为自连接
44+
45+
- 连接算法
46+
47+
- 循环嵌套(LOOP JOIN):类似于C里的for嵌套
48+
- 合并连接(MERGE JOIN):类似于两个有序数组的合并。两个输入表都在合并列上排序,然后依序对两张表逐行做连接或舍弃。
49+
如果预先建好了索引,合并连接的时间复杂度是线性的。
50+
- 哈希连接(HASH JOIN):适用于查询的中间结果,通常是无索引的临时表,以及中间结果的行数很大时。
51+
52+
- 事务隔离级别
53+
54+
- 未提交读
55+
- 已提交读
56+
- 可重复读
57+
- 串行读
58+
59+
- 事务的特性
60+
61+
- Atomicity:原子性
62+
- Consistency:一致性
63+
- Isolation:隔离性
64+
- Durability:持久性
65+
66+
## 数据库优化
67+
68+
- 加缓存
69+
- 检查硬件是否达到应有的标准
70+
- EXPLAIN并且检查索引是否设计正确
71+
- 加硬件
72+
- 读写分离,一主多从
73+
- 垂直分表(把不相关的字段拆走)
74+
- 水平分表(例如定期归档)
75+
- 垂直分库(如微服务化)
76+
- 水平分库(sharding)
77+
78+
- 覆盖索引
79+
80+
https://stackoverflow.com/questions/62137/what-is-a-covered-index
81+
82+
`select * from table where conditions` 假设conditions有用到索引,那么查询是先使用conditions,然后下降到B+树的叶子节点
83+
拿数据,这需要扫描搜索出来的行。而如果是 `select a, b from table where conditions`,conditions, a, b都有索引的话,a和
84+
b就可以直接在B+树的节点中取值而不需要去叶子节点拿到对应的行来取值了。这就叫索引覆盖,或者覆盖索引。EXPLAIN的时候如果显示
85+
`Using index` 就说明是索引覆盖。
86+
87+
- primary key 和 unique key的区别
88+
89+
https://stackoverflow.com/questions/9565996/difference-between-primary-key-and-unique-key
90+
91+
- 主键只能有一个
92+
- 主键不能为NULL
93+
- 主键是unique key但是反之不成立
94+
- unique可以有多个
95+
- unique可以有NULL,而且可以有多个
96+
- It can be a candidate key?(https://en.wikipedia.org/wiki/Candidate_key)
97+
98+
- 索引设计
99+
100+
- 索引的本质是用写入时间获取读取时间
101+
- 尽可能的复用索引,而不建重复的索引,如:有UNIQUE就不需要另建索引
102+
- 尽可能选取区分度大的索引
103+
- 使用覆盖索引
104+
- 设计三星索引

docker.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Docker相关问题
2+
3+
![dockerd](./img/dockerd.png)
4+
5+
- dockerd通过gRPC和containerd通信
6+
- 如果是start或者exec容器,containerd就拉起一个container-shim
7+
- container-shim拉起之后,拉起runC进程,runC
8+
9+
- [runC](https://github.com/opencontainers/runc): CLI tool for spawning and running containers according to the OCI specification
10+
- [containerd](https://github.com/containerd/containerd): An open and reliable container runtime

gc.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# GC算法
2+
3+
- 标记清除:从一些任何时候都可以访问的对象出发,例如线程内的栈,将能触及到的对象都做一个标记。第二步,扫描全部对象,清除
4+
没有标记的对象。
5+
- 引用计数:对每个对象增加引用时,引用计数+1,反之-1。引用计数为0则回收对象
6+
- 拷贝:把整个堆里,可以触及的对象拷贝到另外一个地方
7+
- 分代回收:按对象的年龄划分
8+
9+
- Python的GC算法:引用计数为主,分代回收为辅,从容器对象出发,减少一个引用,看是否为0,为0则回收。越老的对象生存的对象可能
10+
会更久。
11+
12+
- Go的GC算法:标记清除。

golang_gmp.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Goroutine 和 Golang runtime
2+
3+
ref: https://jiajunhuang.com/articles/2018_02_02-golang_runtime.md.html
4+
ref: https://jiajunhuang.com/articles/2017_02_24-goroutine_and_work_stealing.md.html
5+
6+
![GMP](./img/golang_gmp.jpg)
7+
8+
此外,还有:
9+
10+
- netpoller负责等待网络事件并且将能唤醒的G重新丢回去
11+
- 一个全局G队列
12+
- work stealing算法保证每个M都不会闲着

grpc.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# gRPC相关
2+
3+
## HTTP2
4+
5+
- HTTP2比1,改进在哪?为什么会更快?
6+
7+
- https://www.zhihu.com/question/34074946
8+
- 多路复用,允许通过单一的HTTP/2连接发起多重的请求-响应消息。而HTTP/1.1协议中,
9+
浏览器客户端在同一时间内,针对同一域名下的请求数量有一定的数量限制。超过限制数目
10+
的请求会被阻塞。(解决办法:CDN使用多个域名)
11+
- 二进制分帧,HTTP/2会将所有传输的信息分割成更小的消息和帧,并对他们采用二进制
12+
格式的编码,其中HTTP/1.1中的首部信息会被封装到HEADER frame,而body则会封装进
13+
DATA frame。头部进行压缩,使用[HPACK](https://www.jianshu.com/p/f44b930cfcac)算法。
14+
- server push。
15+
16+
------------
17+
18+
- https://http2.github.io/http2-spec/
19+
20+
## protobuf
21+
22+
- https://developers.google.com/protocol-buffers/docs/encoding
23+
24+
- little endian
25+
- base 128 varints: 每个byte的第一位,代表接下来是否仍然有数据。
26+
低的7位表示数据,base-128是因为2的7次方是128。例如1,则表示为
27+
`0000 0001`,300,则表示为 `1010 1100 0000 0010`,怎么还原成300呢?
28+
首先把高位忽略,变成 `010 1100 000 0010`,然后翻转(因为是little endian),
29+
所以是 `000 0010 010 1100`,即 `100101100`,算一下即 `256 + 32 + 8 + 4 = 300`
30+
- 表示类型的byte,低三位表示类型,高三位是field number,即proto message里的tag。
31+
32+
- gRPC vs RESTful
33+
34+
- 需要传输的数据量更小(数据压缩,例如int32最少只需要一个byte)
35+
- HTTP头部有很多重复的信息
36+
- 调用更方便

http_https_http2.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# HTTP(s)协议和HTTP/2
2+
3+
- HTTP并没有规定其下面该用什么协议(TCP,UDP)实现,不过通常是用TCP(因为安全,可靠)
4+
5+
- HTTP方法
6+
7+
- GET -> 幂等
8+
- HEAD -> 幂等
9+
- POST
10+
- PUT
11+
- DELETE
12+
- TRACE
13+
- OPTIONS
14+
- CONNECT
15+
- PATCH
16+
17+
- 历史版本
18+
19+
- HTTP/1.0
20+
- HTTP/1.1 相对于1.0增加了 Keep-Alive, Cache-Control, Chunked。所有头部中除了Host
21+
其他都是可选的
22+
- HTTP/2 见 [这里](./grpc.md)
23+
24+
- 状态码
25+
26+
- 100 go on
27+
28+
- 100 Continue
29+
- 101 Switching Protocols
30+
- 102 Processing
31+
32+
- 200 success
33+
34+
- 200 OK
35+
- 201 Created
36+
- 202 Accepted
37+
- 204 No Content
38+
39+
- 300 go away
40+
41+
- 300 Multiple Choices
42+
- 301 Moved Permantly
43+
- 302 Found
44+
- 303 See Other
45+
- 304 Not Modified
46+
- 305 Use Proxy
47+
- 307 Temporary Redirect,与302不同,不会改变请求方法
48+
- 308 Permanent Redirect,与301不同,不会改变请求方法
49+
50+
- 400 your bad
51+
52+
- 400 Bad Request
53+
- 401 Unauthorized
54+
- 402 Payment Required
55+
- 403 Forbidden
56+
- 404 Not Found
57+
- 405 Method Not Allowed
58+
- 429 Too Many Requests
59+
60+
- 500 my bad
61+
62+
- 500 Internal Server Error
63+
- 501 Not Implemented
64+
- 502 Bad Gateway
65+
- 503 Service Unavailabel
66+
- 504 Gateway Timeout
67+
68+
- 基本的请求体结构:
69+
70+
```http
71+
GET / HTTP/1.1
72+
Host: www.google.com
73+
```
74+
75+
- 基本的响应结构:
76+
77+
```http
78+
HTTP/1.1 200 OK
79+
Content-Length: 599
80+
Server: openresty
81+
Date: 2018...
82+
Content-Type: application/json
83+
Connection: Keep-Alive
84+
```
85+
86+
- Chunked模式
87+
88+
```http
89+
HTTP/1.1 200 OK
90+
Content-Type: text/plain
91+
Transfer-Encoding: chunked
92+
93+
25
94+
blablabla
95+
96+
1c
97+
bladlsjdlksajd
98+
99+
8
100+
kldsajlkds
101+
102+
0 -> 0然后\r\n\r\n就是结束
103+
```
104+
105+
- HTTPs握手流程
106+
107+
- 浏览器发起请求
108+
- 服务端下发证书和支持的加密方法
109+
- 浏览器验证证书是否可信
110+
- 如果可信,浏览器选择自己也支持的加密方法,生成随机数
111+
- 浏览器用公钥加密随机数,发送给服务器
112+
- 开始对称加密通信
113+
114+
- HTTP/2
115+
116+
- 压缩头部
117+
- 多路复用(分帧,帧上面带有序号)
118+
- server push

0 commit comments

Comments
 (0)