写点什么

架构实战营模块 4 作业

用户头像
En wei
关注
发布于: 2021 年 05 月 16 日

题目

基于模块 4 第 6 课的估算结果和 Redis sentinel 的初步方案设计,完善考试试卷存储方案,具体包括:

1)完善 Redis 的数据结构设计,明确具体使用哪种 Redis 数据结构

2)设计具体的读写流程(可以文字描述也可以序列图描述,序列图要有文字辅助说明)

3)对照模块 4 第 6 课的性能估算结果,计算 Redis sentinel 集群的服务器数量和性能

题目分析

相关的考试性能评估详情


每秒 5W 的 QPS,这个量级还是比较吓人的,但考虑到几乎全部是读取,单台 redis 完全可以胜任。在考虑高可用,那么 redis sentinel 就可以应对,其实 Redis Cluster 不是更香么。

场景分析

试卷既然放到 Redis 中保存,必然是序列化保存的的,按照应用场景区分为写入和读取。

1)出卷场景分析

老师出卷时是一道一道出的,而且他肯定不想刷新一下界面就把数据都丢了,而且很有可能后面还去修改之前出的某张试卷的某个题目。

ok,梳理一下需求:

  • 可以将整张试卷保存下来

  • 修改某张试卷的试题

  • 以读取之前的某张试卷


2)考试场景分析

学生考试获取试卷都是整张试卷读取的,没有范围查询的需求,因此最好是直接能把试卷的全部题目读取出来。


题目回答

完善 Redis 的数据结构设计

我们知道 Redis 中共有五种常见数据结构: 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets)。

根据我们场景分析结论,进行存储的数据结构涉及。

  • 直接采取字符串的话,直观上可以满足需求,但这需要将正张试卷进行序列化和反序列化,这在保存和读取整张试卷是没有问题的,但在修改上就需要读取整张试卷,然后修改对应部分,再重新序列化并保存,怎么看都不是很合适。但字符串比较适合保存试卷状态,如编辑中或是已发布。

  • 散列:适合于试卷-题目两级存储,但由于存储的数据没有顺序,不太合适保存有顺序属性的题目。

  • 集合:适合于试卷-题目两级存储,但由于存储的数据没有顺序,不太合适保存有顺序属性的题目。

  • 列表:适合于试卷-题目两级存储,其实是比较适合存储试卷的,但由于还想修改指定试卷的指定元素,这需要 O(n)的复杂度,n 为列表长度

  • 有序集合:适合于试卷-题目两级存储,将题目序号作为 score,题目序列化后作为 value 存储。学生考试时获取整张试卷通过 ZRange min max 实现,老师出题时添加或修改题目通过 zadd 序号 题目序列化值实现。


接下来就在于 Key 的设计了,需求也是比较明确的,希望能够直接读取到指定的试卷,那么只需要考虑试卷的一些基本属性,如下所示。

  • 年份(2021)

  • 学校(学校代号)

  • 年级(高三-3)

  • 科目(物理-PHY,化学 CHE)

  • 考试类型(期中-MID,期末-END)

key 的示例如下:


2021年南开中学高二物理期中试卷
2021:NK:2:PHY:MID
复制代码

综上所述:

有序集合存储试卷,题目序列化后作为value,题目序号作为scorce,都保存在年份:学校:年级:科目:考试类型的key下。
另外试卷的状态采用String的形式保存,key选择年份:学校:年级:科目:考试类型:STATE,value则保存具体状态。
复制代码


设计具体的读写流程


出试卷场景(试卷写入)

  1. 老师再前台编写试卷的题目

  2. 前台将题目数据传输到后台

  3. 后台将数据序列化为 value

  4. 后台组装试卷的 key,index 代表序号

  5. 后台通过 ZADD key index value 写入数据

  6. 重复 1~5 步直至全部题目保存完毕

  7. 前台保存整张试卷

  8. 后台组装试卷状态的 key

  9. 后台通过 set key 已发布来实现试卷状态的变化。


开始考试场景(试卷读取)

  1. 前台读取指定的试卷

  2. 后台组装试卷的 key

  3. 后台通过 ZRange 1 44 读取全部的题目

  4. 将全部数据反序列化为题目数据返回前台

  5. 前台根据返回的数据进行渲染

计算集群的服务器数量和性能

试卷存储估算细化

课程里只给出了选择 RedisSentinel 的选型,但估算这块没有详细估计试卷的存储,为了后面服务器估算,因此在这里补充一下对试卷存储的估算,课程中估算的核心数据如下:

  • 1000 万学生

  • 每年考 2 次

  • 20 门课

假设每 200 人一个年级,即一共有 5 万个年级,结合 20 门课和每年 2 次考试,则每年共有大概 200 万不同的试卷。

一份试卷由 20 判断,20 选择,4 道大题组成,这里将所有的图都保存到 CDN,文件另行存储,试卷中大部分为汉字(一个汉字 2 字节)。可以估算 20*100*2+20*(100+40*4)*2+4*400*2=17600 字节,为留出余量,按照 20kb 估算。

【为了验证估算,又找了一个高三的政治月考试卷全部文字加起来不到 4000 字,因此 20kb 大小估算还是留出了相当大余量的。】

则试卷所需的存储共计 2000000*20kb=40GB。

服务器数量和性能

上面计算得到年度全部数据应该不超过 40G,服务器内存 64G 内存就差不多了,Redis Sentinel 使用的必然要组成集群,至少三台服务器,每台服务器部署一个 Sentinel 和一个 Redis 节点。由于 Redis 需要持久化数据因此不可避免的需要频繁访问硬盘,所以硬盘还是配备一个固态比较好。

服务器性能,64G内存+1T硬盘+32核CPU
服务器数量,3
复制代码


学习分享

这个模块主要讲的就是数据存储的设计,还是老样子,分为 3 次上 6 个课时。

先后介绍了存储架构的基本概念,复制架构,分片和分区架构,作为基础知识。

紧接着从理论上介绍了如何设计存储架构,简单来说就是先估算性能需求,再选择存储系统,然后设计存储方案这三步,后两步是不断迭代进行的。

然后又介绍了常见存储系统,从技术本质上介绍了 hbase,redis,ClickHouse 以及 HDFS,这个很赞。

最后结合之前的千万级学生管理系统的示例,进行了存储系统设计的实战。

学完了这些课程之后还是一种看上去很简单,但自己干时却是一种找不着方向的感觉,架构确实是比较微妙很吃经验和感觉。

后面只能再把课程多复习几遍,慢慢的找感觉,很多东西不是一朝一夕就能搞定的。


发布于: 2021 年 05 月 16 日阅读数: 17
用户头像

En wei

关注

还未添加个人签名 2017.12.10 加入

还未添加个人简介

评论

发布
暂无评论
架构实战营模块4作业