视频共享服务系统的目的 Youtube是基于广告的视频共享服务,允许用户上传基于视频的媒体内容。用户可以上传、观看、搜索、喜欢、不喜欢视频、向视频添加评论。用户只能作为注销用户上传/删除视频,但他们可以作为注销用户搜索/观看视频。这项服务是一项基于广告的免费服务,因此用户在观看视频时会看到广告。此外,用户可以通过自己的帐户跟踪其他用户或渠道。此外,用户只有在登录系统时才能向视频添加评论。 在开始设计任何系统(如照片和视频共享社交网络服务系统)之前,建议详细考虑系统边界和要求,并尝试了解未来(如5年或10年)的系统容量。这是非常关键的,因为在某些情况下,如果系统的用户数呈指数增长,该系统的容量将不足以提供快速响应。在建筑设计背后,你必须考虑五大支柱(可用性、可靠性、弹性、耐用性和性价比)。这些是我们应该一起考虑的支柱,因为它们是相互耦合的。简而言之,可用性意味着系统应该始终可用。可靠性意味着系统应该按预期工作。弹性意味着,如果出现任何问题,系统将如何以及何时自我恢复。耐久性是系统每个部分都应该存在的支柱,直到我们删除它。性价比也是一个重要的话题,它基本上与在成本效率下使用服务有关。可以这样说明,如果系统将建立在AWS上,并且足以使用t2 micro EC2实例,那么就没有任何理由使用更大的EC2实例并支付额外费用。 系统的要求和目标 Youtube是最大的视频共享服务之一,现在它有很多组件,但过去它不是这样创建的。每个系统都越来越注重增长,系统的组件将比第一个版本更多。现在我们将设计Youtube的主要功能。我们不会详细讨论推荐系统、频道背景、搜索系统,因为它们都是独立的讨论主题。 因此,如果你想设计一个系统,你必须首先定义需求和系统边界。您可能会有一个服务设计文档,并在该服务设计文档中定义需求、边界、架构决策和其他内容。Youtube是一种视频共享服务,用户可以上传/观看视频。因此,您的系统将支持这些功能; –用户必须能够创建帐户。 –每个注册用户都必须有自己的个人账户页面。 –用户必须能够登录系统并从系统中注销。 –用户登录时必须能够在系统中上传/删除视频。 –用户必须能够在登录时向系统中的视频添加评论。 –用户登录或注销时必须能够在系统中观看视频。 –用户登录或注销时必须能够搜索视频/用户/组。 –用户必须能够关注频道。 –用户必须能够喜欢/不喜欢视频。 –用户可以喜欢或不喜欢视频,在这种情况下,系统应该保留喜欢、不喜欢、评论、视图的数量,以将这些数量呈现给用户。 –系统必须能够监控。 –系统必须能够支持公共和私人账户。 –系统必须能够支持公共和私人视频。 在定义系统边界和功能需求时,需要考虑云或承诺选项。你的系统可以是; –承诺%100(您自己的数据中心/服务器) –%100云(AWS、谷歌云、Azure) –OnPromise和cloud的混合(在迁移过程中,您可以同时拥有这两种功能) 如今,由于云机制的优势,云服务已经非常流行。这些优势; –成本效益 –高速 -安全 –备份解决方案 –无限存储容量 –有很多不同的服务选项。你们不需要从头开始创造世界 –可靠性 –耐用性 –弹性 –监控几乎所有服务 –易于与其他服务进行软件集成 如果我们谈论Youtube、Netflix或其他大型可扩展系统,这意味着这些系统将面临大量流量。系统中可能同时有大量请求,系统应该倾向于在实时体验中响应所有请求。复制、分片和负载平衡器有助于系统的高可用性。稍后我们将讨论这三个特性。 此外,系统应以最小的延迟响应。假设你是一个用户,你想在Youtube上做任何事情,你真的想等很长时间才能得到回复吗?我认为你不想等待太多时间,也不想实时体验系统。为了说明这一点,当您在系统中搜索视频时,该系统应尽快建议相关视频。 让我们考虑一下设计界限; 由于很多用户会在系统中观看视频,所以该服务将被大量阅读,所以系统将保持一致性和可靠性,这意味着不会有任何数据丢失。此外,服务将是持久的,这意味着系统的所有部分都应该存在,直到它们被手动删除。在考虑容量之前,您必须定义服务的目的。即使这对on promise服务更为重要,但对on promise和云服务都非常重要,因为您可以根据目的选择正确的服务,根据可用区域定位服务,并定义容量。这些例子包括:; –创建比写服务更多的读服务。 –根据操作类型选择服务器类型。 –根据容量估算定义缓存策略。 –根据您的需求选择数据库类型(SQL、NoSQL)。 –根据您的容量估计定义备份解决方案。 –根据您的需求等定义数据分片策略… 假设用户总数为1亿,读流量大于写流量,下载和上传数据的比例为25:1。 我们将假设视频的平均大小为250 MB,因此系统将具有:; 5年的视频容量; –5*100M*1*250MB=120PB。(假设每个用户每年上传1个视频)。 –360 PB,具有复制和备份功能。 这个计算只是一个简短的例子,说明如何定义系统容量,我们不计算每日下载/上传容量和元数据容量,但是你应该考虑这个计算(和每日读/写容量估计)服务/数据库缩放。 此外,缓存是返回数据的基本系统。如果要构建大型可扩展系统,就必须考虑不同的缓存策略。您可以将CDN用作视频内容缓存,将Redis/Memcache用作元数据缓存。缓存的最大问题是可伸缩性(全局缓存机制)和缓存逐出策略。如果您正在AWS上构建服务,那么可以使用Cloudfront作为CDN(内容缓存),也可以使用AWS上的elasticache服务进行元数据缓存。请注意,Cloudfrount是高度可伸缩的AWS服务,您不需要使用维护/可伸缩性。AWS将自行维护和扩展Cloudfront服务。 API设计 在当今世界,许多系统都支持移动平台,因此API是能够区分开发人员和支持移动支持的最佳选择。我们可以用休息或肥皂。许多大公司更喜欢根据自己的系统使用REST或SOAP。我们将在下面提到三个主要的API: 1-上传视频(apiKey、标题、描述、类别、语言) 上传视频是我们应该提到的第一个API。这个API基本上有五个主要属性。您可以向UploadVideo API添加更多属性。请注意,apiKey是服务注册帐户的开发者密钥。多亏了apiKey,我们可以消除黑客攻击。UploadVideo返回HTTP响应,该响应显示视频是否成功上载。 2-删除视频(apiKey,videoID) 检查用户是否有删除视频的权限。如果操作已排队,它将返回HTTP响应200(确定)、202(接受),或者根据您的响应返回204(无内容)。 3-GetVideo(apiKey、查询、videoCountToReturn、页码) 返回包含视频和频道列表信息的JSON。每个视频资源将有一个标题,创建日期,如计数,总视图计数,所有者和其他元信息。 **有更多的API来设计视频共享服务,然而,这三个API比其他API更重要。其他API将像likeVideo、addComment、搜索、推荐等… 数据库设计 定义数据库模式有两种选择。它们是SQL和NoSQL。我们可以使用传统的数据库管理系统,如MsSQL或MySQL来保存数据。如你所知,我们应该将有关视频和用户的信息保存到RDBMS中。关于视频的其他信息,称为元数据,也应该保留。现在我们有三个主要的表来保存数据。(注意,我们只考虑Youtube的基本属性。我们可以忘记推荐系统)。 使用者 –用户ID(主键) –姓名(nvarchar) –年龄(整数) –电子邮件(nvarchar) –地址(nvarchar) –注册日期(日期时间) –上次登录(日期时间) 视频 –VideoID(主键–由KGS生成–密钥生成服务) -视频标题(nvarchar) –尺寸(浮动) –UserID(带用户表的外键) –说明(nvarchar) –CategoryID(int):请注意,我们可以创建类别表来定义类别 –喜欢的数量(整数) –不喜欢的数量(整数) –显示的数字(整数)-我们可以使用大整数来保持显示的数字 –上传日期(日期?me) 视频评论 –CommentID(主键) –UserID(带用户表的外键) –VideoID(带视频表的外键) –评论(nvarchar) –注释日期(日期时间) 系统设计考虑 基于网络的系统有一些基本功能。主要包括客户端、web服务器、应用服务器、数据库和缓存系统。根据系统流量的强度,服务器或服务的数量会增加,负载平衡器会在这些服务器或服务之间分配传入的请求。此外,根据传入请求者的密度,可以使用队列。队列操作可以帮助用户避免等待更多时间来获得响应。在我们的Youtube服务中; -客户 –网络服务器 –应用服务器 –数据库 –视频存储 –编码服务 –排队 –复制 –冗余 –负载平衡 -切分 我们可以将服务分为三个部分,以减少响应时间,因为视频上传比视频下载需要更多时间。视频可以从缓存中下载,从缓存中获取数据是一种快速的方法。客户端主要是使用系统的用户。Web服务器是第一个满足请求的实体。传入请求可以在上传服务、搜索服务或下载服务中进行。如果我们给异步下载视频的用户一个机会,系统流量将得到缓解。编码器是将上传的视频编码成多种格式。有三种类型的数据库,即视频内容数据库、用户数据库和视频元数据存储。队列过程发生在应用服务器和encode之间。 我们的Youtube服务会被大量阅读,我们在构建系统时应该小心。我们的主要目标应该是尽快返回视频。我们可以在不同的服务器上保存视频副本,以解决交通问题。此外,这确保了该系统的安全性。我们可以使用负载平衡器将流量分配到不同的服务器。该系统还可以保存元数据数据库、用户数据库和视频内容数据库的两个副本。我们可以使用CDN来缓存流行数据。 系统流程图; 1-客户端发送请求。 2-来自Web服务器的请求满足。 3-Web服务器控制缓存。系统上可能还有两个缓存数据库。 4-如果请求发生在缓存中,响应将重定向到客户端。 5-否则,web服务器会将请求重定向到应用服务器。 6-web服务器和应用服务器之间可以有负载均衡器。 **如果此请求是搜索或查看服务,它会通过查看元数据数据库和视频内容数据库来尝试查找请求。负载平衡器可以放置在系统的每一层,例如应用服务器和视频内容存储之间,应用服务器和元数据数据库之间,等等… 当服务器向客户机响应请求时,相关数据将根据缓存过程进行缓存。 众所周知,Youtube是一个巨大的视频分享系统。用户可以上传视频,上传视频的数量每天呈指数增长。根据上传的视频,系统中可能还有一个相同的视频。为了消除视频的重复,我们可以实现一种智能算法。例如,当视频进入系统时,算法会自动检查该视频是否已保存在系统中。如果系统已经有了这个视频,那么我们就不需要保存重复的数据。它使我们免于不必要地使用空间。此外,如果传入的视频包含保存在系统中的视频,那么我们可以将视频分成小块,只需对相同的视频块进行引用即可处理复制问题。 复制和备份是我们前面提到的提供支柱的两个重要概念。复制是处理服务或服务器故障的一个非常重要的概念。复制可以应用于数据库服务器、web服务器、应用服务器、媒体存储等。。实际上,我们可以复制系统的所有部分。(一些AWS服务,如Route53,其本身具有高可用性,因此您无需负责Route53、负载平衡器等的复制。)请注意,复制还可以帮助系统缩短响应时间。您可以想象,如果我们将传入请求划分为多个资源,而不是一个资源,那么系统可以轻松满足所有传入请求。此外,每个资源的最佳副本数为3个或更多。您可以通过将数据保存在AWS的不同可用性区域或不同区域来提供冗余。 对于缓存策略,我们可以通过使用缓存服务器来使用全局缓存机制。我们可以使用Redis或memcache,但缓存策略最重要的部分是如何提供缓存逐出。如果我们使用全局缓存服务器,我们将保证每个用户将在缓存中看到相同的数据,但如果我们使用全局缓存服务器,则会有时间延迟。作为一种缓存策略,我们可以使用LRU(最近使用最少的)算法。 如前所述,对于媒体文件缓存,我们将使用CDN。CDN位于不同的边缘位置,因此响应时间比直接从AWS S3获取媒体内容要短。 负载平衡器允许根据特定条件将传入请求重定向到资源。我们可以在系统的每一层使用负载平衡器。如果我们想使用AWS负载平衡器服务,AWS将支持三种不同的负载平衡器类型,分别是:; –网络负载均衡器 –经典负载平衡器(已弃用) –应用程序负载平衡器 对于这项服务,应用程序负载平衡器将适合我们的服务,它还将自己处理AZ分发。否则,你可以使用NGinx,但你必须实现算法,如果我们想使用NGinx,你必须提供维护。 我们可以使用负载均衡器; –在请求和web服务器之间。 –在web服务器和应用服务器之间。 –在应用服务器和数据库之间 –在应用服务器和图像存储之间。 –在应用服务器和缓存数据库之间。 –我们可以对负载平衡器使用循环方法。循环方法防止请求进入死机服务器,但循环方法不能处理任何服务器处于高流量的情况。我们可以修改循环法,使之成为一种更智能的方法来处理这个问题。 视频上传是一个大过程。它应该使用分片机制,当出现故障时,系统应该确保继续从故障点上传视频。 视频编码过程应该包括队列操作。当上传的视频出现时,这个新任务会被添加到队列中,队列中的所有任务都会从队列中逐个执行。 系统基本编码
JAVA
// Java program for design public enum AccountStatus{ PUBLIC, PRIVATE, CLOSED } public enum VideoContentStatus { PENDING, PROCESSED, FAIL, REJECTED } public enum VideoStatus { PUBLIC, PRIVATE, DELETED } public enum VideoQuality { LOW, MIDDLE, HIGH } public class AddressDetails { private String street; private String city; private String country; ... } public class AccountDetails { private Date createdTime; private AccountStatus status; private boolean updateAccountStatus(AccountStatus accountStatus); ... } public class Comment { private Integer id; private User addedBy; private Date addedDate; private String comment; public boolean updateComment(String comment); ... } public class Video { private Integer id; private User createdBy; private String path; private VideoStatus videoStatus; private VideoContentStatus videoContentStatus; private int viewsCount; private HashSet<Integer> userLikes; private HashSet<Integer> userDisLikes; private HashSet<Integer> userComments; ... } public class User { private int id; private String password; private String nickname; private String email; private AddressDetails addressDetails; private AccountDetails accountDetails; private UserRelations userRelations; private HashSet<ConnectionInvitation> invitationsByMe; private HashSet<ConnectionInvitation> invitationsToMe; private boolean updatePassword(); public boolean uploadVideo(Video video); public List<Videos> getVideos(); ... } |
参考:http://highscalability.com/youtube-architecture 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。