性能测试工具bench
This commit is contained in:
50
doc/conclusion.md
Normal file
50
doc/conclusion.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# 性能定位结论(主线程)
|
||||
|
||||
## 1) 主要瓶颈结论
|
||||
|
||||
基于当前主线程采样统计,结论是:
|
||||
|
||||
- **主线程最大开销确实是内存申请/管理相关开销**(而不是纯 memcpy)。
|
||||
- 开销占比大致为:
|
||||
- `submit_write` 打包阶段:约 **61.3%**
|
||||
- 其中 alloc 约 **66.5% of pack**(折算到主线程总开销约 **40.8%**)
|
||||
- copy 约 **14.2% of pack**(折算到主线程总开销约 **8.7%**)
|
||||
- 入队/通知(SPSC push + notify):约 **29.2%**
|
||||
- 回收释放:约 **9.5%**
|
||||
- backpressure 影响很小(loops≈0)
|
||||
|
||||
所以“减少申请内存次数”这个判断是对的,而且是当前最有价值的优化方向。
|
||||
|
||||
---
|
||||
|
||||
## 2) 对方案 2 / 3 的评价(结合本系统)
|
||||
|
||||
### 方案 2:A/B 双 flag 缓冲覆写保护
|
||||
|
||||
- **优点**:实现直观,容易快速落地验证正确性。
|
||||
- **缺点**:
|
||||
- 本质仍是“执行路径与拷贝路径耦合”,请求推进会受慢侧牵制;
|
||||
- 不能从根本上消除 alloc 热点,只是控制覆写时序;
|
||||
- 在高并发下调试成本会上升(状态机与边界条件多)。
|
||||
- **结论**:适合快速试验,不是长期高性能形态。
|
||||
|
||||
### 方案 3:ChainBuffer 所有权移交(摘链/归还)
|
||||
|
||||
- **优点**:
|
||||
- 以“指针/节点移动”替代大量 alloc+copy,方向与当前瓶颈完全一致;
|
||||
- 对大 value、高吞吐场景收益潜力更大。
|
||||
- **缺点**:
|
||||
- 生命周期、并发归还、异常回收都要设计清楚;
|
||||
- 实现复杂度明显高于方案 2。
|
||||
- **结论**:更符合长期性能目标,但需要更严格的工程设计。
|
||||
|
||||
---
|
||||
|
||||
## 3) 哪个在你当前系统里更容易实现?
|
||||
|
||||
如果只比较你给的这两个方案,在你现在的系统里:
|
||||
|
||||
- **更简单的是方案 2(A/B 双 flag)**;
|
||||
- **更值得长期投入的是方案 3(所有权移交)**。
|
||||
|
||||
建议:短期先用方案 2 验证行为边界,最终收敛到方案 3(或其等价的零拷贝所有权模型)。
|
||||
300
doc/interview_answers_aggressive_50.md
Normal file
300
doc/interview_answers_aggressive_50.md
Normal file
@@ -0,0 +1,300 @@
|
||||
# KVStore 激进版:50 题参考回答(含风险等级与避坑话术)
|
||||
|
||||
> 对应文件:`doc/interview_questions_aggressive_50.md`
|
||||
> 建议答题模板:**目标 -> 方案 -> 收益 -> 代价 -> 兜底**
|
||||
|
||||
---
|
||||
|
||||
## 1) 架构与边界(1-5)
|
||||
|
||||
### 1. 分层设计收益与复杂度
|
||||
- **风险等级**:低
|
||||
- **参考回答**:我把系统拆成网络层(收发)、协议层(RESP 解析)、执行层(命令分发)、持久化层(快照/oplog)和复制层(SSYNC+shm)。收益是可替换和可定位问题,比如网络和持久化互不耦合。代价是模块间接口变多,调试时需要跨层追踪。兜底是我保留了主调用链文档,排障按固定链路走。
|
||||
- **避坑话术**:别说“完全解耦”,改成“低耦合、边界清晰”。
|
||||
|
||||
### 2. Reactor vs Proactor/协程
|
||||
- **风险等级**:中
|
||||
- **参考回答**:当前选 Reactor 是因为代码路径短、可控性高,适合先把协议和持久化跑稳。Proactor/协程在高并发下有潜力,但会引入更复杂的调度和状态管理。我的 tradeoff 是先优化主路径和持久化,再评估网络模型切换。
|
||||
- **避坑话术**:不要说“Reactor 一定最快”,要说“在当前代码复杂度和目标下更合适”。
|
||||
|
||||
### 3. 三引擎选型边界
|
||||
- **风险等级**:低
|
||||
- **参考回答**:Array 实现简单但查找线性,适合小规模或验证场景;RBTree 有序且 O(logN),适合有序访问;Hash 平均 O(1),适合热点随机读写。收益是能覆盖不同 workload。代价是维护三套实现和一致性语义。
|
||||
- **避坑话术**:不要泛泛说“都很快”,要给出复杂度和场景。
|
||||
|
||||
### 4. 主路径轻量化
|
||||
- **风险等级**:中
|
||||
- **参考回答**:主线程主要做解析、执行、回包,持久化提交走 io_uring worker。收益是减少 I/O 阻塞对主循环影响。代价是异步链路更复杂,需要回收队列和背压。我通过 destroy queue + wakeup 回收来控风险。
|
||||
- **避坑话术**:别说“主线程无开销”,保留“主要开销下降”。
|
||||
|
||||
### 5. 多核扩展优先级
|
||||
- **风险等级**:中
|
||||
- **参考回答**:我会先做连接分片,再做数据分片。连接分片改动小、收益快;数据分片需要引擎和一致性改造,复杂度高。tradeoff 是短期吞吐提升 vs 长期架构演进,我会分两阶段做。
|
||||
- **避坑话术**:不要一次性承诺“全做完”,强调迭代路线。
|
||||
|
||||
---
|
||||
|
||||
## 2) 协议与解析(6-10)
|
||||
|
||||
### 6. 半包/多包/粘包与错误恢复
|
||||
- **风险等级**:低
|
||||
- **参考回答**:我按“可消费字节”循环解析,len=0 视为半包等待下次,len<0 视为协议错误。收益是能稳定处理 pipeline。代价是错误策略偏严格,遇坏包直接断链。这是在安全性和可恢复性之间偏安全的选择。
|
||||
- **避坑话术**:别说“能恢复所有坏包”。
|
||||
|
||||
### 7. binary-safe 为何用 slice
|
||||
- **风险等级**:低
|
||||
- **参考回答**:因为 key/value 可能包含 `\0` 和二进制字节,C 字符串 API 会截断。slice(ptr+len)能保留完整字节语义。收益是协议正确性和通用性更强,代价是代码里长度参数管理更繁琐。
|
||||
- **避坑话术**:强调“正确性优先”。
|
||||
|
||||
### 8. 恶意请求限制
|
||||
- **风险等级**:中
|
||||
- **参考回答**:我在协议层设置了 bulk 上限和参数上限,同时连接层有读写缓冲上限。收益是避免单连接吃光内存。代价是极端合法请求也可能被拒绝。我会通过可配置阈值平衡安全和业务需求。
|
||||
- **避坑话术**:不要说“完全防攻击”,说“降低风险面”。
|
||||
|
||||
### 9. inline 与 multibulk 共存
|
||||
- **风险等级**:低
|
||||
- **参考回答**:如果首字节不是 `*`,走 inline;是 `*` 就走 multibulk。收益是兼容 Redis 常见输入。代价是代码路径多一支,但复杂度可控。
|
||||
- **避坑话术**:不要说“全面兼容 Redis”,说“覆盖当前命令集下的 RESP2 常用场景”。
|
||||
|
||||
### 10. 新命令最小改动
|
||||
- **风险等级**:中
|
||||
- **参考回答**:当前是命令枚举 + dispatch switch,新增命令主要改解析映射和执行分支。收益是性能直观、可调试。代价是规模大时 switch 变长。我会在命令数继续增长时再抽象为表驱动。
|
||||
- **避坑话术**:别提前宣称“完全插件化”。
|
||||
|
||||
---
|
||||
|
||||
## 3) ChainBuffer 与“零拷贝”(11-15)
|
||||
|
||||
### 11. 零拷贝边界
|
||||
- **风险等级**:高
|
||||
- **参考回答**:接收阶段是 readv 直写到链式缓冲,减少中转拷贝;发送阶段用 sendmsg 聚合。当前仍存在线性化/打包场景下的 memcpy,所以更准确是“低拷贝主路径 + 局部拷贝回退”。tradeoff 是实现复杂度可控,同时先拿到主要收益。
|
||||
- **避坑话术**:主动说“不是全链路绝对 0 拷贝”。
|
||||
|
||||
### 12. linearize 触发条件
|
||||
- **风险等级**:中
|
||||
- **参考回答**:当上层需要连续字节视图而数据跨 chunk 时触发 linearize。收益是简化了解析和执行接口。代价是触发时会有额外 memcpy,影响尾延迟。我会通过 chunk 策略和请求分布降低触发频率。
|
||||
- **避坑话术**:不要说“从不 linearize”。
|
||||
|
||||
### 13. free_list 选型
|
||||
- **风险等级**:低
|
||||
- **参考回答**:free_list 复用 chunk,减少频繁 malloc/free 抖动。收益是吞吐更稳、分配开销更低。代价是会保留一定空闲内存。通过 free_limit 做上限控制,平衡性能和内存占用。
|
||||
- **避坑话术**:别说“零内存浪费”。
|
||||
|
||||
### 14. 大小 Key 混跑碎片问题
|
||||
- **风险等级**:中
|
||||
- **参考回答**:我用固定 chunk + 链式扩展,先保证正确和稳定。大 Key 会占多 chunk,可能带来局部碎片;收益是实现简单、行为可预测。后续可按 key size 分层 chunk 策略优化。
|
||||
- **避坑话术**:承认“有优化空间”更可信。
|
||||
|
||||
### 15. 部分发送一致性
|
||||
- **风险等级**:低
|
||||
- **参考回答**:sendmsg 返回 n 后按字节 drain 缓冲,未发完保留在 wbuf,EPOLLOUT 下次继续。收益是协议字节流不会错位。代价是状态维护复杂一点,但这是非阻塞发送必须的成本。
|
||||
- **避坑话术**:别说“一次 send 一定发完”。
|
||||
|
||||
---
|
||||
|
||||
## 4) 所有权移交与并发安全(16-20)
|
||||
|
||||
### 16. 所有权定义
|
||||
- **风险等级**:高
|
||||
- **参考回答**:我的定义是“谁持有谁负责释放”,通过 detach/release 把片段生命周期显式化。收益是未来可做执行-落盘低拷贝协作。代价是引用计数和回收时序更复杂。当前实现已提供接口,进一步全链路化是下一阶段。
|
||||
- **避坑话术**:明确“已实现接口与局部机制,非全链路完成”。
|
||||
|
||||
### 17. UAF / double free 防护
|
||||
- **风险等级**:中
|
||||
- **参考回答**:通过 refcnt + release 路径统一回收,避免多方直接 free。收益是降低并发回收风险。代价是需要严格约束调用顺序和异常路径。排查时我会优先核对 detach/release 对称性。
|
||||
- **避坑话术**:别说“绝对不会 UAF”,说“通过机制显著降低风险”。
|
||||
|
||||
### 18. 连接关闭后的回收
|
||||
- **风险等级**:中
|
||||
- **参考回答**:连接关闭只释放连接侧对象,已移交片段由持有方继续走 release。收益是不会因连接断开丢失回收路径。代价是关闭逻辑需要区分“本地拥有”和“已移交”。
|
||||
- **避坑话术**:避免一句话“直接全清掉”。
|
||||
|
||||
### 19. 谁申请谁释放
|
||||
- **风险等级**:低
|
||||
- **参考回答**:这是为了避免跨线程释放带来的生命周期混乱。收益是定位泄漏和崩溃更直观。代价是需要一个回收协作队列,代码量会增加。总体是工程上更稳的 tradeoff。
|
||||
- **避坑话术**:强调“可维护性收益”。
|
||||
|
||||
### 20. 真正 0 拷贝落盘约束
|
||||
- **风险等级**:高
|
||||
- **参考回答**:要做到真正 0 拷贝,需要落盘线程直接消费网络片段并延迟释放,约束包括引用计数、回收屏障和慢盘背压。收益是减少打包复制。代价是并发复杂度显著上升,错误成本更高。
|
||||
- **避坑话术**:别承诺“短期必做完”,给阶段目标。
|
||||
|
||||
---
|
||||
|
||||
## 5) io_uring 流水线(21-25)
|
||||
|
||||
### 21. n*SPSC vs MPSC
|
||||
- **风险等级**:中
|
||||
- **参考回答**:n*SPSC 的好处是队列局部性好、竞争少,延迟更稳;代价是负载均衡和线程参数调优复杂。MPSC 实现集中但热点明显。当前我更看重稳定性,所以先用 n*SPSC。
|
||||
- **避坑话术**:不要否定 MPSC,强调场景选择。
|
||||
|
||||
### 22. 80% 水位
|
||||
- **风险等级**:中
|
||||
- **参考回答**:80% 是保护阈值,目的是给 CQE 回收和突发流量留缓冲。收益是降低 overflow 风险。代价是峰值吞吐可能不是最大。这个值不是常量真理,我会按压测再调。
|
||||
- **避坑话术**:不要说“最优解”,说“保守工程值”。
|
||||
|
||||
### 23. 背压策略
|
||||
- **风险等级**:中
|
||||
- **参考回答**:队列满时会回收已完成任务并让出 CPU,必要时限流连接。收益是系统不崩。代价是尾延迟上升。tradeoff 是优先保活再保时延。
|
||||
- **避坑话术**:别说“无损无延迟”。
|
||||
|
||||
### 24. 批量回收
|
||||
- **风险等级**:低
|
||||
- **参考回答**:批量偷取 destroy queue 能减少锁/原子开销和碎片回收抖动。收益是主循环更平滑。代价是回收时点有批处理延迟。这个延迟通常可接受。
|
||||
- **避坑话术**:承认“不是实时逐条释放”。
|
||||
|
||||
### 25. 优雅停机
|
||||
- **风险等级**:中
|
||||
- **参考回答**:停机流程是 stop 标志 -> 唤醒 worker -> drain 队列 -> join 线程 -> 清理剩余任务。收益是尽量保证数据路径收敛完成。代价是停机时间变长。这里优先数据完整性。
|
||||
- **避坑话术**:别说“秒停”,说“可控停机”。
|
||||
|
||||
---
|
||||
|
||||
## 6) 快照 + 增量一致性(26-30)
|
||||
|
||||
### 26. 一致性窗口
|
||||
- **风险等级**:高
|
||||
- **参考回答**:快照代表某个时间点状态,后续变更由 oplog 补齐。收益是写入不中断。代价是天然存在窗口,需要恢复阶段串联重放。这个设计是吞吐优先下的最终一致方案。
|
||||
- **避坑话术**:不要声称“强一致快照”。
|
||||
|
||||
### 27. 先快照后回放
|
||||
- **风险等级**:低
|
||||
- **参考回答**:快照是基线,oplog 是增量。先加载基线再套增量语义清晰。收益是恢复逻辑简单。代价是快照越旧回放越长。可通过更频繁快照平衡。
|
||||
- **避坑话术**:说明“恢复时间与快照频率 tradeoff”。
|
||||
|
||||
### 28. 命令字节流日志
|
||||
- **风险等级**:中
|
||||
- **参考回答**:命令字节流实现快、复用现有解析器,开发成本低。代价是回放时要重新解析执行,效率不如结构化 WAL。当前选择是快速迭代优先,后续可演进为结构化记录。
|
||||
- **避坑话术**:承认“不是最终形态”。
|
||||
|
||||
### 29. 坏日志策略
|
||||
- **风险等级**:高
|
||||
- **参考回答**:当前更偏“发现坏日志就失败退出”,先保证正确性边界。收益是避免静默数据错误。代价是可用性下降。生产化可加校验和分段容错,再做可恢复降级。
|
||||
- **避坑话术**:不要说“自动修复所有坏日志”。
|
||||
|
||||
### 30. 状态边界证明
|
||||
- **风险等级**:高
|
||||
- **参考回答**:我会把边界定义成“快照点 + 之后成功持久化的增量”。收益是定义清楚,便于测试。代价是需要故障注入验证不同崩溃点。我的做法是先给出可验证边界,而不是口头保证。
|
||||
- **避坑话术**:避免绝对词“完全一致”。
|
||||
|
||||
---
|
||||
|
||||
## 7) 主从与状态机(31-35)
|
||||
|
||||
### 31. 状态机描述
|
||||
- **风险等级**:中
|
||||
- **参考回答**:slave 发 SSYNC 申请全量,master 异步产出并发送 snapshot,slave 落盘后回 SREADY,再进入增量流。收益是流程清晰且可扩展。代价是阶段切换复杂,需要严格顺序控制。
|
||||
- **避坑话术**:别忽略“阶段切换失败处理”。
|
||||
|
||||
### 32. 快照期间新写入
|
||||
- **风险等级**:高
|
||||
- **参考回答**:思路是用 seq 把快照基线和增量窗口连接起来。收益是减少丢数据窗口。代价是实现复杂,需要状态机和顺序保证。当前代码有通道和钩子,协同还在持续完善。
|
||||
- **避坑话术**:一定说“机制已搭,协同在完善中”。
|
||||
|
||||
### 33. wrap marker 可行性
|
||||
- **风险等级**:中
|
||||
- **参考回答**:尾部放不下时写 wrap marker 并回到 0,消费者识别后跳转。收益是实现简单。代价是需要严格保证读写顺序和越界检查。适合单写者模型。
|
||||
- **避坑话术**:别说“多写者也没问题”。
|
||||
|
||||
### 34. seq 断档处理
|
||||
- **风险等级**:高
|
||||
- **参考回答**:断档处理要看目标:一致性优先就阻塞/重建,可用性优先可短暂跳过并告警。我的偏好是关键链路一致性优先。代价是短期可用性受影响。
|
||||
- **避坑话术**:避免“所有场景一个策略”。
|
||||
|
||||
### 35. eBPF 控制面定位
|
||||
- **风险等级**:中
|
||||
- **参考回答**:我把 eBPF 钩子放控制面,用于状态切换和转发触发,不直接承载主数据处理。收益是降低主路径侵入。代价是又多一层调试复杂度。
|
||||
- **避坑话术**:别说“eBPF 加速了所有链路”。
|
||||
|
||||
---
|
||||
|
||||
## 8) 内存分配器与内存池(36-40)
|
||||
|
||||
### 36. 分级依据
|
||||
- **风险等级**:低
|
||||
- **参考回答**:8-512B 覆盖高频小对象,按 8B 对齐分桶,页内 free-list 管理。收益是分配释放路径短。代价是可能有内部碎片。属于延迟优先的选择。
|
||||
- **避坑话术**:不要回避碎片问题。
|
||||
|
||||
### 37. 大对象回退 malloc
|
||||
- **风险等级**:低
|
||||
- **参考回答**:大对象生命周期和尺寸离散,放进小块池会放大管理成本。回退系统分配更简单。收益是降低池复杂度。代价是大块分配性能受系统 allocator 影响。
|
||||
- **避坑话术**:别说“mempool 覆盖全部场景”。
|
||||
|
||||
### 38. 空闲页回收
|
||||
- **风险等级**:中
|
||||
- **参考回答**:我保留一定空闲页做缓存,超过阈值再释放,平衡复用和内存占用。收益是减少抖动。代价是峰值内存更高。阈值可按业务压测调。
|
||||
- **避坑话术**:强调“可调参数”。
|
||||
|
||||
### 39. 三 allocator 差异来源
|
||||
- **风险等级**:中
|
||||
- **参考回答**:差异主要来自小对象分配路径、锁竞争、缓存复用和写盘模式耦合。mypool 在当前 workload 下命中率高,所以吞吐更好。代价是通用性不一定优于成熟 allocator。
|
||||
- **避坑话术**:别说“mypool 永远最优”。
|
||||
|
||||
### 40. 内存异常排查优先级
|
||||
- **风险等级**:低
|
||||
- **参考回答**:先看 RSS、分配失败、队列积压、in-flight、回收延迟,再看对象分布。收益是先定位“增长来源”再定位“泄漏点”。代价是需要加一些可观测指标。
|
||||
- **避坑话术**:别一上来就说“就是泄漏”。
|
||||
|
||||
---
|
||||
|
||||
## 9) 压测方法学(41-45)
|
||||
|
||||
### 41. 复现性保证
|
||||
- **风险等级**:低
|
||||
- **参考回答**:固定参数、固定轮次、分组合独立目录、每轮重启,保存原始日志与 CSV。收益是可回放可核对。代价是执行时间更长。
|
||||
- **避坑话术**:不要只报“最好一轮数据”。
|
||||
|
||||
### 42. bench vs testcase 取舍
|
||||
- **风险等级**:中
|
||||
- **参考回答**:bench 更灵活,但随机 key 与 RSET 插入语义会碰撞;testcase mode=4 更稳定,适合长期对比。tradeoff 是灵活性 vs 稳定性。
|
||||
- **避坑话术**:主动解释语义差异,避免被质疑口径不一致。
|
||||
|
||||
### 43. QPS 口径
|
||||
- **风险等级**:中
|
||||
- **参考回答**:我用“完成请求数/耗时”,并明确是否包含错误。收益是可比较。代价是不同工具默认口径不同,需要文档化。
|
||||
- **避坑话术**:别把不同口径结果直接横比。
|
||||
|
||||
### 44. 避免虚高
|
||||
- **风险等级**:低
|
||||
- **参考回答**:做预热、控制 keyspace、分离预填充和正式压测、多轮取均值并看波动。收益是结果更稳。代价是实验时间增加。
|
||||
- **避坑话术**:不要只强调峰值,不报波动。
|
||||
|
||||
### 45. 波动解释
|
||||
- **风险等级**:中
|
||||
- **参考回答**:波动来自调度、缓存、I/O 抖动和后台回收。我的做法是看均值+CV,不用单轮结论。tradeoff 是展示更真实但数字不一定最亮眼。
|
||||
- **避坑话术**:别把异常轮次“隐去不提”。
|
||||
|
||||
---
|
||||
|
||||
## 10) 真实性与演进(46-50)
|
||||
|
||||
### 46. 零拷贝表述边界
|
||||
- **风险等级**:高
|
||||
- **参考回答**:我会说“接收/发送主路径低拷贝,局部场景有拷贝回退”,而不是“全链路绝对零拷贝”。收益是表达亮点同时不失真。代价是表述没那么激进。
|
||||
- **避坑话术**:先给边界,再讲优化方向。
|
||||
|
||||
### 47. 状态机协同实现到哪
|
||||
- **风险等级**:高
|
||||
- **参考回答**:SSYNC/SREADY、快照传输、增量通道与 seq 机制已打通;全量-增量无缝协同仍在完善。这样说能体现工程进度和规划。
|
||||
- **避坑话术**:别说“完全解决协同一致性”。
|
||||
|
||||
### 48. 两周落地计划
|
||||
- **风险等级**:中
|
||||
- **参考回答**:第 1 周先补一致性边界和故障注入测试;第 2 周做所有权移交闭环和指标监控。收益是先补正确性再补性能。代价是短期新功能延后。
|
||||
- **避坑话术**:给里程碑,不要空谈“能做完”。
|
||||
|
||||
### 49. 最大技术债
|
||||
- **风险等级**:中
|
||||
- **参考回答**:最大的债是“协同一致性语义和容错测试还不够系统化”。我优先做了主链路可运行和性能基线。tradeoff 是先可用再完善严谨性。
|
||||
- **避坑话术**:承认技术债并给修复计划,面试官反而更认可。
|
||||
|
||||
### 50. 三人小组下一版目标
|
||||
- **风险等级**:低
|
||||
- **参考回答**:目标按优先级:一致性文档+故障矩阵、可观测性、性能回归门禁。验收指标包括恢复正确率、复制延迟、QPS/CV 基线。tradeoff 是减少“新功能数量”,换“上线可信度”。
|
||||
- **避坑话术**:不要只提“再提 2 倍 QPS”。
|
||||
|
||||
---
|
||||
|
||||
## 快速复习(高风险题清单)
|
||||
- **高风险题**:11, 16, 20, 26, 29, 30, 32, 34, 46, 47
|
||||
- **统一策略**:先讲“已实现边界”,再讲“预案与下一步”,避免绝对化承诺。
|
||||
76
doc/interview_questions_aggressive_50.md
Normal file
76
doc/interview_questions_aggressive_50.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# KVStore 激进版本:面试高频追问 50 题(含 Tradeoff 视角)
|
||||
|
||||
## 回答建议(统一框架)
|
||||
- 建议每题按「目标 -> 方案 -> 收益 -> 代价 -> 兜底」回答。
|
||||
- 收益常见维度:吞吐、时延、稳定性、可维护性、可扩展性。
|
||||
- 代价常见维度:实现复杂度、内存开销、排障成本、一致性窗口、开发周期。
|
||||
|
||||
## 1) 架构与边界(1-5)
|
||||
1. 你把系统拆成了哪些层(网络/协议/执行/持久化/复制)?这种分层带来的收益与额外复杂度分别是什么?
|
||||
2. 为什么默认选择 Reactor 而不是 Proactor/协程网络模型?三者在吞吐、延迟、开发复杂度上的 tradeoff 是什么?
|
||||
3. Array/RBTree/Hash 三种引擎的选型边界是什么?在不同数据分布下的性能收益与维护成本如何权衡?
|
||||
4. 你说“主路径轻量化”,具体删掉了哪些主线程工作?对 CPU 利用率与代码复杂度的 tradeoff 是什么?
|
||||
5. 如果要做多核扩展,你会优先做连接分片还是数据分片?两者在扩展性与一致性上的代价分别是什么?
|
||||
|
||||
## 2) 协议与解析(6-10)
|
||||
6. RESP 解析如何处理半包/多包/粘包?选择“严格报错”还是“尽量恢复”的 tradeoff 是什么?
|
||||
7. binary-safe 为什么必须用 slice(ptr+len)而不是 C 字符串?这对性能和代码可读性有什么影响?
|
||||
8. 你如何限制恶意请求(超大 bulk、超多参数)?安全性提升与正常流量误伤之间如何平衡?
|
||||
9. inline 与 multibulk 共存时如何处理优先级?兼容性收益与实现复杂度代价分别是什么?
|
||||
10. 新增命令时如何保证最小改动?抽象过度与快速迭代之间的 tradeoff 怎么拿捏?
|
||||
|
||||
## 3) ChainBuffer 与“零拷贝”追问(11-15)
|
||||
11. readv 直写后用户态还会发生哪些拷贝?你如何定义“零拷贝”和“低拷贝”的边界?
|
||||
12. chain_buffer_linearize 何时触发?减少复杂解析逻辑与引入额外 memcpy 的 tradeoff 是什么?
|
||||
13. 为什么要做 chunk free_list?复用内存带来的性能收益与内存峰值风险如何平衡?
|
||||
14. 大 Key(64KB)与小 Key 混跑时,chunk 策略如何避免碎片化?吞吐和内存效率谁优先?
|
||||
15. sendmsg 聚合发送遇到部分发送时如何保证一致性?更高吞吐与更复杂状态管理如何权衡?
|
||||
|
||||
## 4) 所有权移交与并发安全(16-20)
|
||||
16. “执行-落盘共享缓冲片段”如何定义所有权?减少拷贝收益与生命周期复杂度代价怎么评估?
|
||||
17. detach/release 如何避免 UAF/double free?你牺牲了哪些性能换取内存安全?
|
||||
18. 连接提前关闭时已移交数据如何回收?优先保证数据安全还是优先快速释放资源?
|
||||
19. 为什么采用“谁申请谁释放”?跨线程释放带来的便利与隐患如何取舍?
|
||||
20. 若做真正 0 拷贝落盘,你会接受哪些新增约束(引用计数/锁/回收时序)?
|
||||
|
||||
## 5) io_uring 持久化流水线(21-25)
|
||||
21. n*SPSC 相比单队列 MPSC 的收益和代价分别是什么?你为什么在当前阶段选 n*SPSC?
|
||||
22. in-flight 上限为何设为 CQ 的 80%?保守水位与峰值吞吐之间如何权衡?
|
||||
23. 队列满时背压策略是什么?“保护系统稳定”与“牺牲尾延迟”之间如何取舍?
|
||||
24. destroy_queue 用批量偷取+集中释放的动机是什么?释放抖动与主循环平滑性如何平衡?
|
||||
25. shutdown 阶段如何保证无悬挂任务?优雅退出时间与数据完整性哪个优先?
|
||||
|
||||
## 6) 快照 + 增量日志一致性(26-30)
|
||||
26. SAVE 与 oplog append 并发时一致性窗口怎么定义?强一致与吞吐的 tradeoff 是什么?
|
||||
27. 为什么恢复顺序是“先快照后 oplog”?恢复速度与恢复正确性之间如何权衡?
|
||||
28. oplog 记录命令字节流而不是逻辑变更,优势和成本分别是什么?
|
||||
29. replay 遇到坏日志时你会“失败退出”还是“跳过继续”?可用性与正确性怎么选?
|
||||
30. 你如何说明恢复后状态边界?文档化成本与实现灵活性的 tradeoff 是什么?
|
||||
|
||||
## 7) 主从同步与状态机(31-35)
|
||||
31. 请描述 SSYNC -> Snapshot -> SREADY -> Incremental 状态机,并说明每步的收益与风险。
|
||||
32. 快照传输期间新写入如何不丢?延迟增大与一致性增强之间怎么平衡?
|
||||
33. 共享内存 ring wrap marker 方案为什么可行?简单实现与健壮性之间的代价是什么?
|
||||
34. seq 不连续时你为何选择阻塞/跳过/重建?各策略的可用性与数据风险如何比较?
|
||||
35. eBPF uprobe 放在控制面而非数据面的考量是什么?观测能力与运行时开销如何权衡?
|
||||
|
||||
## 8) 内存分配器与内存池(36-40)
|
||||
36. mempool 分级(8-512B)的依据是什么?固定桶命中率与碎片风险如何平衡?
|
||||
37. 大对象回退 malloc 的原因是什么?统一路径与分层路径在复杂度上怎么取舍?
|
||||
38. mempool 如何处理空闲页回收?低延迟复用与低内存占用的 tradeoff 怎么设定?
|
||||
39. malloc/jemalloc/mypool 在你的 workload 下差异来自哪里?泛化能力与场景优化如何平衡?
|
||||
40. 线上内存峰值异常时先看哪些指标?指标全面性与观测成本如何取舍?
|
||||
|
||||
## 9) 压测方法学与结果可信度(41-45)
|
||||
41. 你如何保证 benchmark 可复现?“实验真实度”与“执行成本”之间怎么平衡?
|
||||
42. 为什么有些场景用 bench.c,有些改用 testcase mode=4?语义准确与工具统一如何取舍?
|
||||
43. QPS 统计口径怎么定义?是否包含失败请求?可比性与直观性之间如何平衡?
|
||||
44. 如何避免预热不足/缓存命中导致虚高?测试严谨性与测试周期如何平衡?
|
||||
45. 如何解释 round 间波动(CV)?追求峰值还是追求稳定性的 tradeoff 是什么?
|
||||
|
||||
## 10) 真实性、边界与演进(46-50)
|
||||
46. 简历里“零拷贝”哪些已落地,哪些是低拷贝/预案?为什么这样表述?
|
||||
47. 简历里“协同状态机”当前实现到哪一步?工程现实与对外表达如何平衡?
|
||||
48. 若给你 2 周把预案落地,你的里程碑怎么排?短期收益与长期架构如何取舍?
|
||||
49. 当前最大技术债是什么?为什么没有先修?业务推进与技术治理如何平衡?
|
||||
50. 若带 3 人继续做,下版目标与验收指标是什么?功能扩展与稳定性建设如何排序?
|
||||
25
doc/resume.tex
Normal file
25
doc/resume.tex
Normal file
@@ -0,0 +1,25 @@
|
||||
\section{项目经历}
|
||||
|
||||
\ResumeItem[KVStore 高性能 KV 存储系统(RESP 兼容 + 异步持久化 + 主从同步)]
|
||||
{\textbf{KVStore} 高性能 KV 存储系统(RESP 兼容 + 异步持久化 + 主从同步)}
|
||||
[个人项目|独立开发]
|
||||
[2025.03 --- 2026.03]
|
||||
\begin{itemize}
|
||||
\item 基于 \textbf{C + Linux} 从零实现单机 KV 服务:支持 \textbf{RESP2 协议解析}、pipeline 与 binary-safe(支持 \texttt{\textbackslash 0}),并统一接入 \textbf{Array / RBTree / Hash} 三类存储引擎。
|
||||
\item 实现链式网络缓冲 \textbf{ChainBuffer}:通过 \textbf{readv/sendmsg} 构建分段零拷贝收发路径,支持大 Key 与半包/多包场景;提供 \textbf{detach/release} 所有权接口,支持后续执行-落盘共享同一数据片段。
|
||||
\item 实现 \textbf{io\_uring + n*SPSC} 异步落盘模型:主线程执行后写入增量日志,worker 线程批量提交 \textbf{writev};通过 in-flight 控制、队列背压、destroy-queue 回收,避免 CQ 溢出与内存失控。
|
||||
\item 设计并落地“\textbf{快照 + 增量日志}”恢复链路:支持启动加载快照并回放 oplog;支持 \textbf{SSYNC $\rightarrow$ 快照传输 $\rightarrow$ SREADY $\rightarrow$ 增量同步} 的主从接管流程,并预留 eBPF uprobe 协同点。
|
||||
\item 实现可插拔内存分配策略(\textbf{malloc/jemalloc/mypool}):自研 mempool 采用 8--512B 分级桶 + 页级 free-list;在 allocator$\times$persistence 复测中,\textbf{mypool} 吞吐最佳(none: 924878 QPS,incremental: 747101 QPS)。
|
||||
\item 构建 hiredis 功能/压测工具链(\texttt{testcase + bench + 自动化脚本}),沉淀多轮可复现实验口径;将关键优化量化为可交付结果(如 ChainBuffer 改造后写路径 QPS 提升约 \textbf{27\%})。
|
||||
\end{itemize}
|
||||
|
||||
\ResumeItem[EncryptSql 基于 PostgreSQL 的透明加密查询与运算框架]
|
||||
{\textbf{EncryptSQL} 基于 PostgreSQL 的透明加密查询与运算框架}
|
||||
[学校横向|部分代码开发]
|
||||
[2024.09 --- 2025.09]
|
||||
\begin{itemize}
|
||||
\item 在客户端侧对 \textbf{libpq} 进行改造,实现 \textbf{SQL 解析后重写}:将原生表达式/运算符节点替换为密态版本函数/算子调用,尽量保证业务侧无侵入接入。
|
||||
\item 基于 \textbf{PostgreSQL 扩展机制}(自定义函数/算子等)接入密态运算:支持常见算术计算(加/减/乘/除)与部分聚合能力,并与查询执行流程集成。
|
||||
\item 设计并实现基于工厂模式的 \textbf{KMS 接口层}:在 \texttt{encryptsql} 组件中统一密钥获取与管理流程,完成 \textbf{LocalKMS} 与 \textbf{Huawei KMS API} 适配,支持外部 KMS 平滑替换。
|
||||
\item 面向高安全计算场景,引入 \textbf{TEE} 承载关键运算链路,在安全性与性能开销之间做工程化平衡。
|
||||
\end{itemize}
|
||||
25
doc/resume_aggressive.tex
Normal file
25
doc/resume_aggressive.tex
Normal file
@@ -0,0 +1,25 @@
|
||||
\section{项目经历}
|
||||
|
||||
\ResumeItem[KVStore 高性能 KV 存储系统(激进表达版)]
|
||||
{\textbf{KVStore} 高性能 KV 存储系统(零拷贝接收 + 异步持久化 + 主从协同状态机)}
|
||||
[个人项目|独立开发]
|
||||
[2025.03 --- 2026.03]
|
||||
\begin{itemize}
|
||||
\item 基于 \textbf{C + Linux} 实现 RESP 兼容 KV 存储内核,支持 \textbf{binary-safe}、pipeline 与多引擎统一分发(Array/RBTree/Hash),形成协议层到执行层的一体化数据通路。
|
||||
\item 围绕大 Key 场景实现 \textbf{ChainBuffer 分段零拷贝接收}:采用 \textbf{readv/sendmsg} 与链式 chunk 组织,支持超大请求分段处理;按线上保护阈值将单请求上限收敛至 \textbf{65535} 字节级别。
|
||||
\item 实现并演进 \textbf{所有权移交} 机制:主线程仅负责命令边界识别与执行,落盘线程复用网络缓冲片段进行持久化,减少主路径内存申请/对象拼装开销。
|
||||
\item 搭建 \textbf{io\_uring + n*SPSC} 持久化流水线:worker 批量提交 writev,主线程异步回收完成任务;结合 in-flight 背压与 destroy-queue,稳定处理慢盘与高并发写入抖动。
|
||||
\item 设计“\textbf{快照 + 增量日志 + 实时复制}”协同方案:通过 \textbf{SSYNC $\rightarrow$ Snapshot $\rightarrow$ SREADY $\rightarrow$ Incremental} 状态机衔接全量与增量,保障复制窗口内的可恢复性与顺序一致性。
|
||||
\item 构建多维压测体系(功能正确性/吞吐/波动):在 allocator$\times$persistence 复测中,\textbf{mypool} 取得最佳吞吐(none: 924878 QPS,incremental: 747101 QPS),并将优化效果沉淀为工程基线。
|
||||
\end{itemize}
|
||||
|
||||
\ResumeItem[EncryptSql 基于 PostgreSQL 的透明加密查询与运算框架]
|
||||
{\textbf{EncryptSQL} 基于 PostgreSQL 的透明加密查询与运算框架}
|
||||
[学校横向|部分代码开发]
|
||||
[2024.09 --- 2025.09]
|
||||
\begin{itemize}
|
||||
\item 在客户端侧改造 \textbf{libpq} 并实现 \textbf{SQL AST 重写}:将明文表达式自动替换为密态函数/算子调用,降低业务系统改造成本。
|
||||
\item 基于 \textbf{PostgreSQL 扩展机制}接入密态算子,支持加/减/乘/除与部分聚合能力,形成可落地的“密文存储 + 密态计算”执行路径。
|
||||
\item 设计并实现 \textbf{KMS 工厂接口框架},完成 \textbf{LocalKMS/Huawei KMS} 适配,支持多云与私有化 KMS 的低成本切换。
|
||||
\item 在高敏感计算场景引入 \textbf{TEE},对关键流程进行可信执行与边界隔离,平衡安全目标与查询性能。
|
||||
\end{itemize}
|
||||
25
doc/resume_conservative.tex
Normal file
25
doc/resume_conservative.tex
Normal file
@@ -0,0 +1,25 @@
|
||||
\section{项目经历}
|
||||
|
||||
\ResumeItem[KVStore 高性能 KV 存储系统(保守版)]
|
||||
{\textbf{KVStore} 高性能 KV 存储系统(RESP 兼容 + 异步持久化 + 主从同步)}
|
||||
[个人项目|独立开发]
|
||||
[2025.03 --- 2026.03]
|
||||
\begin{itemize}
|
||||
\item 基于 \textbf{C + Linux} 实现单机 KV 服务,支持 \textbf{RESP2} 解析、pipeline 与 binary-safe(支持 \texttt{\textbackslash 0})键值处理。
|
||||
\item 统一命令分发层,接入 \textbf{Array / RBTree / Hash} 三种引擎,实现 SET/GET/DEL 及对应 R*/H* 命令族。
|
||||
\item 实现 \textbf{ChainBuffer} 分段网络缓冲:接收侧使用 \textbf{readv} 直写,发送侧使用 \textbf{sendmsg} 聚合发送,并通过 linearize 处理跨分段解析场景。
|
||||
\item 实现 \textbf{io\_uring + n*SPSC} 异步增量日志写入,包含 in-flight 限流、背压与完成队列回收,降低主线程阻塞。
|
||||
\item 实现“\textbf{快照 + 增量日志}”恢复路径:支持 SAVE 快照、oplog 回放;支持 \textbf{SSYNC/SREADY} 启动同步与共享内存增量通道。
|
||||
\item 构建 hiredis 功能/性能测试工具链;在 2026-03-04 的 allocator$\times$persistence 复测中,\textbf{mypool} 组合吞吐最佳(none: 924878 QPS,incremental: 747101 QPS)。
|
||||
\end{itemize}
|
||||
|
||||
\ResumeItem[EncryptSql 基于 PostgreSQL 的透明加密查询与运算框架]
|
||||
{\textbf{EncryptSQL} 基于 PostgreSQL 的透明加密查询与运算框架}
|
||||
[学校横向|部分代码开发]
|
||||
[2024.09 --- 2025.09]
|
||||
\begin{itemize}
|
||||
\item 在客户端侧对 \textbf{libpq} 进行改造,实现 \textbf{SQL 解析后重写}:将原生表达式/运算符节点替换为密态函数/算子调用,尽量保证业务侧无侵入接入。
|
||||
\item 基于 \textbf{PostgreSQL 扩展机制}(自定义函数/算子等)接入密态运算:支持常见算术计算(加/减/乘/除)与部分聚合能力,并与执行流程集成。
|
||||
\item 设计并实现基于工厂模式的 \textbf{KMS 接口层}:在 \texttt{encryptsql} 中统一密钥获取与管理流程,完成 \textbf{LocalKMS} 与 \textbf{Huawei KMS API} 适配。
|
||||
\item 面向高安全计算场景,引入 \textbf{TEE} 承载关键运算链路,在安全性与性能开销之间做工程化平衡。
|
||||
\end{itemize}
|
||||
Reference in New Issue
Block a user