深度技术揭秘Twitter是如何处理每秒
前些年Twitter还主要提供文字信息为主,甚至有严格的字符限制。随着智能设备普及和网络升级,自年开始,Twitter选择主动拥抱变革,开始提供丰富的多媒体功能,这样的转变是通过Twitter自研的全新媒体平台(MediaPlatform)实现的。这个平台可以支持照片预览、多图发送、Gif动图、Vine视频以及内嵌视频等功能。
从这个Twitter媒体平台我们可以学习到一些有意义的东西:
1.因陋就简的思考方式注定失败
最容易想到的方式就是在发布推文的同时上传多媒体资源,无论最后成败与否,都需要长时间锁定,而且这种方式扩展性不好,尤其在网络比较差的时候,这使得Twitter很难增加新的功能。
2.去耦合
通过将推文与附带的多媒体去耦合,Twitter就可以分别针对各类资源的途径进行优化,更加具有灵活性。
3.移动句柄,而不是存储块
众所周知,移动磁盘上的数据效率很低,会导致需要移动这些数据的服务遭遇性能问题。更好的方法是单独存储数据,并通过句柄的方式进行引用。
4.分段可续传方式上传
这种方式可以大大降低上传失败的可能性。
5.持续试验和研究
Twitter研究发现,对于不同的图片变体(例如缩略图、小图、大图等)的存活期(Timetolive,TTL),20天算是一个阈值,这个值可以很好地平衡存储和计算的矛盾。超过20天的图片变体被访问的概率会大大降低。因此删除超过阈值的图片变体,可以每天节省至少4TB存储空间,使计算服务器计算量减少一半,每年至少节省数百万美元。
6.按需重建
就如上面研究所述,老图片变体很少被访问,如果再次访问可以即时重建,不需要一直存储。这种按需重建的方式可以提高灵活性,更加容易控制。
7.采用渐进式JPEG(ProgressiveJPEG)
是一种广泛使用的标准图片格式,无论前后台,都很好地支持这类格式,甚至在网络不好的时候,也有优异的表现。
Twitter的转型之旅有许多有趣的事情,我们来讨论他们具体怎么改变的。
第一阶段:年左右
一个年的用户通过App发了一条带图片的推文。客户端提交推文给一个集中式端点(monolithicendpoint),图片和其他推文内容一起上传,处理过程中所有内容的处理都是捆绑处理的。在这个设计里,这个集中式端点就变成了最大的troublemaker。
问题一:浪费大量宝贵带宽
推文和多媒体上传的创建紧密结合在一起。上传的过程具有不确定性,要么成功,要么失败。一旦出现网络中断,传输错误等,就要求全部从头传输。只有一张图片还好,如果几乎传完的一个大视频呢,那不是要崩溃了!
问题二:不能很好地兼容长多媒体文件
这种方式不会提前评估视频的体积,大文件会大幅提升上传失败的可能性,尤其是一个网络质量不是很好的地区,那就想都别想了。
问题三:内部带宽使用率低下
端点需要连接到处理用户认证和路由的TFE(Twitter前置终端,TwitterFrontEnd),然后用户会被路由到图片服务器。图片服务器会使用图片变体生成器创建各种不同的变体图片,所有变体图片都被存储在BlobStore(这是一种专为图片和视频等大型载荷进行过优化的key-value类型的容器)中,随后图片将永远存储在这里。
在创建和保存推文的时候还涉及到其他服务。因为端点是集中式的,如果将包含多媒体在内所有的推文内容一起处理,可能会影响到其他本不需要处理多媒体的服务,这些服务同样需要针对高负荷请求进行优化。这样的做法导致内部带宽使用效率严重降低。
问题四:存储空间占用急剧增加
数月甚至数年前发布的推文中所包含的图片可能已无人问津,但依然需要永远存储在BlobStore中,这些内容耗费了宝贵的存储空间。因为没有垃圾回收机制,有时甚至在推文被删除后,图片依然会保存在BlobStore中。
用户看到一条包含图片的推文。图片来自哪里?客户端从CDN请求图片的变体。CDN需要从原始位置或TFE检索该图片。
问题五:不可能引入新的变体
这种设计不是非常灵活。如果需要添加新的变体,也就是说需要为图片创建一个新的尺寸,此时必须为BlobStore中的每个图片创建一个新尺寸的版本。这种方式缺乏按需创建变体的便利机制。缺乏灵活性意味着Twitter很难为客户端添加新的功能。
第二阶段:年之后
为了解决以上问题,在年左右,Twitter做出了这些改变:
1.将多媒体的上传与推文本身解耦
成功上传是第一要务,那就需要一个专门用于上传原始图片到BlobStore的上传端点。这种方式为上传操作的处理提供了极大的灵活性。
客户端连接到TFE,TFE随后路由到图片服务器,图片服务器将图片保存至BlobStore并将相关数据转到元数据存储。这一过程不会涉及其他的服务,不需要处理媒体,也不需要四处传输图片。随后图片服务器会返回一个代表该多媒体文件的唯一标识符,即mediaId。
当客户端需要创建推文,发布私信或更新头像时,将使用这个mediaId作为引用该媒体的句柄,而不需要提供媒体的原始文件。
假设用户想要使用刚上传的图片发布推文,过程将会是这样:客户端连接到更新端点,在推文中包含mediaId,该请求将发送至TFE,随后TFE会将请求路由至对于所创建内容对应的服务。对推文本身服务是TweetyPie,私信和用户资料信息的处理也由不同服务进行,所有这些服务都能与图片服务器通信,图片服务器中包含处理面孔检测、儿童色情内容检测等功能,检查上传的资源,当这些功能执行完毕后,图片服务器会与处理图片的ImageBird或处理视频的VideoBird服务通信。ImageBird负责生成变体,VideoBird则对视频进行一定的转码,最终处理生成的媒体内容将保存至BlobStore。不再需要将媒体内容四处传输,借此可节约大量本被浪费的带宽。
2.分块可续传的上传
传输过程中突然网络中断,过一会恢复,上传过程可从上次中断的地方恢复进行,对用户来说该过程是完全无感的。
客户端使用上传API发起上传会话,后台会为用户提供一个mediaId,这个mediaId将在整个上传会话中充当标识符。
如果图片太大,就被拆分为多个小块,例如拆分成三块。这些文件块可使用API附加到一起,每次调用的附加操作可提供必要的片段索引,所有附加操作都可作用于同一个mediaId。上传完成后对上传内容进行合并,随后这个媒体就可以正常使用了。
这种方法更容易适应网络故障。每个独立小块可以重试,如果网络因为任何原因中断,用户可以暂停并在网络恢复后从暂停的位置继续上传。
3.引入MinaBird
此处用到了一种名为MinaBird的CDN源服务器。MinaBird可与ImageBird和VideoBird通信,这样就算不存在,也可以即时生成不同尺寸图片和不同格式视频的变体。
在处理客户端请求方面,MinaBird更流畅也更动态。举例来说,假设有内容由于DMCA(数字千年版权法)的要求需要删除,此时很容易便可阻止对相关内容的访问,或重新允许对媒体特定片段的访问。
4.按需生成
按需即时生成变体和转码的方式使得Twitter在存储容量的使用方面更为高效。按需生成变体,意味着不需要将所有变体都存储在BlobStore中,这是一个巨大的进步。
原始图片在删除前将一直保留,而变体只保留20天。继续保留更早前上传的图片可以获得的收益在逐渐下降。更老的媒体文件也有可能就此无人问津。
不设置存活时间(TTL)并且不过期的情况下,媒体文件的存储导致数据存储总量每天增加6TB,按需生成所有变体的“偷懒”做法会让数据存储总量每天增加1.5TB。在读取的同时生成所有变体,需要为每个数据中心提供台ImageBird服务器,而20天存活时间的做法只需要投入75台。
5.使用渐进式JPEG
客户端对渐进式JPEG的支持是通过Facebook的Fresco库实现的。Fresco库的功能很强大,就算在2G网络中也能实现绝佳效果。渐进式JPEG的首次扫描只产生10kb流量,因此很快就可以加载完成。当原生渠道还在等待加载,无法显示任何内容的时候,渐进式JPEG已经可以提供可分辨的图片。
这种格式可以使用逐行扫描的方式进行渲染,首次扫描的图片可能显得斑驳不匀,但可通过逐行扫描的方式逐渐进行完善。性能更好。
相比传统JPEG编码速度慢60%。但由于编码工作只需要进行一次,因此这不算什么大问题。虽然渐进式JPEG不支持透明,因此还需保留透明PNG,但在其他方面都很出色。
参考文献:
转载请注明:http://www.shijichaoguyj.com/wxjq/2433.html