如图所示,我们在上传本地数据文件时,依然使用分片方式上传。每读取一帧数据,判断一下数据的时间戳有没有到达事件的开始时间。如果到达,那么就向web服务器汇报一次事件信息,并且记录下这个事件的开始在该分片文件中所处的位置。同样,判断当前正在处理的事件,比较时间戳,是否已经达到结束时间。如果已经结束,同样记录一个结束位置。一个分片文件可能对应多个event,有些event在这个分片文件的某个地方开始,有些event在这个分片文件的某个地方结束,还有些event可能占有整个分片文件。当一个分片文件上传结束时,需要向web服务器汇报分片文件信息,包括一些基本信息(大小,媒体参数,以及文件的uri等),以及分片文件与event的映射关系,即event的位置信息。在数据库的设计中,event存储一个表项,分片文件存储一个表项,映射关系存储一个表项。
关系如下图所示:
在event与file的映射表项中,存储了event与file id,以及这个event的开始位于file的位置(start_pos)以及结束位置file中的位置(end_pos)。如果这个event不在这个file中开始,也不在这个file中结束,那么说明这个file处于这个event的中间,既不是第一个分片,也不是最后一个分片,那么start_pos就是0,end_pos就是分片文件大小,即分片的结束。index就是这个分片文件是该event的第几个分片文件。
当我们观看某个云视频时,只需要在数据库中按照event进行查找,即可以返回这个event的所有分片文件。观看端拿到这些分片文件信息去亚马逊S3下载,就行播放。
对于数据库的影响:
2.0版本中,对于一个event在上传一个分片文件之后,就要向web服务器汇报一次。web服务器判断该event是否是第一次汇报,如果是在数据库插入一行新的表项;如果不是,则要更新之前插入的表项
3.0版本中,分片文件每次汇报,只需要插入表项即可,没有更新操作。event信息在开始的时候汇报一次,在结束的时候需要更新一次。
整体来说,3.0版本中减少了数据库的update操作。搞过数据库的人都知道,更新操作比插入对数据库的消耗大得多,从某种意义上来说也变相减轻了数据库的负载。
在3.0版本中,我们修改了redis的使用策略。2.0版本仅仅用redis来统计每天的event数量,但是其实在查询的时候,我们并不需要关心有多个数量。移动端查询时,是按业来查询的,每次查询10个,每次向下翻页就再查询10个,无法再翻页时,就说明已经查询出当天所有数据了。为了提高查询性能,我们将event的信息存储在redis里面。包括event 的触发时间,时长,icon信息。按照日期+cid(采集端的id,唯一标识)+type(event类型)作为key, value是一个list类型的值,保存当天所有的event id信息。然后再用eventid作key, value保存event的详细信息。这样在查询时,先按照cid+日期+类型找到列表key,从里面读取一页的数据。然后再根据这一页的数据,去查询里面每个event的详细信息。这样在查询列表时就不要再访问数据库了。
浓缩视频,压倒数据库的最后一根稻草
3.0版本上线三个月之后,系统运行的还算良好,但是我们发现数据库表项在飞速膨胀。我们的云服务用户已经有几万个,每个采集端每天平均都要上传几十条视频,所以按照这种速度,单表记录很快就来到了将近1000w。在mysql上,1000万几乎就是单表记录上限了。搞web的兄弟发现这一趋势后,做了分表方案。按照采集端的cid尾数 即(0-9),将event,file,以及映射表分成了10张表。虽然是解决了存储方面的问题,但是随着使用云服务的用户在不断增加,数据库的访问压力也在渐增。在3.0版本,我们新增了浓缩视频功能,就是将一天中的视频变化压缩成很短的几分钟。由于短视频每天才产生一个,所以我们在当天录制完之后,第二天的0点之后开始上传前一天产生的浓缩视频。这个功能在3.0版本上运行了一段时间,刚开始没有问题。但是在不知不觉中,却为自己刨了一个大坑。那段时间运营部门搞促销活动,用户登录送积分,用积分赠送云服务。突然有一天,测试人员早上过来后发现前一天的浓缩视频没有上传,翻开采集端日志一看,在凌晨0点之后那段时间,所有的web请求全部失败了。让运维同学查看了下凌晨那段时间发生了啥,一看惊呆了,在0点0分0秒那一刻,瞬间涌入了上万的请求。web服务器还好,有负载均衡,但是数据库只有一台,1s之内成千上万的请求,数据库不死才怪。由于在采集端做了失败重试,请求失败之后又会接着再次请求,数据库几乎一直在"卧倒"状态。幸好的是,采集端做了重试次数限制,所以基本在凌晨1点之后请求数也就慢慢降下来了。而这一切,都是由于浓缩视频集中在凌晨那段时间上传导致的。做促销活动的那几天,每天都会送出1w多的云服务,一下子就把数据库压垮了。其实解决这个问题的方法很简单,对于浓缩视频来说,我们只要保证上传了就可以,没必要非得全部挤在0点这个时间。我们把上传的时间随机延长至0~5点之间任何一个时间点,保证用户在早上起来后能查看到即可。很快就出了更新版本,服务器的访问压力随即降了下来,服务也回归正常。但是还是有一种隐约的不安,因为用户还在快速增长,不知道哪一天服务器又会遇到类似的问题。
4.0 火炮时代