1. 需求简介算法
根据用户的测试状况,给他推荐相应的课程,而后根据学习时长能够得到勋章数据库
2. 效果图缓存
3. 功能拆解异步
3.1. 测试题分布式
【要点】学习
一、 须要一个题库,配好题目和答案选项;测试
二、须要根据用户的答题状况(分数)抽取必定量的各类类型的题目大数据
三、本次抽取的题目与上一次的题目重复率不得超过50%spa
四、提交答案3d
【难点】
这个功能最复杂的地方在于重复率不得超过50%,能够用两次的题目去交集来判断,也能够排除上一次的题目后再随机,没有用什么高深的算法(主要是不懂)这里我用的后者,再也不赘述。
3.2. 生成计划
【要点】
一、从大数据那里获取推荐内容
二、上一个计划未完成不容许开启下一个计划
三、同种勋章只能得到一次
四、保存数据(计划、计划详情、勋章、消息)
【难点】
一、调大数据的接口时要考虑到失败的状况,即便大数据的服务挂了,我们也不能挂,为此加上try...catch,超时时间等等都是必要,这还不够。万一调大数据失败了,返回保底数据。
二、考虑到重复提交的状况,需加分布式锁
3.3. 计划首页
【要点】
一、内容展现,包括分已购未购、免费付费、会员非会员、标签等等
二、学习时长展现,包括时长、天数、当前阶段、勋章等等
【难点】
一、查数据库想都不要想,首选直接查Redis,可是Redis查的次数多了综合起来也有可能慢,必要时可考虑本地缓存(内存缓存)
二、时长、天数等均从在Redis总累计,可直接获取
3.4. 学习时长
【要点】
一、实时记录
【难点】
一、线上相似的接口高峰时段可达到1分钟84万次请求,所以想都不用想,必须异步,咱们采用MQ
二、尽管消费者是一条一条的消费,然而这并不意味着一秒钟只消费一条,据观察,线上其它相似MQ消费者平均一秒钟消费300条
三、时长最终是要更新到MySQL数据库中的,可是如此频繁的写数据,风险比较大,想来想去,最终选择用定时任务在夜深人静的时候从Redis同步到MySQL
四、学习时长是一个特别重要的参数,关系到挑战任务,关系到勋章,所以以秒为单位,累计至1分钟再写入
五、在压测的时候,我发现基于Redis的分布式锁彷佛并不能保证彻底100%锁住,虽然几率极低,但我好像碰到了
3.5. 楼层
【要点】
一、根据用户计划的状态展现不一样的按钮及背景图
二、连续关闭两次楼层后再也不出现,新开启计划后再次出现
【难点】
一、用户关闭楼层的行为直接记到Redis中,没必要存数据库
3.6. 弹窗
【要点】
一、每一个挑战任务对应一个勋章,再加上最后一个奖励勋章。任务是有顺序的,所以弹窗也是,为此须要知道任务先后的关系
二、每一个弹窗只弹一次,所以须要记录用户是否查看过
【难点】
一、用双向链表将挑战任务串联起来,这样就能够根据当前所处阶段快速找到上一个或下一个任务
二、在Redis缓存结构上,我犯了一个错误。缘由我想的是既然是有顺序的要不就用List类型,可是后来发现更新的时候极其不方便,要把全部的元素先删除(LTRIM命令),而后修改后从新插入,在一次压测过程当中发现里面大量重复数据,还没删完就已经插入了,因而越插入越多,这就是偷懒的代价,最终紧急改为Hash类型,这样即便有重复也会被覆盖。
3.7. 通知消息
【要点】
一、APP消息和站内信都要发
二、不用的阶段的消息文案不同
【难点】
一、定时任务扫描
二、异步发送,保证互不影响
4. 压测
全部的Redis查询都是批量查询,即便是这样,响应时间依然很长,平均响应时间400ms左右。用PinPoint分析排查:
后来,加上了本地缓存Caffeine,感受快了不少
顺便看下其它指标