学生管理系统 - 考试存储架构设计
前言
本文是千万级学生管理系统的子系统--考试存储架构的架构设计文档,用于指导考试存储架构的部署与运维实施。
词汇表
redis:Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker。Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。
redis sentinel:官方文档定义:Redis Sentinel provides high availability for Redis. In practical terms this means that using Sentinel you can create a Redis deployment that resists without human intervention certain kinds of failures。即 Redis 哨兵(Sentinel)模式,通过哨兵监控多台 redis 服务器运行状态,实现故障自动切换的高可用模式。
1. 业务背景
在千万学生管理系统存储架构设计中,我们分析了考试场景中的数据量级和读写 QPS,其中试卷请求 QPS=5 万/s,基于这么大的 QPS,我们选择了 RedisSentinel 的存储架构,用于存储试卷信息,以支撑学生考试时的试卷读取请求。
2. 约束和限制
必须做到读取试卷性能 QPS>=5 万/s。
可用性 99.9%
试卷加载 maxRT<=10s
3. 总体架构
3.1 架构分析
高性能:试卷读取 QPS=5 万/s,对读性能要求要求极高,但是一次考试同一科科目试卷基本都是同一份,保存一份即可,而且可以提前上传试卷内容,所以写入性能可以不考虑。
高可用:考试试卷读取是在考试时的开考时间统一进行,如果系统出问题,那么可能就会导致大批的学生延期,甚至有可能需要重新设计试卷,这样将会浪费大量的师生时间,所以高可用这块我们认为必须在 99.9%以上。
可扩展:这部分暂时来看需求不强烈,因为目前的考试基本上几年都不会改变一次,还是主要以文字类型为主,所以认为这块可以不考虑。
成本、安全:千万量级的学生系统,对于成本这块来说,认为预算应该是没有问题的,有必要的支出都可以满足。安全上来说,一般试卷也就是提前几天上传,能保证不会被轻易获取即可,这块可以通过业务系统保证,数据存储这块保障不会接受 ip 白名单外的请求即可。
3.2 总体架构
使用 Redis 的 HashTable 存储试卷与学生考试答题结果。
使用 redis-sentinel 作为 redis 的高可用高性能部署方案,因为 redis-sentinel 可以做读负载均衡,实现高性能,且可以实现故障自动转移,实现高可用。
4. 详细设计
4.1 核心功能
4.1.1 试卷上传
老师做试卷上传时,系统将设计好的试卷以 HTML 的格式作为 value,课程 ID+第几次考试作为 key,上传 redis。
数据结构设计:
Key:为本学期课程 ID,如果一个学期考试多次,则 key 可以是课程 ID+第几次考试,
Value:是考试试卷内容。
方案分析:
由于一次考试每个同学的试卷内容都一样,这样讲试卷整体作为 value,而不是分每一道题作为 key-value,这样能减少复杂度,并且保证每个同学的试卷完整性。
这里要说明一下,redis 的 key 和 string 类型 value 限制均为 512MB,一般的试卷纯文本应该最多几 M,应该是没有问题的,这里的需求里不考虑图片,理论上图片不放入 redis 存储。
4.1.2 试卷下载功能
学习开始考试时,首先打开待考页面,选择待考课程与第几次考试,点击开始考试时,基于课程 ID+第几次考试作为 Key,redis 请求试卷内容,加载到浏览器中。
4.1.3 考试结束提交功能
考试结束后,学生将考试答题结果提交,这里依然使用试卷内容+答题结果整体作为 Value 的方式,课程 ID+第几次考试+学生 ID 作为 Key,保存学生答题结果。
数据结构设计:
Key:课程 ID+第几次考试+学生 ID
Value:试卷内容+答题结果整体作为 Value
方案分析:
这样不仅能降低设计复杂度,而且能最原始地还原学生答题的结果,没有必要将试卷和答案分开存,或者每道题和答案去关联。
4.1.3 考试结果持久化
考试完成后,不再要求高可用高性能,但是系统依然希望能保存每个同学的答题结果,则可以做异步的备份,将学生的考试结果备份到 mysql 中,这里选择 mysql 是因为可以通过 mysql 直接关联学生、教师、课程等信息,需要使用关系型数据库,另外就是回溯考试结果本身是一件低频访问的事件,无需设计其他数据存储方案,使用现有方案即可。
4.2 关键设计
4.2.1 redis-sentinel 故障转移
当主服务器宕机后,主从架构中需要手动把一台从服务器切换为主服务器,需要人工干预,会造成一段时间内服务不可用。在考试场景中,我们希望故障时自动转移主服务器,这时我们就需要 reids 的哨兵模式。
哨兵模式是一种特殊的模式,首先 Redis 提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待 Redis 服务器响应,从而监控运行的多个 Redis 实例,在 master 出故障时,重新选举一个 slave 作为 master 承接新的请求。这里的哨兵即是 sentinel 集群,使用集群的原因是 sentinel 也需要保障自身的高可用性。
故障切换(failover)的过程:
假设主服务器宕机,哨兵 1 先检测到这个结果,系统并不会马上进行 failover 过程,仅仅是哨兵 1 主观的认为主服务器不可用,这个现象成为主观下线。
当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行 failover 操作。
切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
主机切换完后通知客户端切换 redis 的主机服务器地址。
老的 master 如果恢复,则会称为新的 slave。
4.3 设计规范
必须遵从 redis 开发对接规范。
5. 质量设计
可测试性:
可通过业务系统上传试卷和下载进行测试。
性能压测需要通过模拟 7.5W/s 的 QPS 进行压测。
可维护性:
搭建 redis 管理系统,管理 redis 服务状态和数据管理。
可观测性:
针对 redis,sentinel 等需要做到服务器硬件系统监控、应用监控等。
成本:
无需太过考虑成本问题,有必要的支出都可以满足。
6. 演进规划
针对考试高发期和低频期,也就是期末、期中是高频期,这段时间可适当增加 redis 和 sentinel 服务器数量,其他时间可适当减少服务器数量。
由于考试模式可能几年才变化一次,业务可扩展可以暂时不考虑。
版权声明: 本文为 InfoQ 作者【babos】的原创文章。
原文链接:【http://xie.infoq.cn/article/a1b5d69d076a19637f229608f】。未经作者许可,禁止转载。
评论