学生考试系统存储设计
存储设计
老师出题
老师出的题目存储在 Mysql 中,试卷表、题目表
试卷表:主要存储 学校,课程,课程老师
题目表:存储对应的试卷的题目
试卷和题目是一对多的关系
考试前试卷初始化
考试前需要把试卷预热到 Redis 中,整个试卷共 24 道题,预估在 3kb 大小,不适合一次性全部获取,可采取一题一题的加载方式,redis 中采用 Lists 结构存储题目,试卷呈现方式可采用一题一题的展现方式,数据结构如下:
key:school_id+paper_id
value:question_id|||num|||type|||context
value 值包含每一题的编号,类型,题目内容,通过特殊符号|||来分割
学生考试获取题目
学生登录系统后,可获取对应的 school_id 和 对应的试卷 paper_id,可从 redis 中获取对应的试卷,每获取一道题目,都缓存在客户端中,无需重复获取。
学生提交答案
考虑到学生答案的重要性,不采用最终一起提交的方式,采用每写一道题提交一次的方式
提交答案的 TPS 估算:1000 万 * 20 课 * 24 题 /20(周末不考试)/ 4 (每天 4 堂考试) / 8 小时 = 2000/秒
存储:学生的答案存储在 redis 中,按题目维度存储,string 数据结构
key : school_id+student_id+paper_id+question_id
value:学生题目答案
老师批改试卷
1.学生试卷获取
老师登录系统,通过 school_id+paper_id 从 redis 中获取试卷和所有题目
根据需批改学生的 id 和 question_id,组装 school_id+student_id+paper_id+question_id,从 redis 中获取题目的学生的答案,完成题目和答案的组装,同样采用一道题一道题的展现方式(由于老师的数量远小于学生数量,此时的 qps 可忽略)
2.试卷批改
老师每批改完一道题目,客户端提交一次请求,用于保存批改结果,批改结果存储在 mysql 中,采用分表的存储方式
总的在校生试卷数量在 24 亿,分表 500 张,teacher_id 为 2 张表的分片键
老师完成一个学生的试卷批改后,通过异步方式去生成学生维度考试成绩表
学生查询分数
学生的考试成绩表存储在 Hbase 中,分为试卷表和学生题目详情表
试卷表:
rowkey:school_id+student_id
colmun:student_paper_id 学生试卷 id
colmun:total_num 学生试卷总分
学生题目详情表:
rowkey:school_id+student_id+student_paper_id
colmun:num 题目编号
colmun:type 题目类型
colmun:context 题目内容
colmun:answer 题目学生答案
colmun:result 批改结果
colmun:score 题目得分
Redis 配置
试卷读取的 QPS:5w/s
试卷提交的 TPS:2000/s
数据存储规模:2.4t,每年增长 0.6t
分析:每年增长 0.6t,意味着每学期的考试存储量在 0.3t,64G 内存的机器按照 50%内存存储,需要 10 台机器,基于 redis 官网基准测试,10 台机器通过 Sentinel 组成的集群,可满足试卷读取和提交的要求
机器配置:16 核 64G 500G 硬盘
数量:10
评论