Interview
面试准备(后端)
语言go
1. 内存管理
总体结构
-
tcmalloc
-
mspan
-
mcache
-
mheap
sync.Pool
-
环状列表
-
victimCache (1.13)
2. 同步
关键字及其用法原理
channel
select
sync.WaitGroup
思想
- 名句
3. 垃圾回收
三色波面推进(标记整理)
具体相关字段
流程
比较其他垃圾回收器
- 引用计数
-
标记回收
-
标记回收整理
-
同步时回收
4. reflection
iface & eface
5. 继承(组合)
一些常考的cases
string(), error(), read(), write()
6. net包
epoll
优秀的连接池包
- fasthttp
计算机网络
总体七层
应用层常用
HTTP 80端口
头,幂等设计
HTTP1.1, HTTP2 & HTTPS
安全
- JWT
- HTTPS
- session
传输层
总体
tcp
-
结构 40 Bytes 五元组<source ip, dest ip> 标志位(RST,ACK,SYN,FIN)
-
面向连接,可靠
- 选择重传(快重传)
- 三次握手,四次挥手
- linux下常用默认设置
-
安全
- 校验码,纠错
udp
-
结构
五元组
-
不可靠 不用握手
-
安全
- crc只可以检测,不可以纠错
网络层
IP协议
MMU(max ) 1500 Bytes
DNS
- 43端口
- 权威,顶级,根
- 递归,迭代
ICMP
trace route, ping
ARP
DHCP
链路层
MAC地址
BGP &
- 域间路由,域内路由
- 链路毒逆转
物理层
略
- 几种光纤
数据库
持久型
MySQL, 5.7
单机事务
-
ACID
-
隔离性四个级别
- 串行
- repeatable Read, 保证写,可能有幻读(范围内的读取读取不到插入或者删除),一般是快照实现(MVVC)
- unrepeatable Read,
基本常用语法
- explain
indexing
-
聚簇索引
-
非聚簇索引
源码生成
缓存内存型
Redis
概括
-
内存跑
-
单线程(网络部分), IO多路复用(epoll)
-
优秀的数据结构
缓存的几种应对
-
读多 写时,先删除,再写 读时,直接读
-
写多 写后再更新
基本结构(对外API)
string
- ziplist
list
- lpop, rpop, lpush, rpush llen
dict
-
ziplist
-
hashmap
set
- dict
zset
- quicklist+ dict
aof & rdb
暂时略
replicated & sentinel & clusters
-
offset复制
-
raft log
操作系统(Linux)
编码
大顶端,小顶端 ASCII
进程,线程
-
- 分配资源的基本单位
- task_struct{}
-
调度的基本单位
调度
-
时间片轮转
-
优先级(nice 值 -20 ~ 19)
-
抢断式
软中断和下半部
内存分配
文件
- 一切皆文件,都有一个fd
硬盘
- 电梯法
计算机组成原理
补码,原码,反码
正数,补码=原码,反码符号位除外全部取反
IEEE754
ps: 0.1+0.2!=0.3 问题
0.1无法用2进制准确表达
总线BUS
Go中常用汇编(plan9)
- SP stack pointer PC
常见命令: ADD SUB
MOV SYMBOL+OFFSET(SP),伪SP OFFSET(SP),真SP
JMP
分布式
CAP 分区容错 一致性 可用性
负载均衡
- 负载均衡算法
- 健康检查(从IP层到HTTP层)
- session的保持方式
事务
2PC -> 3PC
共识算法
Paxos -> MultiPaxos -> ZAB -> Raft
Project
-
日志的输出kafka,处理; 包括失败下线,成功率,设计任务调度队列
-
缓存的任务调度队列,针对不同级别的任务队列,进程池的的大小来区分优先级;
项目
- job调度,使用工作池来限制其权重速率大小
- 限流,redis hmget,存储
- kafka,排除消息堆积: 提交到broker的偏移量处开始消费。 我在网上查阅了消息堆积和消息重复的一些原因,发现问题可能出现在kafka的poll()设置上。 查阅kafka官网发现我用的那个版本的kafka主要有以下几个比较关键的指标: a. max.poll.records一次poll返回的最大记录数默认是500 b. max.poll.interval.ms两次poll方法最大时间间隔这个参数,默认是300s 这次问题出现的原因为由于业务上下方的消息增量变多,导致堆积的消息过多,每一批poll()的处理都能达到500条消息,导致poll之后消费的时间过长。 服务端约定了和客户端max.poll.interval.ms,两次poll最大间隔。 如果客户端处理一批消息花费的时间超过了这个限制时间,broker可能就会把消费者客户端移除掉,提交偏移量又会报错。 所以拉取偏移量没有提交到broker,分区又rebalance,下一次重新分配分区时,消费者会从最新的已提交偏移量处开始消费,这里就出现了重复消费的问题。 而服务注册中心zookeeper以为客户端失效进行rebalance,因此连接到另外一台消费服务器,然而另外一台服务器也出现poll()超时,又进行rebalance…如此循环,才出现了一直重发消息,导致消息数量被消费后下降很慢。
rebalance:
consumer订阅topic中的一个或者多个partition中的消息,一个consumer group下可以有多个consumer,一条消息只能被group中的一个consumer消费。 consumer和consumer group的关系是动态维护的,并不固定,当某个consumer卡住或者挂掉时,该consumer订阅的partition会被重新分配给该group下其它consumer,用于保证服务的可用性。 为维护consumer和group之间的关系,consumer会定期向服务端的coordinator(一个负责维持客户端与服务端关系的协调者)发送心跳heartbeat,当consumer因为某种原因如死机无法在session.timeout.ms配置的时间间隔内发送heartbeat时,coordinator会认为该consumer已死,它所订阅的partition会被重新分配给同一group的其它consumer,该过程叫:rebalanced。
方案:
使用Kafka时,消费者每次poll的数据业务处理时间不能超过kafka的max.poll.interval.ms,可以考虑调大超时时间或者调小每次poll的数据量。 增加max.poll.interval.ms处理时长(默认间隔300s)
- max.poll.interval.ms=300
修改分区拉取阈值(默认50s,建议压测评估调小)
max.poll.records = 50
- 可以考虑增强消费者的消费能力,使用线程池消费或者将消费者中耗时业务改成异步,并保证对消息是幂等处理
- 不但要有消息积压的监控,还可以考虑做消息消费速度的监控(前后两次offset比较)
- redis, 缓存的一致性,write aside,write through
- failbackup,用资源换延迟,发送多个请求,有一个返回就用那个
项目
库存管理 数据库升级,MySQL -> Mongo 聚合型,业务要求,库存和价格混合覆盖,省钱;
线程池实现job的更新队列速度,改进,top类别使用第三方队列,可以考虑全部用第三方队列,宕机之后方便恢复;
促销:秒杀,方案从读缓存,不存在入Mongo(write through,read through)到直接在Redis上进行增加减少(一段时间或大促过后更新到持久层) 促销定时器,(redis zset->时间轮);
过滤平台请求:kafka入队信息,定时器计数;
运营系统,对账(减内存占用,保证准确性);
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!