转转转后端

文章发布时间:

最后更新时间:

自我介绍,介绍项目

8年代码经验 算法(noip),全栈,团队沟通,基础(成绩,os,db,计网,组原都有认真手写lab或黑皮书), AI (llm推理引擎,Yolov8,RL) 实习 项目:创业,招新(2年,近万人) 实习:所有浏览器功能(权限,生态,优化) 1框架(组件拦截) 2:截图自定义海报接口 3需求管理机器人 4团购券

! ai工具使用

  1. 学习、lab:不用
  2. 业务项目:把所有 框架(数据关系,这个接口的效果和数据方式)(生成,后期不会让他修,因为代码量大,涉及文件多,不如自己改快)

强制缓存和协商缓存

https://xiaolincoding.com/network/2_http/http_interview.html#%E4%BB%80%E4%B9%88%E6%98%AF%E5%BC%BA%E5%88%B6%E7%BC%93%E5%AD%98

强制缓存由浏览器主导,在一定时间内(Cache-Control)不找后端

协商缓存用 Last-Modified/If-Modified-Since, ETag/If-None-Match 来(后端)判断是否修改过,如果没修改过返回304

Go 静态服务 http.FileServer 使用 Last-Modified(文件系统元数据),hash运算开销太大

手写 ETag,把要发的data做md5 hash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func GetData(c *gin.Context) {
// 强制缓存
c.Header("Cache-Control", "public, max-age=3600")

// 协商缓存 (手动实现)
data := getData()
etag := generateETag(data)

if match := c.GetHeader("If-None-Match"); match == etag {
c.Status(http.StatusNotModified)
return
}

c.Header("ETag", etag)
c.JSON(http.StatusOK, data)
}

HTTPS (SSL/TLS)

登录&https 加密 在 TCP 和 HTTP 网络层之间加入了 SSL/TLS 安全协议,HTTPS 在 TCP 三次握手之后,还需 SSL/TLS 的握手 机密性:非对称加密获得会话密钥,对称加密传输数据

认证 确保公钥的身份

HTTP/2

  • 头部压缩
  • 二进制格式
  • 并发传输:同一个tcp连接里的不同http请求可以并发,用 stream ID 识别
  • 服务器主动推送资源 双方都可以建立 stream,客户端建立的 Stream 必须是奇数号,而服务器建立的 Stream 必须是偶数号。

HTTP/3 QUIC

 QUIC 是一个在 UDP 之上的 TCP + TLS + HTTP/2 的多路复用的协议 - 无队头阻塞:实现每个stream相互独立的TCP的rdt,减少队头阻塞 - 更快的连接建立:把tcp连接和tls连接合在一起 - 连接迁移:不像 TCP的源ip+端口 & 目标ip+端口 来标识每一个tcp连接,而是让进程创建唯一标识,来防止ip改变而引起的

epoll

用于监听多个文件描述符,询问时只返回就绪的文件描述符 一个红黑树map(用于存储所有监听信息,快速查/删)(epoll_ctl添加节点),一个就绪队列(epoll_wait阻塞等待就绪队列有值之后返回就绪队列) select/poll只能知道有fd就绪,不能知道是哪些fd就绪,\(O(所有监听节点)\) 用于轮询查找,epoll \(O(就绪节点)\) for I/O 多路复用

LT 是“只要有数据就一直提醒”,而 ET 是“只有新数据到来时才提醒一次”。*

缓存

设计模式

  1. Cache Aside:应用程序负责管理缓存和数据库(后面三个都是只和缓存交互)。即缓存没有命中时app自己找db。read:先缓存;write:先更新数据库再删除缓存(因为先删除缓存可能另一个线程读取db脏数据又给放到缓存了)
  2. Read Through:缓存负责从数据库加载数据。
  3. Write Through:同步写,缓存让db写入数据之后返回success给app
  4. Write Behind:异步写,like page cache in os or db,更新缓存之后返回成功,异步地延迟执行db更新 ### 驱逐参数 volatile/allkeys 是否只驱逐设置了ttl的缓存、 lru 最长时间未被访问 lfu 访问频率

量化指标

缓存20-30%的数据达到85%+的命中率 命中率 请求平均延迟 吞吐量,RPS(请求数/s),QPS(数据库查询数/s) cpu使用率和连接数

如何避免缓存雪崩、缓存击穿、缓存穿透

雪崩:大量缓存数据在同一时间过期,导致大量用户请求访问数据库。随机,不过期 击穿:热点数据过期。提前更新缓存 穿透:数据库没有该值(可能是攻击)。布隆过滤器,手动判断

docker

详见 docker & k8s

MYSQL

解析器 -> 语法树 -> 优化器 -> plan -> 执行器 -> 存储引擎 InnoDB: - B+树 - 表空间 :段,(索引段,数据段,回滚段) 区(数据量大,让页之间连续) ,页 ,行 - 行格式:变长列长度(len[]),是否null位图,头,rowid 主键(若无定义),事务id, roll id(mvcc),每列值 - 页目录slot 分组,存储每组最大row的偏移

Redis

高性能高开发、高可用(集群) string.hash.set.zset.list bitmap, geo, stream(消息队列) 内部实现: - listpack: (类型、长度、数据、总长度)[] 用于对小的list.hash.zset - 小Set 处整数;intset int16[] 排序 主逻辑单线程 后台线程:close file.AOF盘、free对象 快的原因:内存、无竞争、I/O多路复用 集群:主从(读写分离)、哨兵(故障、转移)

Golang

面向对象:封装(struct,大小写)、继承(struct嵌套,匿名,自动提升),多态 js:弱类型 大多数值在堆上,变量本身为指针 优势:1协程 2编译速度快、开发效率 2自由 make & new:1类型new(string、int,数组),make(只:切片、map, Channel) 2返回指针or值 for range 每次循环一个临时变量 string 长度不能用len():字节长度 len ([ ] rune ( str ) 类似char

反射 - Typeof:Struct的元数据:可以找到Tag - ValueOf : 接口值 map.slice.chan为引用类型(值本身类似指针) select:I/O多路复用(每个case为in/out) panic:下标越界、Channel关闭、÷0、断言(no ok)

map不是并发安全->Sync.map (读多买少是优于读写锁) - read map →缓存 hash表 - dirty map

多返回值:在调用此fune的函数的栈上预留空间 Slice/Struct/map: copy(dst, src) & reflect.DeepEqual 程序初始化:最深包 init开始

GC

三色+写屏障 白:未扫描 灰:已扫描,还有出边为白(还在队列中) 根:全局、栈、寄存器 并发:不正确(同时满足1 2):1:创建 黑→白 2删除 灰->白 混合写屏障(对应上面两个条件)1.当创建 黑-》白时白边灰,2.当删除 灰-》白 时检查白没有其他灰指向,就变灰(STW:无能并行 stop the world

微服务

https://juejin.cn/post/7052143950085226510

apollo架构 https://mp.weixin.qq.com/s/-hUaQPzfsl9Lm3IqQW3VDQ ## K8S https://mp.weixin.qq.com/s/wOMzZw-CImSgDoQasy2iHg

一、微服务基础组件

1. 服务治理(Kitex / Spring Cloud 体系)

核心能力:
1. 服务注册与发现
* 常见组件:Nacos、Eureka
2. 健康检查 / 服务追踪
3. 配置管理(动态配置)
4. 网关(统一入口)
5. 负载均衡


2. 服务注册与发现

  • 注册中心:
    • Nacos
    • Eureka(AP 优先)
  • 客户端调用流程:

服务注册 → 服务发现 → 客户端负载均衡 → 调用


3. DNS vs 注册中心

  • DNS:
    • 简单解析 IP
    • 不适合动态服务
  • 注册中心:
    • 支持动态上下线
    • 健康检查
    • 更适合微服务

4. 负载均衡策略

  • Random(随机)
  • Round Robin(轮询)
  • Pick First(优先选一个)
  • 一致性 Hash(部分场景)

5. RPC 框架(Dubbo / gRPC / Kitex)

  • 核心:
    • 服务调用(远程)
    • 序列化协议
    • 服务治理
  • 长连接 + KeepAlive
  • Watch 机制(监听服务变化)

二、Kubernetes(K8s)

核心概念

  • Master:
    • etcd(存储)
    • 调度器(scheduler)
  • Node:
    • 运行 Pod

核心对象

  • Pod:最小部署单元
  • Deployment:管理副本
  • Service:服务暴露

Service 类型

  • ClusterIP(集群内访问)
  • NodePort(节点端口)
  • LoadBalancer(外部负载均衡)

配置中心

配置实时生效(.env),灰度发布(容器的镜像id?) ## 三、网关(Gateway)
### 作用
* 所有外部请求入口
* 做统一处理:
* 路由
* 负载均衡
* 限流
* 鉴权
* 灰度发布
常见网关 Nginx Traefik
traefik
* Provider:
* Docker
* Kubernetes
* 注册中心
鉴权流程:先转到authservice -> 成功 -> 给后端并附加一个header 失败 -> 302/401 给前端
### 熔断 & 降级
* 熔断:
* 下游错误率高 → 直接不请求下游
* 限流:
* 控制 QPS 令牌桶 * 重试 ### 3. CAP 理论

  • C(一致性)
  • A(可用性)
  • P(分区容错)

五、高并发 & 秒杀系统

典型流程

前端限流or验证码 → 网关限流 → Redis 预扣库存(原子lua get&desc 防超卖) → 消息队列削峰 → DB 最终写入(乐观锁&唯一id)-> 最终一致性 ## 六、分布式事务

1. TCC 模式

  • Try(预处理)
  • Confirm(提交)
  • Cancel(回滚)

2. SAGA 模式

  • 长事务拆分
  • 每一步都有补偿操作
    ### 3. Seata
  • AT 模式(自动回滚 undo log)
    ## 七、分布式锁
    ### Redis 实现
  • SET NX EX
  • 防止死锁:设置过期时间
  • 解锁: lua ### Redlock(多节点锁)
    直接在多个节点上锁,多数都有才算获取锁 ### Zookeeper
  • 临时节点
  • Watch 机制
    ## 八、分布式 ID
    ### 方案
  • UUID(简单但无序)
  • redis
  • 号段,类ip子网
  • 雪花算法(Snowflake)
    ## 十、乐观锁 ### SQL 示例
1
2
3
update table   
set count = count - 1
where id = ? and version = ?

十一、限流

  1. 计数器
  2. 滑动窗口
  3. 令牌桶 *
  4. 漏桶

C++

虚函数

实现运行时多态,调用时动态判断时调用哪个版本的函数 基类像是interfere 如果析构函数是虚函数:先调用派生类析构函数 , 再调用基类析构函数。(正常是覆盖)

  1. 分配内存。
  2. 调用 A 构造函数:vptr 指向 A 虚表 -> 执行 A 构造体(输出 A)。
  3. 调用 B 构造函数:vptr 改指向 B 虚表 -> 执行 B 构造体。

查端口

netstate 查询网络状况,最新用ss sudo ss -ltnp sport = :80 lsof -i :80 (list open file)

TIMEWAIT是什么,服务器有大量timewait是为什么,如何缓解

是四次挥手过程中,主动方收到被动方的FIN然后发送ACK之后进入状态,持续两个MSL,大概60s;为了确认ACK被收到(被动方关闭),2msl是ack丢失+被动方重发。 服务器主动关闭:1. 没有长连接 2. 长连接超时 3. 连接数量太多 → 高并发且持续的短连接 过多的timewait会导致无法连接更多,需要手动减少。tcp_tw_reuse 快速回收或增加nginx连接数大小

三次握手

四次挥手

js this

function 是调用时指定,箭头函数是定义时指定 但是 setInterval 里的 function() {} 不是你调用的,是浏览器/Node.js 在定时器触发时调用的,相当于:

1
2
// 定时器触发时,浏览器内部大概这样调用: 
callback() // 普通函数调用,没有指定 this