Contents

第十章 住宿、床位与并发

该文档说明如何用按床位锁、按学生锁与数据库唯一约束三层机制,防止数千人并发选宿时重复分配床位,并介绍宿舍层级模型、学院床位池与分组准入等配置化设计。

  • 床位不超卖靠数据唯一约束兜底,不依赖程序判断
  • 并发保护分三层:床位锁、学生锁、数据库唯一约束
  • 宿舍层级从校区到床位,组团与住户级可留空
  • 资格校验须覆盖查看、选床、退床、改选每个动作
  • 预览期不显示占用,避免公平争议与误读

住宿,是这套系统里第一个不允许出错的东西。

前面的字段映射错了可以重导,权限配错了可以改回来,通知发错了可以再发一条。床位不行。一张床分给两个人,早上七点到校的那一家站在宿舍门口,手里拿着系统给的确认页,而门里已经有人在收拾床铺——这一刻没有任何一句解释是有效的。

几千人抢同一批床位而不超卖,是这套系统最硬的一项技术事实。 也正因为它硬,后面那些"智能代办""自动放行"才敢往上面接。

10.1 从栋到床:宿舍的层级模型

学校描述一间宿舍的语言,比软件系统默认的细得多。

系统里的层级是这样一路分下来的:校区/宿舍区/组团 → 栋 → 单元 → 层 → 住户 → 房间 → 床位。组团这一级是可空的——有的学校按"梅园""菊园"这样的组团管宿舍,有的学校没有这个概念,留空即可,不必为了迁就系统硬造一层。住户这一级同样是可空的:校内宿舍直接用房间,只有校外租用的公寓、小区才需要"某幢某室"再套一层门牌。

能深能浅,是这个模型真正的用处。 一所学校把整栋留学生公寓按套间分、一所学校把校外租的小区房源纳统,两套口径不用改任何东西,只是层级走得不一样深。房间记录里那条完整的门牌——形如"1#-1-101-A"——一路写着栋号、单元、楼层、房号和床位字母,学生看到的就是这一串,它同时也是宿管找人的地址。

房间这一级带着学校真正会用的属性:房间类型(双人间、四人间)、床位总数、性别限制、收费标准、是否开放自选。户型还单独有一张表,记名称、面积、户型图和外链的全景地址。

另外有一件事常被忽略:每栋有楼长,每层有层长,每间有宿舍长,三个位置都指向具体的人。这不是装饰——报到当天要找一个能拍板的人,靠的就是这三层归属。

10.2 三个人同时点同一张床,为什么不会乱

选宿开放的那一刻,一个学院的几千名学生同时在线,热门房间的抢争是真正的并发争抢。这件事靠三层处理。

第一层,锁按床位分开加。 系统不是一把大锁锁住整个选宿功能,而是给每张床位单独一把锁。这样做的结果很直接:抢 101 房间 A 床的和抢 305 房间 B 床的互不阻塞,几千人同时在线不会退化成排队过闸口。并发保护的粒度,决定了洪峰时刻的吞吐。

第二层,锁按学生分开加。 同一个学生的选、改、退三种操作被串成一条线。这一层防的不是别人抢他,而是他自己——手快点两下、两个页面同时打开,结果一个人占住两张床。这种错在报表上只会多出一行,在现实中却少了一张能住的床。

第三层,也是最后那道,不在程序里。 同一批次、同一房间、同一床位号,数据本身只允许存在一条记录。前两层都失效的极端情况下,第三个人提交时会撞在这道规则上,系统随即回一句"该床位刚被其他同学选走,请返回重新选择"。

这一层的意义在于:不超卖这件事不依赖程序自觉,是数据不允许第二种结果出现。 依赖判断的防线会被绕过,依赖规则的不会。

改选那条路还多留了一个心:改选新床失败时,原床位保留不动。不能让一个已经住进去的学生,因为一次没抢成的换宿操作变成没有床的人。

这一项已经在真实开学季跑过,数千人同时选床未出现重复分配。

10.3 指定分配与自主选床并存

学校对"床位谁说了算"的答案并不统一,所以两条路都得留。

一条是指定分配:学校分好,学生只是查看和确认。另一条是自主选床:开放一段时间窗,学生在可选项里自己挑。两种模式在系统里是两类任务,不是二选一的开关,甚至可以并存——有的学校让师范生定向班直接分配,让普通学生自主选。

选床这条路上还有个变体:先手机选号、再完成缴费。付费类事项和床位绑在一起时,顺序怎么排各校不同,所以顺序也是配置。

同一套引擎要能同时服务"学校说了算"和"让学生自己挑"这两种管理哲学,才算真的配置化。 只支持其中一种的系统,本质上是把某一种管理习惯写死了。

10.4 谁有资格选:学院床位池、分组准入、性别与时间窗

床位不是全校一个大池子。

学校通常先把房源切给学院——某个学院的预分配范围就是这些房间,本院学生只能在这个池子里挑,超出范围会被直接拒绝,提示说清"该床位不在您所在学院的预分配范围内"。池子之上还可以再切一层任务分组:同一个学院里,特定分组的学生才看得到某批床位。

这一层的资格校验有个必须交代的过程。分组资格最初只在进入页面时判过,后面查看房间、看床位、选床、退床、改选这几个动作上没有逐个把关,理论上存在绕过页面直接提交、从本学院池子外面抢床的可能。这个口子后来在每个动作上逐一补齐,并且留了一组回归测试专门盯着,防止以后再加功能时漏掉其中一环。

资格控制一旦只做在入口,就等于没做。 一套系统怎么对待边界,看它把校验放在几个动作上就知道。

此外还有两道常规但硬性的过滤:性别——男生看不到女生楼,房间层面的性别限制在候选列表就生效,不是提交时才拦;时间窗——不在选宿起止时间内,任何一次操作都被拒。时间窗按管理员配置的北京时间判定。

10.5 预览期为什么看不见"已选"

这是宿舍功能里最不起眼、却最能说明分寸的一处设计。

很多学校会开放一个预览期:先看楼层、看房间、看床位分布,正选时间一到再动手。而在这之前,管理员往往已经给一些学生提前留好了床位——身体有特殊情况的、定向培养的、需要集中管理的楼层。

问题来了:预览期要不要把这些床位显示成"已选"?

显示,看起来更透明,实际后果是公平的争议——学生点开一张床看到"已选",而他不知道那是老师提前留的,只会得出"内部有人先挑过了"的结论。不显示,则预览期的床位数量保持完整,正选一开始才恢复真实占用状态。

系统选的是后者:纯预览期内所有床位一律不显示占用,正选时间一到,占用状态同时恢复。 这不是隐瞒,是把"提前安排"这件确有必要的行政动作,放到不会被误读的时间段去完成。

技术上只是多一个显示判断,学校却要求先想清楚什么时候该显示、对谁显示。迎新系统里最难的不是把功能做出来,是判断它在什么时候该出现。

10.6 设施台账、调宿与走读申请

床位之外,宿舍还有一堆要管的东西。

设施台账是宿管真正每天用的部分:每间房的设备、家具、报修记录,可以整批导入,导入时遇到已存在的记录有明确的处理规则,不会把去年的台账覆盖掉。台账之外还管三件事——调宿(住进去之后因为身体、矛盾、专业调整换床)、住宿确认(选完了要本人点头,确认后才算落实)、床品尺码采集(被褥这类要提前定的东西,跟着宿舍一起收)。

走读申请是宿舍侧唯一的"反向"流程:学生申请不住校。这一环带着家长签名与家长联系方式——不住校意味着学校把安全责任的一部分交还给家庭,这一笔必须有监护人的确认留在那里,不能只凭学生自己点一下。

这些环节合起来才是宿舍管理的真实工作量。床位分配只是开学那几天的事,台账、调宿、走读是一整年的事。

10.7 床位数据的独特价值:报到前就知道室友是谁

第一章那句"他知道哪栋楼好,学校该知道他卡在哪一步",在床位这件事上可以说得最具体。

学生在平台上能查到的,是"这所学校哪栋宿舍楼好"——哪栋新、哪栋有独立卫浴、哪栋被吐槽多。这些他查得到,也查得准。

他查不到的是:他被分到哪一间,以及室友是谁。

这一条只有学校知道,而且不只在报到当天知道——床位一旦确定,学院、专业、班级、生源地、采集过的兴趣爱好,全部落在同一个房间号上。也就是说,"你隔壁那张床是同专业的同学,来自哪个省""你们四个人里有两个人勾了同一项爱好"这些话,学校手里本来就有依据可说;把它们做成学生可查的一屏,是按批次建设的内容。

"报到前就知道室友是谁",是官方信息能够压过野生攻略的少数几个凭据之一。 攻略能告诉他楼新不新,只有学校能告诉他这件事——而这正是他在入学前最焦虑、又最无处可查的一个问题。

要提醒的是边界:这类信息必须由学生本人主动查看才出现,不做默认公开,也不做群发。同宿舍不等于互相同意公开家庭住址。这条分寸在第十五章讲隐私与授权时会写成硬约束。

10.8 校园地点与路线:不自建 3D

新生到校的第一个真实动作是找路,于是很多学校被建议做一个三维校园。

这条路不建议。学校缺的从来不是精美的三维模型,是一个学生能问"我要去的地方怎么走"的入口。 三维建模要钱、要维护、要有人更新,新建了一栋楼就得重做,多数学校做完第一年就不管了。

现在的做法务实得多:户型图、楼层图挂在房间与户型上,全景展示直接用外链——学校已经有全景资源的,贴一个地址进来就能看,没有也不强行补。真正按批次建设的是一套校园地点库:地点名称、照片、开放时间、使用规则、类别,配上起终点路线,让学生搜"报到点""财务处""校医院"能得到可走的路线,而不是只能看到一张效果图。

能用现成资源解决的,不做成需要长期维护的自建工程。 它省下的不是首次建设费,是三年后没人管的那笔账。

走到这里,床位这件事其实把前面几章的能力全用上了:房源与名单先进得来,组织归属先分得清,学院隔离与分组准入先管得住,指定分配还是自主选床、先选还是先缴都撑得起配置,几千人同时抢不能超卖,最后还得有分寸——预览期不显示占用,室友信息不默认公开。

这六样凑齐,一个学生才能在动身之前就知道自己住哪间、和谁住、几点能到、怎么走;少任何一样,选宿就退化成报到现场靠老师拿花名册拦人。 而他手里一旦有了这些只有学校才给得出的确凿,还会去评论区问"这学校宿舍到底怎么样"吗——这就是第二十三章要回答的问题。