Bootstrap

千万级学生管理系统的考试试卷存储方案

1. 估算性能需求

1.1. 多少考卷?

每门课程有 100 名学生

在校学生 1000万,每学期20门课,每科一年2次考试

每学期考卷数量:1000万 * 20(课)* 2(考试次数)/100 = 400万

在校学生考卷数量:400万 * 2(学期) * 3(只有前三年考试) = 2400万

要配合学生答案的存储,查看答案时需要看到配套的考卷。

离校学生考卷数量:每年 800万

1.2. 考卷大小

考卷 20判断题,20选择题,4道大题

考卷大小:文字部分 2000,图片部分 1M

考卷存储量

  • 本学期考卷文字部分:400万 * 2000 = 8G

  • 本学期考卷图片部分:400万 * 1M = 4T

  • 在校学生考卷文字部分:48G

  • 在校学生考卷图片部分:24T

  • 离校学生考卷文字部分:每年 16G

  • 离校学生考卷图片部分:每年 8T

1.3. 请求量

假设学校的考试都安排在某一个月(考试月)的20天内(周末不考试),每天4堂考试,请求试卷集中在考试开始前1分钟,因此估算如下:

请求读取考卷:1000万 * 20(课)/ 20(20天考试)/ 4(每天4堂课)/ 1分钟 = 5万/每秒

假设老师出卷都安排在考试月前的一个月(出卷月)的20天内(周末不出卷),假设老师在本地设计完整个试卷后一次性提交。因此估算如下:

提交考卷请求:400万(每学期考卷)/ 20 (天)/ 8 (小时)= 7/每秒

2. 选择存储系统

2.1. 存储架构分析

2.1.1. 本学期考卷文字部分

单机能否存储所有数据:是

单机能否支撑写性能:是

单机能否支撑读性能:否

是否需要自动切换:是

主从切换或者集群选举

2.1.2. 本学期考卷图片部分

单机能否存储所有数据:否

是否需要分区部署:否

分片架构

2.1.3. 在校学生考卷文字部分

单机能否存储所有数据:是

单机能否支撑写性能:是

单机能否支撑读性能:是

是否需要自动切换:否

主备复制

2.1.4. 在校学生考卷图片部分

单机能否存储所有数据:否

是否需要分区部署:否

分片架构

2.1.5. 离校学生考卷文字部分

单机能否存储所有数据:否

是否需要分区部署:否

分片架构

2.1.6. 离校学生考卷图片部分

单机能否存储所有数据:否

是否需要分区部署:否

分片架构

2.2. 存储架构图

本学期考卷文字部分使用 Redis sentinel

在校学生和离校学生考卷文字部分使用 HBase 集群

所有考卷图片部分(本学期、在校学生、离校学生)使用 HBase 集群

3. 设计存储方案

3.1. 本学期考卷文字部分

3.1.1. 数据结构设计

key: "tp:" + 学校ID + ":" + 考试ID

使用 list

前缀 tp 是 test paper 的缩写

list 的每一项是一个 json,json 的字段:

  • text: Markdown版的考题文字(使用 Markdown 除了方便排版,还方便插入图片)

  • options: 选择题的选项

  • type: 考题类型,包括判断题、选择题、问答题

3.1.2. 读写分析

3.2. 在校学生和离校学生考卷文字部分

3.2.1. 数据结构设计

key: 学校ID + 考试ID

column family: test

column: paper (JSON格式)

3.2.2. 读写分析

3.3. 所有考卷图片部分

3.3.1. 数据结构设计

key: 学校ID + 考试ID + 图片ID

column family: test

column: pic

3.3.2. 读写分析

4. Redis Sentinel 集群服务器数量和性能

Redis 服务器单机 TPS 5~10万

请求试卷 5万/每秒

每次请求试卷只需要读取 Redis 服务器一次就能获取整张试卷(图片不依赖 Redis),用最基础的3机 Sentinel 集群就足够了。