设计一个可以支持数十亿人的系统是非常困难的。对于软件架构师来说,这一直是一个很大的挑战,但是,从现在开始,阅读我的文章后,你会发现它变得容易多了。以下是我在本文中涉及的一些主题:从最简单的开始:一切合而为一。可扩展性的艺术:向上扩展,向外扩展。扩展关系数据库:主从复制、主从复制、联合、分片、非规范化和SQL调优。使用哪个数据库:NoSQL还是SQL?高级概念:缓存、CDN、geoDNS等。在本文中,我不会讨论一般的HPC术语,例如容错、可靠性、高可用性等。1.从头开始??在下图中,我将首先与一些用户一起设计一个基本的应用程序。最简单的方法是将整个应用程序部署在一台服务器上。我们大多数人可能都是这样开始的。网站(包括API)在Apache(或Tomcat)等网络服务器上运行。Oracle(或MySQL)等数据库。我们在同一台物理机器上同时拥有Web服务器和数据库服务器。但是,当前的架构存在以下缺陷:如果数据库出现故障,系统就会出现故障。一旦网络服务器出现故障,将导致整个系统瘫痪。在这种情况下,我们没有故障转移,也没有冗余。如果一台服务器发生故障,则所有服务器都将失败。使用DNS服务器解析主机名和IP地址在上图中,用户(或客户端)连接到DNS系统以获取我们系统所在服务器的Internet协议(IP)地址。获得IP地址后,请求将直接发送到我们的系统。每次访问网站时,您的计算机都会执行DNS查询。通常,域名系统(DNS)服务器用作托管公司提供的付费服务,而不是在您自己的服务器上运行。2.可扩展性的艺术我们的系统可能需要扩展的原因有很多,比如数据量的增加,工作量的增加(比如交易的数量),用户的增加。可扩展性通常是指在不影响用户体验的情况下,添加更多的资源来处理更多的用户、客户端、数据、事务或请求。我们必须决定如何扩展系统。在这种情况下,有两种类型的扩展:向上扩展和向外扩展。ScaleUpvsScaleOutScaleup:向现有服务器添加更多内存和CPU这也称为“垂直扩展”,指的是最大化系统利用率以提高系统处理不断增加的负载资源的能力——例如,增加服务器通过添加内存和CPU来增加容量。如果我们运行的服务器有8G内存,只要更换或增加硬件,就可以很容易地增加到32G甚至128G。纵向扩展的方法有很多,如下所示:通过在RAID阵列中添加更多硬盘驱动器来增加I/O容量。通过改用固态驱动器(SSD)来缩短I/O访问时间。切换到具有更多处理器的服务器。通过升级网络接口或安装额外的网络接口来提高网络吞吐量。通过增加内存减少I/O操作。对于能够负担得起硬件升级但有一些严重限制的小型系统,向上扩展是一个很好的选择,如下所示:“不可能向单个服务器添加无限容量”。这主要取决于操作系统和服务器的内存总线宽度。升级系统内存时,必须关闭服务器,所以如果系统只有一台服务器,宕机是不可避免的。功能强大的机器往往比流行的硬件贵得多。向上扩展不仅适用于硬件方面,也适用于软件方面,例如,优化查询和应用程序代码。相反,缩减是指从现有服务器中移除现有资源,例如CPU、内存和磁盘。您需要多台服务器吗?当用户数量不断增加时,一台服务器将无法满足需求。我们需要考虑将单个服务器拆分为多个服务器。当用户数量不断增加时,一台服务器将无法满足需求。采用这种体系结构具有以下优点:Web服务器可以与数据库服务器进行不同的调整。Web服务器需要更好的CPU,而数据库服务器需要更多内存。为Web层和数据层提供单独的服务器允许它们相互独立地扩展。水平扩展:增加任意数量的硬件和软件实体这也称为“水平扩展”,是指向资源池中添加更多的实体(如机器、服务等)。向外扩展比向上扩展更难,因为我们在构建系统之前必须考虑到这一点。首先,我们需要更多的服务器来满足我们最基本的需求,因此横向扩展最初往往会花费更多,但最终,我们将获得更多收益。我们需要权衡利弊。服务器数量的增长意味着需要维护更多的资源。同时,必须修改系统代码以允许在多个服务器之间并行和分配工作。相反,缩减是指移除现有服务器的过程。3.使用负载均衡器来平衡所有节点之间的流量负载均衡器是一种专门的硬件或软件组件,有助于将流量分配到服务器集群,从而提高系统的响应能力和可用性,包括但不限于应用程序、网站或数据库。使用负载平衡器来平衡所有节点之间的流量。负载均衡器一般在客户端和服务器之间,接受传入的网络和应用流量,并使用各种算法将流量分发到多个后端。端服务器。因此,它也可以用在各种场合,比如Web服务器和数据库服务器之间,客户端和Web服务器之间。HAProxy和Nginx是目前比较流行的开源负载均衡软件。负载均衡技术是一种容错保护方法,可以提高系统的可用性,具体如下:如果服务器1掉线,所有流量都会路由到服务器2和服务器3,网站不会掉线。您还需要向服务器池中添加一个新的健康服务器来平衡负载。当流量快速增长时,您只需向Web服务器池添加更多服务器,负载均衡器就会为您路由流量。负载均衡器通过不同的策略和任务分配算法来优化分配负载,如下所示:Roundrobin:在这种情况下,每个服务器按顺序接收请求,类似于先进先出(FIFO)。最少连接:连接最少的服务器将被定向到请求。最快响应时间:具有最快响应时间(最近或经常)的服务器将被定向到请求。权重:较强的服务器比较弱的服务器会收到更多的请求。IP哈希:在这种情况下,计算客户端IP地址的哈希值以将请求重定向到服务器。在多个服务器之间平衡请求的最直接方法是使用硬件设备。从共享IP添加和删除真实服务器将立即发生。可以根据需要进行负载均衡。软件负载平衡是硬件负载平衡器的廉价替代方案。它运行在第4层(网络层)和第7层(应用层)。第4层:负载均衡器使用TCP在网络层提供的信息。在这一层,它一般不看请求的内容,而是选择一个服务器。第7层:可以根据来自查询字符串、cookie或我们选择的任何标头的信息以及包括源地址和目标地址在内的一般层信息来平衡请求。4.扩展关系型数据库对于一个简单的系统,我们可以通过RDBMS来存储数据项,比如Oracle或者MySQL。但是,关系数据库系统也存在一些问题,尤其是当我们需要扩展时。扩展关系数据库的技术有很多:主从复制、主从复制、联邦、分片、非规范化和SQL调优。复制一般指的是一种技术,可以让我们在不同的机器上存储相同数据的多个副本。联合(或功能分区)按功能划分数据库。Sharding是一种与分区相关的数据库架构模式,将不同部分的数据放在不同的服务器上,不同的用户会访问数据集的不同部分。非规范化试图以牺牲一些写入性能为代价来提高读取性能,将数据写入多个表以避免昂贵的连接。SQL调优。主从复制主从复制技术可以将一台数据库服务器(主服务器)的数据复制到一台或多台其他数据库服务器(从服务器),如下图所示:客户端连接到主服务器,并更新数据。然后在从服务器上传输数据,直到所有数据在服务器上一致。在实践中,仍然存在一些瓶颈。如果主服务器由于某种原因宕机,数据仍然可以从从服务器获得,但是新的写入将不再可能。我们还需要一种新算法来将奴隶提升为主人。以下是实现只有一台服务器可以处理更新请求的一些解决方案。同步方案:只有所有服务器都接受了修改数据的事务(分布式事务)才会提交,所以发生故障转移时,数据不会丢失。异步方案:commit→delay→propagatetocluster中的其他服务器,所以发生failover时会丢失部分数据更新。请记住,如果同步解决方案太慢,请更改为异步解决方案。Master-MasterReplication每个数据库服务器都可以充当主服务器,而其他服务器充当主服务器。在某个时间点,所有这些服务器都会同步,以确保它们的数据正确且最新。所有节点读写所有数据以下是主从复制的一些优点:当一个主服务器发生故障时,其他数据库服务器可以正常运行并接管。当数据库服务器重新联机时,它将使用复制来赶上进度。主服务器可以位于多个物理站点或分布在网络中。受限于主服务器处理更新的能力。联合联合(或功能分区)按功能划分数据库。例如,您可以拥有三个数据库:论坛、用户和产品,而不是一个单一的单体数据库,这样可以减少每个数据库的读写流量,从而减少复制滞后。FederatedFunctionallyPartitionedDatabases数据库越小,它可以容纳在内存中的数据就越多,这反过来又会由于缓存命中率的提高而导致缓存命中率增加。由于不需要单个中央主机来序列化写入,您可以进行并行写入,从而提高吞吐量。分片分片,也称为数据分区,是一种将大型数据库划分为许多较小部分的技术,以便每个数据库只能管理数据的一个子集。理想情况下,我们有不同的用户都在与不同的数据库节点通信。它有助于提高系统的可管理性、性能、可用??性和负载平衡。每个用户只需要与一台服务器对话,因此可以从该服务器获得快速响应。负载在服务器之间得到了很好的平衡——例如,如果我们有五台服务器,那么每台服务器只需要处理20%的负载。实际上,有许多不同的技术可以将数据库分解成更小的部分。水平分区是一种将不同行放入不同表中的技术。例如,如果我们将用户资料存储在一张表中,我们可能会决定将ID小于1000的用户存储在一张表中,将ID大于1001且小于2000的用户存储在另一张表中。我们将不同的行放入具有垂直分区的不同表中,我们对数据进行分区并将与特定功能相关的表存储在它们自己的服务器上。例如,如果我们正在构建一个类似于Instagram的系统——它需要存储有关用户的数据、他们上传的照片以及他们关注的人——我们可以决定将用户的个人资料信息放在数据库服务器上,朋友列表在另一台服务器,照片在第三台上。我们对数据进行分区,存储与特定特征相关的表,并将它们存储在各自的服务器上。使用基于目录的分区解决此问题的松散耦合方法是创建一个查询服务,该查询服务了解您当前的分区方案并维护每个实体到存储它的数据库分片的映射。我们可以在数据存储时使用这种方法可能需要扩展到单个存储节点的可用资源之外,或者通过减少数据存储中的争用来提高性能。但请记住,分片有一些常见问题:数据库连接变得更加昂贵,在某些情况下不可行。碎片破坏了数据库的参照完整性。数据库架构更改可能会变得非常昂贵。数据分布不均,分片负载很大。反规范化反规范化的目的是提高读性能,但是是以牺牲一定的写性能为代价的。为避免昂贵的连接,可以将数据的冗余副本写入多个表。一旦数据通过联合和分片等技术变得分散,管理跨数据中心的连接会进一步增加复杂性。非规范化避免了对这种复杂连接的需要。在大多数系统上,读取操作的数量超过写入操作的比例约为100:1,甚至1000:1。导致对复杂数据库连接的读取可能非常昂贵,并且会占用大量磁盘时间。一些RDBMS,如PostgreSQL和Oracle,支持物化视图,它可以处理存储冗余数据并保持冗余副本的一致性。Facebook的RyanMack在他的优秀文章《建立时间表:利用非规范化的力量扩大规模来保存你的生活故事》(BuildingTimeline:Scalinguptoholdyourlifestory)中分享了很多Timeline本身的实现故事。5.使用哪个数据库?在数据库世界中,主要有两种解决方案。SQL和NoSQL。它们的不同之处在于构建方式、存储的信息类型以及存储方式。SQL关系数据库以行和列的形式存储数据。每行包含一个实体的所有信息,每列包含所有单独的数据点。目前最流行的关系数据库是MySQL、Oracle、MSSQLServer、SQLite、Postgres和MariaDB。NoSQL也称为非关系数据库。这些数据库一般分为五类:Key-Value、Graph、Column、Document和Blob存储。键值存储数据存储在键值对数组中。键(key)是连接到值(value)的属性名。著名的键值存储有Redis、Voldemort和Dynamo。文档数据库在这些数据库中,数据存储在按集合分组的文档中(而不是表中的行和列)。每个文档可能具有截然不同的结构。文档数据库包括CouchDB和MongoDB。宽列式数据库在列式数据库中,我们没有“表”,而是列族,它们是行的容器。与关系型数据库不同,我们不必事先知道所有的列,也不需要要求每一行的列数相同。列式数据库最适合分析大型数据集,著名的有Cassandra和HBase。图形数据库这些数据库用于存储其关系最好由图形表示的数据。数据保存在具有节点(实体)、属性(关于实体的信息)和线(实体之间的连接)的图形结构中。图数据库的示例包括Neo4J和InfiniteGraph。Blob数据库Blob更像是文件的键/值存储,可通过AmazonS3、WindowsAzureBlobStorage、GoogleCloudStorage、RackspaceCloudFiles或OpenStackSwift等API访问。如何选择要使用的数据库?谈到数据库技术,没有万能的解决方案。这就是为什么许多企业同时依赖SQL和NoSQL数据库来满足不同需求的原因。看看下面我的思维导图!使用哪个数据库?6.扩展web层我们已经扩展了数据层,现在我们还需要扩展web层。为此,我们需要将用户会话的数据(状态)移出Web层,并将其存储在关系数据库或NoSQL等数据库中。这也称为无状态架构。无状态系统很简单。不要使用状态架构;由于执行状态会限制可扩展性。降低可用性,增加成本,所以我们需要尽可能选择无状态架构。在上述场景中,由于可以选择任何服务器进行最佳请求处理,因此负载均衡器可以达到最高效率。7.高级概念缓存负载均衡可以帮助你横向扩展越来越多的服务器,但是缓存可以让你更好地利用现有资源,从而更快地为下一个请求提供数据。如果数据不在缓存中,则从数据库中取出,然后保存到缓存中,再从缓存中读取。我们可以在服务器上加一个缓存,避免直接从服务器读取网页或数据,从而减少服务器的响应时间和负载。这使我们的应用程序更具可扩展性。缓存可用于许多层,例如数据库层、Web服务器层和网络层。内容分发网络(CDN)CDN服务器保存内容(如图像、网页等)的缓存副本,并从最近的位置提供服务。使用CDN可以缩短用户的页面加载时间,因为数据是在离它最近的地方检索的。这也有助于提高内容的可用性,因为它存储在多个位置。使用CDN可以缩短用户的页面加载时间,因为数据是在离它最近的地方检索的。CDN服务器向我们的Web服务器发出请求以验证缓存的内容并在需要时更新它们。缓存的内容通常是静态的,例如HTML页面、图像、JavaScript文件、CSS文件等。走向全球随着您的应用程序在全球范围内推出,您将在全球范围内构建和运营数据中心,以确保您的产品24小时不间断运行一天,每周7天。传入的请求将被路由到基于GeoDNS的“最佳”数据中心。当您的应用程序走向全球时...GeoDNS是一种DNS服务,可根据用户的位置将域名解析为IP地址。来自亚洲的客户可以获得与来自欧洲的客户不同的IP地址。把它们放在一起通过迭代应用所有这些技术,我们可以轻松地将系统扩展到超过1亿用户,例如无状态架构、应用程序负载均衡器、尽可能使用缓存数据、支持多个数据中心、在Host静态资产在CDN上,通过分片等方式扩展数据层。缩放是一个迭代过程
