题目重点:五段 OA 模拟如何维护连接、对象亲和和每台服务的负载,并处理不题目子对 SHUTDOWN 的冲突。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 本训练版选择跨多帖互相印证的最少负载/小下标规则,server 下标从 0 起;容量按活跃连接计。
- 同一个 objectId 只要仍有活跃连接,新连接必须去其 server;满载时拒绝,不破坏亲和。最后一个活跃连接离开后解除绑定。
- SHUTDOWN 训练版临时排除目标 server,先逐出其所有连接,再按 connectionId 稳定顺序重路由,迁移结束后该 server 恢复可用。永久下线是另一帖变体,必须单独确认。
解题路线
- 维护 connId→(userId,objectId,server)、objectId→活跃 connId 集合、每 server 活跃计数。唯一状态来源是 conn 表,两个索引与负载始终与之同步;可以在测试中重新扫描 conn 表断言不变量。
- CONNECT 若 connId 已在活跃表,先按题面约定重复操作:训练版原样返回旧分配且不增加负载。新连接有 object 活跃时检查绑定 server 容量,满则拒绝;无绑定时在所有可用且未满 server 中选 (load,index) 最小。
- DISCONNECT 删除 connId 并减少该 server 计数;从 object 集合删除,集合空时解除绑定。未知 connId 按训练版无状态变化。
- SHUTDOWN 先按稳定 ID 顺序收集受影响连接并逐个移出状态,再把目标 server 排除于候选集,按相同 CONNECT 规则逐个重路由。被拒绝的迁移连接保持断开;结束时解除临时排除。若题面要求永久下线,目标不恢复,未来普通 CONNECT 也排除它。
- 每阶段测一组最小状态转移:并列负载、断开后重用最小 server、最后一个 object 释放、粘性目标已满、全满、迁移容量冲突、重复 connId 与关机 server 空载。
手动走一遍
训练例两个 server 容量 2。CONNECT c1/oA→0;CONNECT c2/oB→1;CONNECT c3/oA 强制→0;此时 CONNECT c4/oA 被拒,即使 server 1 还有空位。DISCONNECT c1 后 c4/oA→0。SHUTDOWN 0 时先逐出 c3、c4,临时只允许 server 1,按 ID 顺序迁移:c3 占 server 1 第二槽,c4 被拒。结束后 server 0 可再接新 object。
规模与取舍
S 台 server、R 条请求、C 个活跃连接:直接扫描选择 server 是每 CONNECT O(S),总 O(RS+C log C)(关机排序总量按实际驱逐计),空间 O(C+S)。若 server 很多可用平衡树/懒堆,但容量、粘性与关机更新会增状态复杂度。
易错点与追问
容易失分的边界
- 只更新负载而忘记 connId/object 索引,断开后仍错误粘性。
- object 目标已满时绕到别台,违反亲和。
- 关机后边驱逐边迁移,未明确是否可回选刚关闭的 server。
- 把 round-robin 与最少负载或永久停机与临时驱逐写成同一固定版本。
- 重复 CONNECT 增加负载两次或输出不稳定。
继续深挖
- 若 SHUTDOWN 后永久不可用,后续 CONNECT 与再次 SHUTDOWN 的状态怎样处理?
- 断开最后一个 object 连接与新连接同时到达时需要哪种序列化?
- 多个真实路由进程如何对 connId、负载和 object 粘性做一致更新?
