视频播放进度记录方案改进

为了更精确的记录用户上一次播放的进度,我采用的方案是:前端每隔10秒就发起一次请求,将播放记录写入数据库。这涉及到大量的数据库写操作,在并发较高的情况下,会给数据库带来非常大的压力。该怎么解决呢?

1. 功能背景

  • 网站课程以录播视频为主,为提升学习体验,需要实现视频续播功能。

  • 用户断开连接或切换设备后,仍然可以从上一次播放位置继续学习。

  • 产品要求

    • 续播时间误差控制在 20 秒以内。

    • 支持多设备切换续播。

2. 目前方案

前端在播放视频时,每隔 10秒通过心跳请求将当前播放进度(currentTime)发送到服务端,服务端将数据写入数据库。

3. 方案改进

播放进度记录较为频繁,写数据库的压力太大。

3.1 改进方案

当写数据库并发较高时,不再直接写到数据库。而是先将数据缓存到Redis,然后定期将缓存中的数据批量写入数据库。

由于Redis是内存操作,写的效率也非常高,这样每次请求的处理速度大大提高,响应时间大大缩短,并发能力肯定有很大的提升。

而且由于数据都缓存到Redis了,积累一些数据后再批量写入数据库,这样数据库的写频率、写次数都大大减少,对数据库压力小了非常多!

变化最大的有两点

  • 提交播放进度后,如果是更新播放进度则不写数据库,而是写缓存(覆盖之前旧数据)

  • 需要一个定时任务,定期将缓存数据写入数据库

3.2 优缺点

3.2.1 优点

  • 写缓存速度快,响应时间大大减少

  • 降低数据库的写频率和写次数,大大减轻数据库压力

3.2.2 缺点

  • 实现相对复杂

  • 依赖Redis可靠性

  • 不支持事务和复杂业务

3.2.3 场景

  • 写频率较高、写业务相对简单的场景

3.3 持久化思路

3.3.1 一般思路

提交播放进度后,如果是更新播放进度则不写数据库,而是写缓存(覆盖之前旧数据)。

所有一定有一个步骤就是持久化缓存数据到数据库。一般采用的是定时任务持久化。

3.3.2 存在问题

但是定时任务的持久化方式在播放进度记录业务中存在一些问题,主要就是时效性问题。我的产品要求视频续播的时间误差不能超过20秒。

  • 假如定时任务间隔较短,例如15秒一次,对数据库的更新频率太高,压力太大

  • 假如定时任务间隔较长,例如2分钟一次,更新频率较低,续播误差可能超过2分钟,不满足需求

注意:如果产品对于时间误差要求不高,定时任务处理是最简单,最可靠的一种方案,推荐使用。

3.3.3 问题分析

那么问题来了,有什么办法能够在不增加数据库压力的情况下,保证时间误差较低吗?

假如一个视频时长为20分钟,我们从头播放至15分钟关闭,每隔10秒提交一次播放进度,大概需要提交90次请求。

但是下一次我们再次打开该视频续播的时候,肯定是从最后一次提交的播放进度来续播。也就是说续播进度之前的N次播放进度都是没有意义的,都会被覆盖。

既然如此,我们完全没有必要定期把这些播放进度写到数据库,只需要将用户最后一次提交的播放进度写入数据库即可。

但问题来了,我们怎么知道哪一次提交是最后一次提交呢?

只要用户一直在提交记录,Redis中的播放进度就会一直变化。如果Redis中的播放进度不变,肯定是停止了播放,是最后一次提交。

因此,我们只要能判断Redis中的播放进度是否变化即可。怎么判断呢?

3.3.4 持久化思路

每当前端提交播放记录时,我们可以设置一个延迟任务并保存这次提交的进度。等待15秒后(因为前端每10秒提交一次,15秒就是等待下一次提交),检查Redis中的缓存的进度与任务中的进度是否一致。

  • 不一致:说明持续在提交,无需处理

  • 一致:说明是最后一次提交,更新视频播放进度到数据库中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyt涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值