先来唠唠
最近成都春招现场搞了个大新闻——直接用AI当面试官!
网上有个人分享自己的经历:他全程对着电脑摄像头答题,AI不光听他说话,还盯着他的表情打分;他还说自己刚开口自我介绍,网突然卡了3秒,结果系统直接弹了个‘抗压能力不足’的评价,气得他差点摔手机。
但这事儿也有魔幻的另一面:有人靠着AI给的‘面试建议’(比如说话别太快、多笑一笑),还真拿到了大厂offer;招聘会数据说,AI筛人比HR快3倍,一上午面了上千人。
问题是,这玩意儿到底靠不靠谱?有人觉得公平,毕竟AI不看学历只看表现;也有人吐槽‘面完都不知道输哪儿’。如果是你,愿意让一个算法决定你的工作机会吗?评论区聊聊。
面经分享
今天分享的面经是万兴的一面,挺简单的,看一下你都会不会:
一、介绍一下 Git 的使用
Git 是一个分布式版本控制系统,用于跟踪代码变更和协作开发。以下是核心使用场景:
基础操作
git init
:初始化本地仓库。git add <file>
:将文件添加到暂存区(git add .
添加所有文件)。git commit -m "message"
:提交更改到本地仓库。git status
:查看当前仓库状态(如未跟踪/已修改的文件)。
分支管理
git branch
:查看分支列表。git checkout -b <branch>
:创建并切换到新分支。git merge <branch>
:合并指定分支到当前分支。git rebase <branch>
:变基操作(整理提交历史)。
远程仓库
git clone <url>
:克隆远程仓库到本地。git pull
:拉取远程分支并合并到本地。git push
:推送本地提交到远程仓库。
撤销与回退
git reset --hard <commit_id>
:回退到指定提交(慎用)。git revert <commit_id>
:生成新提交以撤销某次更改。
二、JWT
JWT(JSON Web Token) 是一种用于身份验证的开放标准(RFC 7519),结构为 Header.Payload.Signature
:
Header
- 声明令牌类型(如
JWT
)和签名算法(如HS256
)。
- 声明令牌类型(如
Payload
- 包含用户信息(如用户 ID、角色)和其他声明(如过期时间
exp
)。
- 包含用户信息(如用户 ID、角色)和其他声明(如过期时间
Signature
- 对前两部分签名,防止篡改(例如:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
)。
- 对前两部分签名,防止篡改(例如:
用途:
- 用户登录后,服务端生成 JWT 返回给客户端,客户端后续请求携带 JWT 进行身份验证。
优点:
- 无状态,适合分布式系统。
- 支持自定义数据,减少数据库查询。
缺点:
- 令牌一旦签发,在有效期内无法主动失效。
三、缓存穿透、击穿、雪崩
1. 缓存穿透
概念:查询数据库中不存在的数据,导致请求直接穿透到数据库。
解决:
- 布隆过滤器:拦截无效请求。
- 缓存空值:对不存在的数据缓存空值并设置短过期时间。
2. 缓存击穿
概念:热点 Key 突然失效,大量请求直接打到数据库。
解决:
- 互斥锁:仅允许一个线程重建缓存。
- 永不过期:逻辑过期时间配合异步更新。
3. 缓存雪崩
概念:大量 Key 同时过期或缓存服务宕机,导致数据库压力激增。
解决:
- 随机过期时间:避免集中失效。
- 集群部署:如 Redis Cluster 保障高可用。
四、慢查询
概念:执行时间超过阈值的 SQL 查询(如 MySQL 默认阈值为 10 秒)。
排查与优化:
开启慢查询日志:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 2; -- 设置阈值
分析工具:
EXPLAIN
:查看执行计划。mysqldumpslow
:分析日志。
优化手段:
- 添加索引。
- 优化 SQL 结构(如避免
SELECT *
)。
五、数据库锁都有哪些
- 行锁:锁定单行(如 InnoDB 的
SELECT ... FOR UPDATE
)。 - 表锁:锁定整张表(如 MyISAM 的写锁)。
- 共享锁(S 锁):允许其他事务读,禁止写。
- 排他锁(X 锁):禁止其他事务读写。
- 意向锁:快速判断表级冲突(如意向共享锁 IS)。
- 间隙锁:锁定范围(防止幻读)。
六、不同隔离层级不同在哪里
- 读未提交(Read Uncommitted):可能读到未提交的数据(脏读)。
- 读已提交(Read Committed):只能读到已提交的数据(解决脏读)。
- 可重复读(Repeatable Read):事务内多次读取结果一致(解决不可重复读)。
- 串行化(Serializable):完全隔离(解决幻读,但性能低)。
七、MVCC
多版本并发控制(Multi-Version Concurrency Control) 通过版本链实现非锁定读:
- 版本链:每行数据关联多个版本(通过
DB_TRX_ID
和DB_ROLL_PTR
)。 ReadView:事务启动时生成快照,决定可见哪个版本。
- 读已提交:每次查询生成新 ReadView。
- 可重复读:事务内复用同一个 ReadView。
八、Redis 数据结构
- String:字符串、整数、二进制数据。
- List:双向链表(支持队列、栈)。
- Hash:键值对集合。
- Set:无序唯一集合。
- Zset:有序集合(基于跳跃表 + 字典)。
- 其他:Bitmaps、HyperLogLog、Streams。
九、Zset 的底层原理
Zset 通过 跳跃表(Skip List) 和 哈希表(Hash Table) 实现:
- 跳跃表:支持 O(logN) 复杂度的范围查询(如
ZRANGE
)。 - 哈希表:存储成员到分值的映射,实现 O(1) 的单点查询。
特点: - 数据按分值排序,成员唯一。
- 插入、删除、查询的时间复杂度均为 O(logN)。
十、Go 中的 GMP 模型
GMP 是 Go 的并发调度模型:
- G(Goroutine):轻量级用户态线程。
- M(Machine):操作系统线程,由内核调度。
- P(Processor):逻辑处理器,管理本地队列和上下文。
调度逻辑:
- P 的数量:默认等于 CPU 核心数(通过
GOMAXPROCS
设置)。 - 工作窃取:当 P 的本地队列为空时,从其他 P 的队列窃取 G。
- 系统调用:若 G 发生阻塞系统调用,M 会解绑 P 并创建新 M 继续执行。
快速排序
package main
import "fmt"
func quickSort(arr []int) []int {
if len(arr) <= 1 {
return arr
}
pivot := arr[len(arr)/2] // 选择中间元素作为基准
left, right := []int{}, []int{}
for _, num := range arr {
if num < pivot {
left = append(left, num)
} else if num > pivot {
right = append(right, num)
}
}
// 递归排序左右部分,合并结果
return append(append(quickSort(left), pivot), quickSort(right)...)
}
func main() {
arr := []int{3, 6, 8, 10, 1, 2, 1}
fmt.Println(quickSort(arr)) // 输出 [1 1 2 3 6 8 10]
}
说明:
- 时间复杂度:平均 O(n log n),最差 O(n²)。
- 优化点:可随机选择基准(避免最坏情况)。
欢迎关注 ❤
我们搞了一个免费的面试真题共享群,互通有无,一起刷题进步。
没准能让你能刷到自己意向公司的最新面试题呢。
感兴趣的朋友们可以加我微信:wangzhongyang1993,备注:sf面试群。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。