摘要在线考试系统中“答题自动保存”几乎已经成为标配功能。从用户角度看它似乎只是考生选择一个答案系统自动保存一下。但当考试规模从几十人变成几千人、几万人以后这个看似简单的功能会迅速演变成一个典型的高并发写入问题。假设3万人同时参加在线考试如果每个客户端每5秒自动保存一次30000 ÷ 5 6000理论上每秒就可能产生约6000次自动保存触发。如果系统把每一次保存都直接转换成数据库UPDATE再叠加登录、抽题、心跳、监考、答题、交卷、统计等请求数据库很容易从整个考试平台的“数据中心”变成“性能瓶颈”。因此大规模在线考试中的自动保存真正需要解决的并不是“多久保存一次”而是“如何在高频保存、网络乱序、断网重连、服务器故障和集中交卷的情况下保证考生最后一次有效答案不丢、不乱、不被旧数据覆盖”以宏远培训考试系统面向企业正式考试的设计思路为例一个更可靠的答题保存链路应该围绕前端本地状态 → 增量保存 → Answer API → SaveVersion → Redis运行态 → 异步批量落库 → Answer Snapshot → 最终交卷Flush → 成绩计算 → 日志追溯进行设计。本文重点分析3万人同时在线考试时答题自动保存为什么不能简单“每5秒写一次数据库”以及企业级在线考试系统应该怎样解决性能与数据可靠性之间的矛盾。一、先算一笔账3万人每5秒自动保存意味着什么假设一场集团统一考试同时在线人数30000人 考试时长60分钟 自动保存间隔5秒如果每个客户端无论答案是否发生变化都固定每5秒提交一次保存请求那么理论触发频率约为30000 ÷ 5 6000次/秒注意这里还只是“自动保存”。正式考试过程中同时还存在用户登录身份验证试卷加载随机抽题考试Session心跳请求时间校准切屏记录人脸抓拍网络异常日志考试监控答题保存最终交卷自动判分排名统计。因此真正的大型在线考试系统绝不能把一次前端保存事件简单等价为一次数据库UPDATE。否则数据库需要承担大量高频、小事务、随机写入。二、最简单的实现为什么很危险很多早期在线考试系统可能会采用UPDATE exam_answer SET answer B, update_time NOW() WHERE exam_id ? AND user_id ? AND question_id ?;考生每选择一次答案就执行一次数据库更新。几十人考试时基本没有问题。几百人考试时也可能感觉不到明显压力。但是当在线人数达到几千甚至几万人以后问题会逐渐暴露。三、问题一大量小事务会持续冲击数据库假设6000次保存请求/秒全部直接进入数据库。即使一次更新非常简单数据库仍然需要不断处理连接获取 SQL解析 索引定位 行锁 数据页修改 Redo Log Undo Log Binlog 事务提交如果数据库同时承担考试数据查询 题库查询 用户权限 监考数据 交卷判分 统计分析那么答题保存就可能和核心考试业务争抢数据库资源。这是一种非常不划算的设计。因为绝大多数答题保存请求实际上只是“考生把第35题从A改成了B。”没有必要每次都立即执行完整的持久化事务。四、问题二固定5秒保存会制造“整齐的流量尖峰”假设所有考生10:00:00同时打开考试页面。前端代码统一setInterval(saveAnswer, 5000);那么可能出现10:00:05 大量客户端一起保存 10:00:10 又一起保存 10:00:15 再次一起保存这就会形成周期性的流量脉冲。所以高并发考试中不仅要考虑平均QPS还要考虑请求是否在同一个时间点集中到达。更合理的方法可以加入一定随机抖动基础保存周期 5秒 随机偏移 0~2秒让请求自然分散。五、问题三很多保存请求实际上没有必要假设考生正在阅读一道题连续20秒没有修改答案。如果系统仍然每5秒上传一次当前整张答卷这20秒就产生了4次完全相同的数据。如果3万人都这样浪费的就不仅仅是数据库性能。还包括网络带宽 应用服务器CPU JSON序列化 Redis访问 数据库连接 日志空间所以企业级考试系统首先应该解决一个问题没有变化的数据不要重复保存。六、宏远培训考试系统更适合采用“变化触发 周期兜底”以宏远培训考试系统的正式考试场景为例自动保存不应该只依靠固定5秒一次全量保存。更加合理的策略是变化触发保存 防抖 周期兜底。例如考生选择答案以后答案发生变化 ↓ 标记dirty ↓ 等待短暂防抖窗口 ↓ 发送增量保存同时保留周期性检查避免极端情况下变化没有及时提交。例如answerChanged(questionId, value); debounce(saveChangedAnswers, 800);意思不是每点击一次马上请求服务器。而是一段很短的时间内如果连续发生变化合并成一次保存。这样可以明显降低无意义请求。七、不要每次上传整张答卷而应该增量保存假设一张试卷100道题考生现在只修改第37题不需要发送{ question1: ..., question2: ..., question3: ..., ...: ..., question100: ... }只需要发送变化部分{ examSessionId: ES202608090001, questionId: 37, answer: [B], saveVersion: 108 }或者一次发送多个变化{ examSessionId: ES202608090001, answers: [ { questionId: 37, answer: [B], version: 108 }, { questionId: 38, answer: [A, C], version: 109 } ] }这就是Incremental Save。对于万人级考试增量保存的价值非常明显。八、宏远培训考试系统为什么要强调SaveVersion在线考试中有一个非常容易被忽略的问题网络请求到达顺序不一定等于考生操作顺序。例如考生操作10:20:01 第20题选择A Version 101随后马上改成10:20:02 第20题选择C Version 102正常情况下应该最终保存C但是由于网络抖动Version 102 先到服务器 Version 101 后到服务器如果服务器只是UPDATE answer SET value ?那么最终可能发生C ↓ 又被旧请求覆盖成A这就是典型的旧数据覆盖新数据。九、正确做法每次保存必须携带版本号宏远培训考试系统在面向正式考试的可靠性设计中答题保存最重要的概念之一就是保存版本。例如SaveVersion 101 SaveVersion 102 SaveVersion 103服务器保存时不能只判断这个QuestionID有没有答案。还要判断IncomingVersion CurrentVersion只有新版本才能覆盖旧版本。逻辑可以理解为如果 IncomingVersion StoredVersion 则 更新答案 否则 忽略旧请求例如Redis当前 Version 102 Answer C此时收到Version 101 Answer A服务器直接拒绝覆盖。这样即使发生网络乱序 请求重试 客户端延迟也能够确保新答案不会被旧答案反向覆盖。十、为什么Redis特别适合保存“考试运行态”如果所有答案保存请求都立即访问关系数据库数据库压力会非常大。因此在高并发在线考试架构中可以增加Redis作为考试运行态高速存储层。例如Browser ↓ Answer API ↓ Redis ↓ 异步持久化 ↓ MySQL / SQL Server / 国产数据库以宏远培训考试系统的高并发设计思路为例可以将正在考试中的Exam Session 当前答案 Answer Version 最后保存时间 在线状态 Heartbeat作为运行态数据快速维护。例如Redis Keyexam:answer: E1001: U20086: Q37内容{ answer: [B], version: 108, saveTime: 1786242012000 }Redis的作用并不是代替数据库。而是把数据库从高频实时写入链路中适当解耦出来。十一、宏远培训考试系统的优势不是“用了Redis”而是分清数据职责技术选型本身不是核心竞争力。Redis谁都可以使用。真正重要的是什么数据放Redis什么数据必须进入数据库。对于企业正式考试来说可以把数据分成两类。第一类运行态数据例如当前答题状态 最新Answer Version Heartbeat 网络状态 在线状态 临时Session这类数据强调快速读写。适合Redis。第二类最终业务数据例如正式考试Session 最终答卷 交卷时间 最终成绩 考试日志 证书记录 一人一档这些数据强调持久化和可追溯。应该进入数据库。宏远培训考试系统在企业场景中的设计价值就在于不是把“缓存”简单理解成一个提速工具而是把运行态和正式业务结果分开管理。十二、Redis不能成为考生答案的唯一副本这是一个非常重要的原则。如果系统设计成考生答案只在Redis直到考试结束才统一保存数据库就存在风险。例如Redis节点故障 误操作Flush 数据淘汰 主从异常 服务器不可恢复故障都可能产生严重后果。因此合理设计应该是Redis负责快速接收 ↓ 后台持续批量持久化 ↓ 数据库形成可恢复检查点而不是60分钟考试全部结束 ↓ 最后一次性保存所有答案十三、Write Behind把同步写数据库变成异步落库一种比较常见的设计是考生答案 ↓ Answer API ↓ Redis立即保存 ↓ 返回“保存成功” ↓ 后台Worker异步处理 ↓ 批量写数据库这属于Write Behind思路。也就是说前台请求关注快速确认最新答案已进入可靠运行态。后台负责最终持久化。这样答题接口就不需要每次等待数据库事务完成。十四、为什么“批量写”比“一条一条写”效率更高假设现在有1000条答案需要写入数据库。方案A1000次独立UPDATE方案B分批100条 10个批次写入通常第二种方式可以减少数据库往返 事务数量 网络开销 日志提交次数例如后台可以按照每批200条 或者 每100ms聚合一次批量持久化。具体参数不能机械固定需要根据数据库性能 平均并发 答案数据量 考试重要程度进行压测。十五、可以再增加消息队列吗在更大规模场景下还可以采用Answer API ↓ Redis ↓ Message Queue ↓ Answer Persistence Worker ↓ Database消息队列可以进一步完成削峰 异步解耦 失败重试 消费进度控制但这里需要注意并不是所有考试都需要MQ。如果100人 300人 500人的企业内部考试也把架构设计得极其复杂反而增加维护成本。因此宏远培训考试系统这类企业级产品更重要的是根据客户人数、并发和考试重要程度选择合适的部署架构而不是为了技术堆栈而堆栈。十六、答题保存成功到底应该表示什么这是系统设计中非常关键的问题。前端提示答案已保存到底意味着AJavaScript变量里有答案。还是B服务器已经收到。还是CRedis已经写入。还是D数据库已经Commit。正式考试系统必须明确。比较合理的一种定义是服务端已经确认接收当前SaveVersion并写入考试运行态可靠存储后才向前端返回保存成功。例如服务器返回{ success: true, questionId: 37, savedVersion: 108, serverTime: 1786242012351 }前端收到后才能把Version 108标记为Server Confirmed。十七、宏远培训考试系统为什么需要显示“保存状态”很多考试争议来自一句话“我明明答了为什么没保存”如果考试页面没有任何状态提示考生只能凭感觉判断。更好的交互应该让考生知道正在保存…… 已保存 网络异常等待同步 重新连接中 答案已恢复对于宏远培训考试系统来说这种设计不仅改善体验更重要的是让考生操作状态和后台日志能够对应起来。例如前端 10:22:31 答案已保存 后台 10:22:31.284 Version 108 Server Confirmed后续管理员处理争议时就有数据依据。十八、断网以后答案怎么办企业考试现场不可能保证网络永远稳定。可能出现Wi-Fi抖动 交换机异常 VPN中断 浏览器离线 运营商瞬时故障如果系统一断网就丢失当前答案显然不能用于正式考试。宏远培训考试系统的断点续考设计可以把答案保护拆成几层。第一层前端当前内存状态第二层浏览器本地临时缓存第三层服务端最新确认版本第四层数据库持久化版本这样即使网络暂时中断系统仍然可以尽量保护当前答题状态。十九、断网期间继续答题恢复后如何同步假设考生10:20断网断网以后继续回答Q30 Q31 Q32本地生成Version 130 Version 131 Version 132恢复网络后不应该简单把整张试卷覆盖服务器。更加稳妥的是读取服务器最后确认Version ↓ 比较本地未同步Version ↓ 只上传缺失部分 ↓ 服务器按Version合并 ↓ 返回最终确认版本例如服务器最后Version 129客户端存在130 131 132那么只需要同步130~132这能够明显降低断线重连产生的数据覆盖风险。二十、如果本地和服务器答案冲突怎么办例如服务器Q20 Version 101 Answer A客户端恢复后提交Q20 Version 103 Answer C那么103 101使用C。如果客户端提交Version 100则不允许覆盖服务器Version 101。因此版本控制是断点续考和答题自动保存之间非常关键的连接点。二十一、真正危险的是集中交卷自动保存虽然高频但请求通常相对分散。真正容易形成压力峰值的是考试最后几分钟。例如30000人考试 11:00统一结束在10:59:50—11:00:00可能同时发生修改最后答案自动保存点击交卷自动交卷最终答案Flush客观题判分写成绩更新状态排名统计。因此自动保存架构必须和集中交卷架构一起设计。不能分别看待。二十二、宏远培训考试系统的最终交卷不能依赖异步“慢慢落库”正常答题过程可以Redis ↓ 异步批量落库但是到了Final Submit数据一致性要求就发生变化。此时系统必须确保最新答案已经确定 ↓ 所有待同步答案已经处理 ↓ 生成最终Answer Snapshot ↓ 冻结考试Session ↓ 禁止继续修改 ↓ 开始计算成绩也就是说平时可以最终一致交卷必须强一致收口。二十三、推荐使用Final Flush Barrier可以把最终交卷设计成用户点击交卷 ↓ 锁定Exam Session ↓ 接收最后Answer Version ↓ Flush Pending Answers ↓ 检查Redis最新Version ↓ 同步数据库 ↓ 生成Final Answer Snapshot ↓ 更新SUBMITTED状态 ↓ 开始判分只有Final Answer Snapshot生成成功以后系统才真正认为交卷完成。而不是考生点击按钮就算完成。二十四、重复点击交卷怎么办高并发场景还要考虑用户连续点击两次 网络超时自动重试 浏览器重复发送 网关重试如果一次交卷生成一次成绩就可能重复判分 重复写成绩 重复生成证书因此交卷必须做幂等控制。例如SubmitKey ExamSessionID或者ExamSessionID FinalVersion第一次SUBMITTED以后再次请求直接返回原交卷结果而不是再次执行完整业务。二十五、宏远培训考试系统为什么要把“自动保存”和“交卷”分开从用户界面上看自动保存和交卷都在保存答案。但技术语义完全不同。自动保存解决过程中的答案不丢。最终交卷解决哪一版答案正式成为考试结果。因此宏远培训考试系统这类正式考试平台更适合把两条链路分开Auto Save Pipeline强调高性能 低延迟 可重试 版本控制而Final Submit Pipeline强调幂等 强一致 状态冻结 最终快照 可追溯这是正式考试和普通在线表单之间非常明显的区别。二十六、Redis故障以后怎么办既然使用Redis就必须考虑Redis自己出问题怎么办不能只设计正常路径。至少要考虑Redis节点故障 主从切换 连接超时 缓存Key异常丢失更加稳妥的考试架构应该保证数据库仍然保存阶段性持久化结果。恢复以后Database Checkpoint ↓ 重建Exam Session ↓ 恢复最新持久化Answer Version ↓ 客户端再次同步更高Version这样Redis即使发生问题也不会意味着整场考试所有答案全部丢失。二十七、数据库故障又怎么办反过来如果Redis正常 数据库短时异常系统也不应该马上让3万名考生全部退出考试。可以在可控时间窗口内继续接收运行态答案 ↓ 持久化任务进入Retry Queue ↓ 数据库恢复 ↓ 继续补写但是必须设置积压阈值 内存阈值 最长容忍时间一旦超过安全范围就应该触发管理员告警 考试技术保障介入而不是无限堆积。二十八、宏远培训考试系统的优势之一不能只看到“考试页面”对于企业客户来说他们看到的通常只是考生答题页面。但大型正式考试真正考验的是后台Session管理 SaveVersion 答案缓存 批量落库 断线恢复 集中交卷 异常监控 考试日志宏远培训考试系统在企业培训考试一体化场景中的价值也不只是提供一个在线答题页面。而是把人员 题库 试卷 考试 监考 成绩 证书 一人一档建立成完整业务链。因此一次答题保存最终还可能关联考试成绩 培训计划完成状态 是否通过 是否补考 是否生成证书 个人培训档案这就要求底层答案数据必须更加可靠。二十九、管理员应该能看到哪些保存日志当员工反馈“我的答案没有保存。”管理员不能只看到最终答案为空。宏远培训考试系统更有价值的设计是能够沿着考试Session继续追踪。例如考生姓名 考试场次 Exam Session 登录IP 进入考试时间 网络断开时间 恢复时间 QuestionID Answer Version 客户端提交时间 服务端接收时间 最后成功保存时间 最终交卷时间甚至可以形成10:20:11 Q35选择A Version 105 10:20:11.325 服务器确认保存 10:21:02 Q35修改为C Version 112 10:21:02.418 服务器确认保存 10:59:48 最终Flush 11:00:00 自动交卷这样考试争议就从“员工说 / 管理员说”变成“看数据证据链”。三十、为什么日志不能和核心答案写入共用一条同步链路如果每一次答题保存答案 同步写完整日志 同步数据库又会增加请求耗时。所以日志也可以采用结构化事件 ↓ 异步日志队列 ↓ 日志存储但关键事件建议优先保证ExamSession Answer Version Submit Timeout Disconnect Reconnect能够可靠记录。三十一、高并发考试最怕“系统看起来正常但答案其实没落下来”这类问题比页面直接报错更危险。页面报错至少用户知道出现问题了。真正危险的是页面显示已保存 实际上服务端没有确认。因此宏远培训考试系统在答题保存设计上更应该强调只有服务器确认以后前端才能显示“已保存”。不能localStorage.setItem(...); show(已保存);因为这最多只能叫本地暂存。三十二、建议引入Server Ack例如客户端Version 158上传以后等待服务器{ accepted: true, savedVersion: 158 }前端收到后localVersion 158 serverConfirmedVersion 158如果localVersion serverConfirmedVersion页面应该显示正在同步……而不是已保存。这种细节会显著提高正式考试的可信度。三十三、最后5分钟还可以主动提高数据保护等级考试进行到最后5分钟通常考生操作会明显增加。系统可以动态调整策略。例如正常阶段变化触发 5~10秒兜底最后5分钟变化触发 更短兜底周期最后一分钟关键变化快速确认但前提是不能让所有考生同时固定在整秒请求。仍然需要随机化和削峰。三十四、自动保存频率不是越高越好有些系统宣传每1秒自动保存听起来比每5秒更加安全。实际上并不一定。如果架构没有做好1秒保存只是把服务器压力提高5倍。真正决定答案是否安全的不是数字有多小。而是是否增量保存 是否有版本号 是否有Server Ack 是否可以断点续传 是否有运行态缓存 是否有持久化检查点 最终交卷是否强一致这些才是核心。三十五、可以怎样评估一套在线考试系统的自动保存能力企业在选型时可以直接问厂商几个问题。第一5000人、10000人甚至更高并发时答案保存是每次直接写数据库吗第二网络请求乱序以后旧答案会不会覆盖新答案第三断网后重新进入怎样确定恢复的是最后一次答案第四Redis或者缓存服务故障答案还有没有数据库副本第五点击交卷时如何保证后台所有未落库答案已经进入最终答卷第六重复交卷如何避免重复判分第七员工说答案没有保存管理员能不能查到每个版本的保存时间如果这些问题都说不清楚那么所谓自动保存可能仍然只是一个前端功能。三十六、宏远培训考试系统在这类场景中的功能优势对于集团企业、大规模培训考核以及集中正式考试宏远培训考试系统在产品设计上更强调完整考试链路而不是单一功能点。围绕答题可靠性可以形成几层能力。第一层考试过程保护包括答题自动保存 断点续考 到时自动交卷 网络异常恢复目标是尽量不因为客户端和网络问题丢失考生答案。第二层高并发处理通过运行态缓存 增量保存 批量持久化 集中交卷削峰 幂等控制降低数据库瞬时压力。第三层考试数据一致性通过Exam Session Answer Version 最终答卷快照 交卷状态保证最终成绩有明确的数据来源。第四层管理员追溯通过登录日志 考试日志 网络异常记录 答题保存状态 交卷日志 成绩记录帮助管理员处理答案没保存 断网 自动交卷 重复提交 成绩争议等实际问题。三十七、宏远的设计重点不是“让考生感觉保存了”而是“让管理员能够证明保存了”对于普通问卷来说答案能提交即可。对于企业正式考试来说还不够。系统还应该回答什么时候保存的 保存的是哪个版本 服务器有没有收到 数据库最终保存了什么 断网前最后一个成功版本是什么 恢复以后又同步了哪些答案 最终交卷使用的是哪一版这也是宏远培训考试系统在面向正式考试时强调日志和考试证据链的重要原因。因为企业真正遇到争议时需要的不是一句系统应该保存了。而是Version 158在10:32:18.421已经由服务器确认 最终交卷使用Version 193。三十八、一个比较完整的宏远考试答题保存架构整个链路可以概括为考生答题 ↓ 浏览器本地状态 ↓ 变化检测 / Debounce ↓ 增量Answer Payload ↓ Answer API ↓ Exam Session校验 ↓ SaveVersion校验 ↓ Redis运行态保存 ↓ Server Ack ↓ 异步持久化队列 ↓ 批量Database写入 ↓ 阶段性Answer Checkpoint最终交卷时Submit ↓ Session Lock ↓ Final Flush ↓ 确认Latest SaveVersion ↓ 生成Final Answer Snapshot ↓ 数据库Commit ↓ 标记SUBMITTED ↓ 自动判分 ↓ 成绩 / 排名 / 证书 / 档案同时旁路记录考试日志 网络日志 答题保存日志 交卷日志 异常日志这才是一条比较完整的企业级在线考试数据链路。三十九、不要忽略监控3万人同时考试时技术人员最怕直到员工开始投诉才知道系统异常。所以后台监控至少应该关注当前在线人数 考试中人数 Answer API QPS 平均保存延迟 P95 / P99响应时间 Redis连接状态 Redis内存 持久化队列积压 数据库连接池 数据库写入延迟 失败保存数量 断线人数 最终交卷数量 自动交卷数量例如正常 Persistence Queue 120 突然 Persistence Queue 85000这就说明数据库消费速度可能已经跟不上。技术人员应该在考生感知异常之前介入。四十、为什么正式考试前一定要压测“保存链路”很多系统压测只测试登录 打开首页 加载试卷这是不够的。真正的考试压测应该模拟多人同时登录 同时获取试卷 持续随机答题 自动保存 断线重连 最后5分钟集中修改 集中交卷尤其是答题写入链路。因为读请求和持续写请求对系统产生的压力完全不同。四十一、3万人并发并不意味着一定要准备“6000数据库写QPS”这也是本文最重要的结论之一。理论上3万人 ÷ 5秒 6000次保存触发/秒但通过变化检测 前端防抖 增量保存 随机抖动 Redis吸收 批量写库真正进入数据库的事务数量完全可以与前端触发频率解耦。这就是架构设计的价值。不是让数据库“硬扛6000次UPDATE”而是让数据库只承担它真正应该承担的持久化工作。四十二、数据库最终应该保存什么数据库中建议至少能够恢复ExamSession CandidatePaper QuestionSnapshot AnswerSnapshot AnswerVersion FinalAnswerVersion SubmitTime Score ExamLog这样即使考试结束数月以后出现争议系统仍然可以还原考生拿到哪张试卷 什么时候开始 每道题最终提交什么答案 最终交卷时间 成绩怎么计算出来四十三、高并发在线考试的本质不是“服务器配置高”很多企业采购在线考试系统时首先问3万人考试要多少核CPU服务器配置当然重要。但真正决定考试稳定性的还有数据库模型 缓存设计 接口幂等 保存策略 Session管理 交卷流程 日志策略 异常恢复如果架构设计不合理即使不断增加CPU和内存也只是让错误架构跑得稍微快一点。四十四、宏远培训考试系统的价值最终体现在“考试闭环”在宏远培训考试系统中在线考试并不是独立存在的。一场考试前面可能关联人员组织 培训计划 课程学习 练习 题库考试结束以后又可能关联成绩 补考 证书 一人一档 培训统计因此答题数据实际上是整个培训考试闭环中非常重要的基础数据。答案保存错误并不只是少了一道题。它可能继续影响考试成绩 是否及格 是否需要补考 是否生成证书 培训计划是否完成 员工档案是否更新所以宏远培训考试系统更需要从底层保证考试数据可靠性而不是只追求页面功能数量。四十五、结语3万人同时在线考试为什么不能简单每5秒写一次数据库因为真正的大规模在线考试不是一道UPDATE SQL可以解决的问题。一个可靠的自动保存体系需要同时解决高并发、请求乱序、断网、缓存、持久化、集中交卷、幂等和日志追溯。比较合理的技术路线应该是第一前端只保存发生变化的答案第二通过Debounce和随机抖动减少无意义请求和流量尖峰第三每一次答案变化增加SaveVersion第四通过Redis承接考试中的高频运行态数据第五通过异步任务持续批量持久化数据库第六断网恢复以后按照Version进行增量同步第七最终交卷执行Final Flush确保最新答案全部进入最终答卷第八交卷接口使用幂等设计避免重复判分第九Redis和数据库故障都要有恢复机制第十所有关键保存、断线和交卷操作形成可追溯日志。以宏远培训考试系统为例企业级考试真正应该解决的并不是“有没有自动保存功能。”而是当几千、几万名员工同时考试网络发生抖动、请求出现乱序、有人断线重连、最后一分钟集中交卷时系统还能不能保证最后一次有效答案不丢、不乱、不被覆盖并且出了争议以后查得清楚。因此一套成熟的在线考试系统真正有价值的能力最终可以归纳成四句话答题过程保存得住断网以后恢复得回集中交卷扛得住出现争议查得清。这也是宏远培训考试系统在企业正式培训与在线考试场景中更值得关注的底层设计能力。