11.29 学习笔记

一、数据库核心考点

1. MySQL 事务(ACID + 项目落地)

  • ACID 特性:原子性、一致性、隔离性、持久性,是数据一致性的核心保障。
  • 项目落地
    • 原子性:科研项目协作平台中"用户角色变更 + 权限同步",事务确保两者全成/全回滚,避免数据不一致;
    • 一致性:校园社交平台"点赞操作",事务内同步"新增点赞记录 + 更新帖子点赞数",保证计数与记录匹配;
    • 隔离性:默认 InnoDB 可重复读(RR)隔离级别,避免脏读/不可重复读,高并发写场景用行锁保证隔离;
    • 持久性:依赖 redo log,事务提交后数据不丢失,数据库崩溃可恢复。
  • 优化:缩小事务范围,将非数据库操作(如 HTTP 请求)移出事务,减少锁占用时间。

2. MySQL 长读取 + 写入 + MVCC 机制

  • 长读取遇写入:RR 隔离级别下,读取生成一致性快照(Read View),写入创建数据新版本并记录 undo log,读写互不阻塞,读取仍返回快照旧版本;
  • 快照本质:仅记录活跃事务 ID/最大事务 ID,不拷贝全表数据,通过 undo log 链关联多版本数据;
  • undo log 回放:仅当数据当前版本不可见时回溯,同一事务内重复读取缓存结果,无需重复回放。

二、Go 语言核心考点

1. GMP 调度模型

  • 核心组件
    • G(Goroutine):用户态轻量级线程,初始栈 2KB,支持动态扩缩;
    • M(Machine):绑定内核线程,同一时间仅执行一个 G;
    • P(Processor):逻辑处理器,维护本地 G 队列,数量默认等于 CPU 核心数(GOMAXPROCS)。
  • 调度逻辑
    • P 管理本地 G 队列,M 从 P 取 G 执行;
    • G 阻塞时,M 释放 P,P 绑定其他 M 继续执行;
    • 本地队列为空时,P 从全局队列/其他 P 偷取 G,实现负载均衡。

2. Go 垃圾回收(GC)

  • 核心流程(Go 1.19+)
    1. 标记准备(STW):暂停 G,开启写屏障,扫描根对象(微秒级);
    2. 并发标记:恢复 G,后台线程标记存活对象,写屏障记录引用变更;
    3. 标记终止(STW):处理剩余引用(微秒级);
    4. 并发清除:回收未标记对象,归还内存;
    5. 可选并发整理:优化内存碎片。
  • 核心优化:三色标记法、混合写屏障、分代回收(Go 1.20+),STW 时间微秒级,低延迟适配高并发。

3. Go 程序 Linux 执行的系统调用

阶段 核心系统调用
启动阶段 execve(加载二进制)、mmap(内存映射)、brk/sbrk(堆初始化)、open(标准流)
运行阶段 socket/bind/listen/accept(网络)、open/read/write(文件)、clone(创建 M)、sigaction(信号)
退出阶段 exit_group(终止进程)
  • 延伸:网络操作底层封装 epoll(epoll_create/ctl/wait)实现 IO 多路复用。

4. Go 内存泄露排查

  • 遇过场景:校园社交平台协程因 Chan 未关闭阻塞,内存占用持续上升。
  • 排查流程
    1. 定位:go tool pprof 分析堆内存/协程数,发现 goroutine 指标异常;
    2. 分析:go tool pprof goroutine?debug=2 查看阻塞协程栈,定位未关闭 Chan;
    3. 验证:测试环境关闭 Chan 后协程正常退出,内存泄露解决;
    4. 监控:Prometheus+Grafana 监控协程数/内存,设置告警阈值。
  • 常见场景:sync.Pool 误用、全局 map 未清理、time.Ticker 未停止。

三、中间件核心考点

Redis 高性能原因

  1. 纯内存存储:读写无磁盘 IO,响应微秒级;
  2. 单线程模型:避免线程切换/锁竞争,简化并发;
  3. 高效数据结构:SDS(字符串)、字典(哈希)、跳表(ZSet),操作效率高;
  4. IO 多路复用:epoll/kqueue 管理多连接,高并发处理;
  5. 其他优化:批量操作(MSET/MGET)、Pipeline 减少网络往返。

四、网络核心考点

1. TCP 三次握手异常(客户端未发最后 ACK)

  • 过程:服务器进入 SYN_RCVD 状态,重发 SYN+ACK(默认 5 次,指数退避),超时(约 30 秒)后释放连接;
  • 影响:客户端连接失败,服务器大量异常会触发 SYN Flood,可通过 SYN Cookie 防御。

2. CDN 原理与访问流程

  • 核心作用:静态资源缓存到边缘节点,降低延迟、减轻源服务器压力;
  • 访问边缘服务器流程
    1. DNS 解析:智能调度 DNS 按用户 IP/运营商/节点负载,返回最优边缘节点 IP;
    2. 资源访问:边缘节点有缓存则直接返回,无缓存则拉取源服务器资源并缓存。
  • 调度策略:地理就近、负载均衡、运营商匹配。

3. IO 模型与多路复用

IO 方式 特点
阻塞 IO 等待 IO 完成,简单但效率低
非阻塞 IO 轮询判断 IO 状态,CPU 开销大
信号驱动 IO IO 完成后系统发信号,减少轮询
IO 多路复用 单进程管理多 IO 通道,epoll 性能最优
异步 IO 完全无阻塞,IO 完成后通知进程
  • IO 多路复用底层
    • select:FD 数量限制(1024),轮询效率低;
    • poll:无 FD 限制,仍轮询;
    • epoll:事件驱动,红黑树存储 FD,LT/ET 触发,高并发最优。
  • Go 实现:netpoller 跨平台适配(epoll/kqueue/IOCP),与 GMP 整合,IO 阻塞时 G 释放 P,提升并发。

4. HTTP 协议演进

(1)HTTP vs HTTPS
维度 HTTP HTTPS
传输 明文 HTTP+TLS/SSL 加密
端口 80 443
安全性 无认证/完整性保障 加密、身份认证、完整性校验
握手 TCP 三次握手 TCP 三次握手 + TLS 四次握手
  • HTTPS 安全保障
    1. 加密:非对称加密(握手)+ 对称加密(传输);
    2. 认证:CA 签发证书,验证服务器身份;
    3. 完整性:HMAC 校验,防止数据篡改。
  • HTTPS 握手流程
    1. 客户端发 Client Hello(TLS 版本/加密套件/随机数);
    2. 服务器发 Server Hello(确认参数)+ 证书;
    3. 客户端验证证书,加密预主密钥发送给服务器;
    4. 双方生成会话密钥,Finished 消息确认握手;
    5. 数据传输:会话密钥对称加密 HTTP 数据。
(2)HTTP/1.1 vs HTTP/2
优化点 HTTP/1.1 HTTP/2
并发机制 串行传输,队头阻塞 帧多路复用,并行传输
头部传输 重复传输,开销大 HPACK 压缩,静态+动态字典
传输格式 文本,解析易出错 二进制帧,解析高效
资源获取 客户端主动请求 服务器推送关联资源
流量控制 基于流的精细化控制
  • 实战价值:HTTP/2 使多静态资源页面加载时间降低 40%+,如文档列表页从 1.2s 降至 0.7s。
(3)HTTP/2 vs HTTP/3
维度 HTTP/2 HTTP/3
传输层 TCP UDP(QUIC)
队头阻塞 连接级阻塞 流级隔离,无阻塞
握手延迟 7RTT(TCP+TLS) 1-2RTT(QUIC 合并 TLS)
连接迁移 绑定 IP+端口 基于连接 ID,支持网络切换
  • HTTP/3 可靠性保障(QUIC)
    1. 可靠交付:序列号+ACK 重传、滑动窗口流量控制;
    2. 有序交付:独立流机制,流内有序、流间隔离;
    3. 拥塞控制:CUBIC/BBR 算法,动态调整速率;
    4. 其他:全量加密、零 RTT 握手、连接迁移。

5. 进程通信方式(IPC)

方式 核心特点 适用场景
管道(Pipe) 半双工,父子进程通信 本地简单数据传递
命名管道 无亲缘关系进程通信 本地低吞吐场景
消息队列 按类型排序,非阻塞 分布式系统数据传递
共享内存 最快 IPC,需信号量同步 高吞吐数据共享
信号量 同步互斥,非数据传递 共享资源访问控制
信号 异步通知 进程终止/异常处理
Socket 跨主机通信 网络分布式系统(C/S)

6. 多进程程序必要性

  1. 隔离性:多租户系统独立进程,避免单点故障影响全局;
  2. 多核利用:进程绑定 CPU 核心,减少资源竞争;
  3. 容错性:核心业务拆分进程,单个崩溃不影响整体,支持自动重启。

五、算法核心考点

1. 二叉树的右视图(BFS)

go 复制代码
package main

import (
	"container/list"
	"fmt"
)

type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func rightSideView(root *TreeNode) []int {
	var res []int
	if root == nil {
		return res
	}
	queue := list.New()
	queue.PushBack(root)
	for queue.Len() > 0 {
		levelSize := queue.Len()
		for i := 0; i < levelSize; i++ {
			node := queue.Remove(queue.Front()).(*TreeNode)
			if i == levelSize-1 {
				res = append(res, node.Val)
			}
			if node.Left != nil {
				queue.PushBack(node.Left)
			}
			if node.Right != nil {
				queue.PushBack(node.Right)
			}
		}
	}
	return res
}
  • 复杂度:时间 O(n),空间 O(n);
  • 边界:空树返回空,左子树存在时取最右侧节点。

2. 两数之和(哈希表 + 延伸)

基础实现(O(n))
go 复制代码
func twoSum(nums []int, target int) []int {
	numMap := make(map[int]int)
	for i, num := range nums {
		if idx, ok := numMap[target-num]; ok {
			return []int{idx, i}
		}
		numMap[num] = i
	}
	return nil
}
延伸追问
问题 核心答案
为什么用哈希表 空间换时间,O(n) 对比暴力 O(n²),效率提升显著
千万级数据哈希表装得下吗 1000 万数据约 160MB,普通服务器可容纳;亿级需 1.6GB,内存紧张则需优化
内存放不下怎么办 分块落盘:拆分为 100 万/块,逐块用哈希表匹配,跨块记录索引
更高效方案 排序+双指针(O(nlogn),空间 O(1)),无需原索引时最优
多组解处理 哈希表存"值→索引列表",遍历收集所有匹配项
O(n) 优化空间 预分配哈希表容量、早停、重复值跳过

3. 子数组和为 K(前缀和 + 哈希表)

go 复制代码
func subarraySum(nums []int, k int) bool {
	prefixMap := make(map[int]bool)
	prefixSum := 0
	prefixMap[0] = true
	for _, num := range nums {
		prefixSum += num
		if prefixMap[prefixSum-k] {
			return true
		}
		prefixMap[prefixSum] = true
	}
	return false
}
  • 复杂度:时间 O(n),空间 O(n);
  • 边界:处理子数组从索引 0 开始的情况(初始化 prefixMap[0]=true)。
相关推荐
白日做梦Q1 小时前
深度学习调参手册:学习率、Batch Size 的最优搭配策略
深度学习·学习·batch
zore_c1 小时前
【C语言】数据在内存中的存储(超详解)
c语言·开发语言·数据结构·经验分享·笔记
摇滚侠1 小时前
零基础小白自学Git_Github教程,Git 四个分区的概念,笔记11
笔记·git·github
不败公爵1 小时前
Git的工作机制
笔记·git·stm32
Philtell1 小时前
【动手学深度学习】笔记
人工智能·笔记·深度学习
玩具猴_wjh1 小时前
11.30 学习笔记
笔记·学习
诺狞猫1 小时前
黄山派 TF卡使用
科技·学习·黄山派·思澈·sifli
卡提西亚2 小时前
数据库笔记-0-MYSQL安装
数据库·笔记·sql
ljt27249606612 小时前
Compose笔记(五十九)--BadgedBox
android·笔记·android jetpack