李成笔记网

专注域名、站长SEO知识分享与实战技巧

System Design一之从0到百万用户的扩展[下]

内容分发网络(CDN) Content delivery network (CDN)

CDN是一个地理位置分散的服务器网络,用于传递静态内容。CDN服务器缓存静态内容,如图像、视频、CSS、JavaScript文件等。


动态内容缓存是一个相对较新的概念,超出了本课程的范围。它可以缓存基于请求路径、查询字符串、cookie和请求头的HTML页面。本课程重点介绍如何使用CDN缓存静态内容。


以下是CDN的高级工作方式:当用户访问网站时,离用户最近的CDN服务器将提供静态内容。直观地说,用户离CDN服务器越远,网站加载速度就越慢。例如,如果CDN服务器在旧金山,洛杉矶的用户将比欧洲的用户更快地获得内容。图9是一个很好的例子,展示了CDN如何缩短加载时间。

1.用户A试图通过使用图像URL来获取image.png。该URL的域由CDN提供商提供。以下两个图像URL是用于演示Amazon和Akamai CDNs上的图像URL的示例:

  • https://mysite.cloudfront.net/logo.jpg
  • https://mysite.akamai.com/image-manager/img/logo.jpg

2.如果CDN服务器的缓存中没有image.png,CDN服务器会从源服务器请求文件,源服务器可以是web服务器或在线存储,如亚马逊S3。


3.原点将image.png返回给CDN服务器,其中包括可选的HTTP报头生存时间(TTL),该报头描述了图像缓存的时间。


4.CDN缓存图像并将其返回给用户a .图像会一直缓存在CDN中,直到TTL过期。


5.用户B发送一个请求来获取相同的图像。


6.只要TTL没有过期,就会从缓存中返回图像。

使用CDN的注意事项

  • 费用:CDN由第三方提供商运营,您需要为进出CDN的数据传输付费。缓存不经常使用的资产不会带来显著的好处,因此您应该考虑将它们移出CDN。
  • 设置适当的缓存过期时间:对于时间敏感的内容,设置缓存过期时间非常重要。缓存到期时间不应太长也不应太短。如果太长,内容可能不再新鲜。如果太短,可能会导致内容从源服务器重复加载到CDN。
  • CDN回退:您应该考虑您的网站/应用程序如何应对CDN故障。如果出现临时CDN中断,客户端应该能够检测到问题并从源端请求资源。
  • 使文件失效:通过执行以下操作之一,您可以在文件到期前将其从CDN中删除: 使用CDN供应商提供的API使CDN对象无效。
  • 使用对象版本控制来提供对象的不同版本。要对对象进行版本控制,可以向URL添加一个参数,如版本号。例如,版本号2被添加到查询字符串:image.png?v=2。

图11显示了添加CDN和缓存后的设计。

1、静态资产(JS、CSS、图像等)不再由web服务器提供服务。它们是从CDN中提取的,以获得更好的性能。

2、通过缓存数据来减轻数据库负载。

无状态web层

现在是时候考虑横向扩展web层了。为此,我们需要将状态(例如用户会话数据)移出web层。一个好的做法是将会话数据存储在持久存储中,如关系数据库或NoSQL。集群中的每个web服务器都可以访问数据库中的状态数据。这被称为无状态web层。

有状态的体系结构

有状态服务器和无状态服务器有一些关键区别。有状态的服务器会从一个请求到下一个请求记住客户端数据(状态)。无状态服务器不保留任何状态信息。

图12显示了一个有状态体系结构的示例。

在图12中,用户A的会话数据和配置文件映像存储在服务器1中。若要对用户A进行身份验证,必须将HTTP请求路由到服务器1。如果向服务器2等其他服务器发送请求,则身份验证将失败,因为服务器2不包含用户a的会话数据。类似地,来自用户B的所有HTTP请求都必须路由到服务器2;来自用户C的所有请求都必须发送到服务器3。


问题是,来自同一客户端的每个请求都必须路由到同一服务器。这可以通过大多数负载均衡器中的粘性会话来完成;然而,这增加了开销。使用这种方法添加或删除服务器要困难得多。处理服务器故障也是一项挑战。

无状态的体系结构

图13显示了无状态体系结构。

在这种无状态体系结构中,来自用户的HTTP请求可以发送到任何web服务器,这些服务器从共享数据存储中获取状态数据。状态数据存储在共享数据存储中,不在web服务器中。无状态系统更简单、更健壮、可扩展。

图14显示了使用无状态web层的更新设计。

在图14中,我们将会话数据移出web层,并将它们存储在持久数据存储中。共享数据存储可以是关系数据库、Memcached/Redis、NoSQL等。选择NoSQL数据存储是因为它易于扩展。自动缩放意味着根据流量负载自动添加或删除web服务器。从web服务器中删除状态数据后,可以根据流量负载添加或删除服务器,从而轻松实现web层的自动伸缩。


您的网站发展迅速,吸引了大量国际用户。为了提高可用性并在更广泛的地理区域内提供更好的用户体验,支持多个数据中心至关重要。

数据中心 Data centers

图15显示了两个数据中心的设置示例。在正常操作中,用户通过geoDNS路由(也称为地理路由)到达最近的数据中心,美国东部的分流流量为x%,美国西部的分流流量为(100–x)%。geoDNS是一种DNS服务,允许根据用户的位置将域名解析为IP地址。

如果发生任何重大数据中心故障,我们会将所有流量导向健康的数据中心。在图16中,数据中心2(美国西部)离线,100%的流量被路由到数据中心1(美国东部)。

要实现多数据中心设置,必须解决几个技术挑战:

  • 流量重定向:需要有效的工具将流量定向到正确的数据中心。GeoDNS可用于根据用户的位置将流量导向最近的数据中心。
  • 数据同步:来自不同地区的用户可以使用不同的本地数据库或缓存。在故障切换的情况下,流量可能会路由到数据不可用的数据中心。一种常见的策略是跨多个数据中心复制数据。之前的一项研究显示了Netflix如何实现异步多数据中心复制。
  • 测试和部署:通过多数据中心设置,在不同位置测试您的网站/应用程序非常重要。自动化部署工具对于保持所有数据中心的服务一致性至关重要。

为了进一步扩展我们的系统,我们需要分离系统的不同组件,以便它们可以独立扩展。消息队列是许多现实世界的分布式系统用来解决这个问题的关键策略。

消息队列 Message queue

消息队列是存储在内存中的持久组件,支持异步通信。它充当缓冲区并分发异步请求。消息队列的基本架构很简单。称为生产者/发布者的输入服务创建消息,并将其发布到消息队列。其他服务或服务器(称为消费者/订阅者)连接到队列,并执行消息定义的操作。该模型如图17所示。

解耦使消息队列成为构建可伸缩且可靠的应用程序的首选架构。使用消息队列,生产者可以在消费者无法处理消息时将消息发送到队列。即使生产者不可用,消费者也可以从队列中读取消息。


考虑以下用例:您的应用程序支持照片定制,包括裁剪、锐化、模糊等。这些定制任务需要时间来完成。在图18中,web服务器将照片处理作业发布到消息队列。照片处理工人从消息队列中挑选作业并异步执行照片定制任务。生产者和消费者可以独立伸缩。当队列变大时,会增加更多的工作人员来减少处理时间。但是,如果队列大部分时间都是空的,则可以减少工作人员的数量。

日志,指标,自动化 Logging, metrics, automation

当处理运行在几台服务器上的小型网站时,日志记录、度量和自动化支持是很好的实践,但不是必需的。然而,现在你的网站已经发展到为大型企业服务,投资这些工具是必不可少的。

  • 日志记录:监控错误日志很重要,因为它有助于识别系统中的错误和问题。您可以在每个服务器级别监控错误日志,或者使用工具将它们聚合到一个集中的服务中,以便于搜索和查看。

指标:收集不同类型的指标有助于我们获得业务洞察力并了解系统的健康状态。以下一些指标很有用:

  • 主机级指标:CPU、内存、磁盘I/O等。
  • 聚合级别指标:例如,整个数据库层、缓存层等的性能。
  • 关键业务指标:日活跃用户、留存率、收入等。

自动化:当系统变得庞大和复杂时,我们需要构建或利用自动化工具来提高生产率。持续集成是一个很好的实践,其中每个代码签入都通过自动化进行验证,允许团队尽早发现问题。此外,自动化您的构建、测试、部署过程等。可以显著提高开发人员的工作效率。

添加消息队列和不同的工具

图19显示了更新后的设计。由于空间限制,图中只显示了一个数据中心。

1、该设计包括一个消息队列,有助于使系统更加松散地耦合和具有故障弹性。

2、包括日志记录、监控、度量和自动化工具。

随着数据每天的增长,您的数据库越来越超载。是时候扩展数据层了。

数据库扩展 Database scaling

数据库扩展有两种主要方法:垂直扩展和水平扩展。

垂直扩展 Vertical scaling

垂直扩展也称为纵向扩展,是通过增加更多能力(CPU、RAM、磁盘等)进行的扩展。)到现有机器上。有一些强大的数据库服务器。根据亚马逊关系数据库服务(RDS),您可以获得24tb RAM的数据库服务器。这种功能强大的数据库服务器可以存储和处理大量数据。例如,2013年stackoverflow.com的月独立访客超过1000万,但它只有一个主数据库。然而,垂直扩展有一些严重的缺点:

  • 您可以添加更多的CPU、RAM等。到您的数据库服务器,但有硬件限制。如果您有大量用户,单个服务器是不够的。
  • 单点故障风险更大。
  • 垂直扩展的总体成本很高。功能强大的服务器要贵得多。

水平扩展 Horizontal scaling

水平扩展,也称为分片,是添加更多服务器的做法。图20比较了垂直缩放和水平缩放。

Sharding将大型数据库分为更小、更易于管理的部分,称为Shard。每个碎片共享相同的模式,尽管每个碎片上的实际数据对该碎片是唯一的。

图21显示了一个分片数据库的示例。基于用户ID将用户数据分配给数据库服务器。任何时候访问数据,都会使用哈希函数来查找相应的碎片。在我们的示例中,user_id%4被用作哈希函数。如果结果等于0,则碎片0用于存储和获取数据。如果结果等于1,则使用碎片1。同样的逻辑也适用于其他碎片。

图22显示了分片数据库中的用户表。

实现分片策略时要考虑的最重要因素是分片密钥的选择。分片键(也称为分区键)由决定数据分布方式的一列或多列组成。如图22所示,“user_id”是分片键。分片键允许您通过将数据库查询路由到正确的数据库来有效地检索和修改数据。选择分片键时,最重要的标准之一是选择可以均匀分布数据的键。 分片是扩展数据库的一项伟大技术,但它远不是一个完美的解决方案。它给系统带来了复杂性和新的挑战:

Sharding是扩展数据库的一种很好的技术,但它远不是一个完美的解决方案。它给系统带来了复杂性和新的挑战:

  • 重新共享数据:当1)由于快速增长,单个碎片无法再容纳更多数据时,需要重新共享数据。2)由于数据分布不均匀,某些碎片可能比其他碎片更快耗尽。当分片耗尽时,需要更新分片功能并四处移动数据。一致散列法是解决这个问题的常用技术。
  • 名人问题:这也称为热点关键问题。对特定碎片的过度访问可能会导致服务器过载。想象一下凯蒂·佩里、贾斯汀比伯和Lady Gaga的数据都出现在同一个碎片上。对于社交应用程序,该碎片将被读取操作淹没。为了解决这个问题,我们可能需要为每个名人分配一个碎片。每个碎片甚至可能需要进一步分区。
  • 接和反规范化:一旦数据库在多个服务器上被分片,就很难在数据库分片之间执行连接操作。一种常见的解决方法是对数据库进行反规范化,以便可以在单个表中执行查询。

在图23中,我们对数据库进行了分片,以支持快速增长的数据流量。同时,一些非关系功能被移到NoSQL数据存储中,以减少数据库负载。

数百万用户甚至更多 Millions of users and beyond

扩展系统是一个迭代过程。重复我们在本章中所学的内容可以让我们走得更远。要超越数百万用户,需要更多的微调和新策略。例如,您可能需要优化您的系统并将系统解耦到更小的服务。本章中学习的所有技术应该为应对新的挑战提供良好的基础。在本章的最后,我们总结了我们如何扩展系统以支持数百万用户:

  • 保持web层无状态
  • 在每一层建立冗余
  • 尽可能多地缓存数据
  • 支持多个数据中心
  • 在CDN中托管静态资产
  • 通过分片扩展您的数据层
  • 将各层划分为单独的服务
  • 监控您的系统并使用自动化工具

祝贺你走到这一步!现在拍拍自己的背。干得好

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言