eBPF 入门:用 bpftrace 给生产服务器做"无侵入体检"
线上 CPU 偶发飙到 90%,日志里又看不到原因。传统 strace + perf 上去一插性能直接打骨折。试了 eBPF 的 bpftrace,在内核里跑探针、零侵入采样,8 行脚本定位到一个第三方库的 spinlock 循环。这篇笔记记录从安装到写出第一个生产可用脚本的完整过程,以及和老牌工具的对比。
记录编程、运维、自动化、分布式系统的心得与踩坑 · 持续学习中
本站是个人技术学习记录,所有文章均为本人学习编程、运维过程中的心得整理,欢迎技术爱好者交流参考。
线上 CPU 偶发飙到 90%,日志里又看不到原因。传统 strace + perf 上去一插性能直接打骨折。试了 eBPF 的 bpftrace,在内核里跑探针、零侵入采样,8 行脚本定位到一个第三方库的 spinlock 循环。这篇笔记记录从安装到写出第一个生产可用脚本的完整过程,以及和老牌工具的对比。
Paxos 难懂,Raft 易懂。本文从 leader election、log replication、safety 三个核心模块拆解 Raft,并结合 etcd 源码看实际工程化怎么做的(尤其是网络分区下的脑裂保护)。读完能理解为什么 K8s、TiDB、CockroachDB 都用 Raft 而不是 Paxos。
最近捣鼓一个内网服务,需要用 Nginx 做反向代理,中间踩了不少坑,比如 502 Bad Gateway、SSL 证书配置、跨域问题等。把这个排查过程记录下来,方便以后查阅,也分享给可能遇到同样问题的同学。
用 requests + threadpool 写了个爬虫,跑 1000 个 URL 要 80 秒。改写成 aiohttp + asyncio 后只要 3 秒。本文从协程原理(event loop / coroutine / task)讲到实战陷阱(同步阻塞调用、异常传递、取消语义),最后给出一个生产级并发限流模板。
公司每周要处理几十张 Excel 报表,手工搞要半天。学了 openpyxl 之后写了个脚本,5 分钟搞定。这篇笔记整理了常用 API、合并单元格、设置样式、批量导出的高效代码片段。
"Don't communicate by sharing memory; share memory by communicating." 这是 Go 官方对并发的指导原则。本文用 channel + select + context 实现一个支持优雅退出的工作池,对比了用 sync.Mutex 的传统写法,演示 CSP 模型的优势(代码量减半 + 无死锁)。
从 C++ 切到 Rust 最大的认知冲击就是所有权(ownership)和借用(borrow)。这篇笔记用一个简单的 String 例子讲清楚 move、copy、borrow、lifetime 四个核心概念,以及为什么 Rust 编译期就能挡住 90% 的内存安全问题。
从零写一个 Todo 应用学 Vue 3。本文涵盖 ref、reactive、computed、watch 的使用场景,以及 Pinia 做状态管理的完整流程。代码量不大,胜在概念清晰。
线上 Redis 突然挂了,重启后数据丢了 5 分钟。排查发现只开了 RDB,没开 AOF。本文从原理到实战对比两种持久化:RDB 适合冷备(快/小,但数据可能丢)、AOF 适合热备(慢/大,但能秒级恢复)。最佳实践是混合开启 + appendfsync=everysec。
从 select(轮询)→ poll(链表)→ epoll(红黑树 + 就绪链表)的演进,解释了为什么 Nginx / Redis / Node.js 选 epoll。本文跟着 Linux 5.x 内核源码走读 epoll_create / epoll_ctl / epoll_wait 三大系统调用,以及 LT vs ET 模式的内核实现差异。
第一次用 Docker 打包应用,踩了不少坑(忘记暴露端口、镜像层太多、权限问题)。这篇笔记把 Dockerfile 的最佳实践和常用命令做了一个梳理,适合刚接触容器化的同学。
学着用 K8s 跑项目,故障排查 SOP 整理:CrashLoopBackOff(99% 是镜像/启动命令)、ImagePullBackOff(私有 registry 凭证)、Pending(资源不足/亲和性)、OOMKilled(memory limit)、Liveness 失败(探针配错)…… 每种都有 kubectl 排查命令清单。
普通哈希分片 N 台机器,加 1 台服务器要重算 100% 的 key 归属,雪崩。一致性哈希用环形空间 + 虚拟节点,加 1 台只重新分配 1/N 的 key。本文用 Python 实现了一个最简版本,并讨论了虚拟节点数量、哈希函数选型、热点处理三个工程难点。
一张 200 万行的表,LIKE 查询要 30 秒。加了一个组合索引后变成 0.1 秒。本文记录怎么用 EXPLAIN 分析慢查询、什么时候该建联合索引、什么时候不该建,以及覆盖索引的妙用。
同样是消息队列,RabbitMQ 单机峰值约 5 万 TPS,Kafka 能跑到 200 万。差距来自三个设计:① 顺序追加写磁盘(机械硬盘也能跑出 SSD 速度);② sendfile 零拷贝(数据从磁盘 → 网卡不经用户态);③ Topic 分区并行消费。本文逐一拆解。
除了 B-tree,PG 还有 GIN(数组/JSONB)、BRIN(时序/范围)、Hash、SP-GiST 等多种索引。本文给出一个 5GB 日志表的真实案例,演示用 BRIN 索引把 6 GB 索引压缩到 30 MB,查询性能不降反升。
之前一直在用 cat / find / grep,直到接触了 Rust 生态的现代版本,效率直接翻倍。bat 替代 cat(自带语法高亮)、fd 替代 find(语法更友好)、ripgrep 替代 grep(快到飞起)、fzf 模糊查找(神器)。
JWT 看似简单(三段 base64 拼一拼),但生产环境实际能踩五种坑:① alg:none 攻击;② 密钥太短被暴力破解;③ 没设过期 → 永久 token 泄露;④ 没刷新机制;⑤ 把敏感信息塞 payload。本文每个坑都给修复代码 + 测试用例。
线上每天 200+ 条告警,90% 是误报。重写告警规则三原则:① 阈值用 P99 不用平均;② 持续时间 ≥ 2min 才告警;③ 告警分级(P1/P2/P3 不同通知渠道)。改完之后告警量降到每天 10 条,且每条都值得看。本文给完整的 alerts.yml 模板。
团队从 SVN 迁到 Git 后,大家对 rebase 和 merge 的用法很混乱。这篇笔记总结了:个人分支用 rebase 保持线性、合到 main 用 merge --no-ff 保留历史,以及 squash 合并什么时候用最合适。
面试经典题。Python 一行 functools.lru_cache 搞定,但底层呢?本文实现 4 个版本:① 朴素 list(O(n));② OrderedDict(O(1) 但锁粒度大);③ 双向链表 + HashMap(教科书版);④ Redis LRU 的近似算法(实战版)。
Java 的 TreeMap 用红黑树,Redis 的 ZSET 用跳表。两者时间复杂度都是 O(log n),为什么作者 antirez 选跳表?答:① 实现简单(红黑树调平衡逻辑容易写错);② 范围查询直接遍历底层链表,跳表友好;③ 内存可调(指数控制层数)。
线上压测 QPS 上 1 万就报 "Cannot assign requested address"。排查发现是 TCP TIME_WAIT 堆积,本机短连接耗尽端口。修复路径:① 服务端开启 keepalive 改长连接(根治);② 客户端调 net.ipv4.ip_local_port_range 扩大端口范围(临时);③ 慎开 tcp_tw_reuse(NAT 环境会出问题)。