简单i+o口扩展实验_从启动到网络扩展:扩展的简要介绍

简单i+o口扩展实验

这篇文章是对扩展Web服务的概念及其经历的不同阶段的简要介绍。 随后的文章将详细介绍此处介绍的许多概念。

起始时间

有一天,您想到一种创建网站以帮助在线销售产品的想法。 您知道您在学校学习过的几种编程语言,还具有数据库的基本知识,并且可以快速学习一些技巧以组成一个网页。 您花了几个小时来考虑用例,设计数据库表,实现细节,创建与应用程序交互的前端UI,进行基本测试并托管应用程序以供公共使用。

您与朋友共享详细信息,其中许多人都喜欢并开始使用它。 您开始看到traffic流。

好奇心如何运作和分析

您知道数据库的详细信息,因此您只需进行很少的查询就可以找到有多少人使用了人们感兴趣的东西。但是,每次都很难查询它。 因此,您开始整理一个分析页面,从中可以轻松获取这些详细信息。

用户群的增长和一次性错误

该应用程序变得流行。 越来越多的流量涌入。您的许多朋友抱怨说他们随机地看到很少的错误。您意识到自己并没有增加太多的日志记录,也没有简单的方法来查找他们面临的问题。

记录和调试

您制定了基本的日志记录策略。 您将大多数日志写入文件,在某些情况下写入数据库本身,以便以后收集信息。

监控和警报

您已记录足够的日志,正在等待下一组失败。 该错误不会出现几个小时。 您可以定期查看日志,但是它拒绝返回日志。 因此,现在您编写了另一个脚本,该脚本将继续监视日志并在发生任何问题时发送电子邮件。 几个小时后,您会收到第一个警报。 有足够的细节来解决这种情况,并在接下来的几个小时内推出所需的代码。 您将要告诉您的朋友您已解决此问题,但是您感到惊喜。 朋友本人正在打给你。 似乎他自己想通了,或者这就是所谓的心灵感应。 兴奋的是您接听电话,但似乎还有更多坏消息。这位朋友告诉您,以前只有很少的几件事随机出现故障,但现在却无济于事,并且服务器似乎已关闭。

可用性问题和高可用性计划

似乎在您尝试推出代码时,服务器宕机了。 这听起来很愚蠢,但您只是做到了。 您想快速摆脱困境。 在添加任何新功能之前,您决定要有一个基本的冗余。

负载均衡和部署策略

您的策略非常简单,您希望将服务器/应用托管在多个设备上。 您听说过Nginx。 您可以快速设置nginx反向代理和代理后面的几个框。 您还决定,下次升级代码时,将ECV移出包装箱,然后将其升级,然后放回原处,对其他包装箱重复同样的操作,就可以减少一个包装箱的交通。

这样可以解决您当前的问题。 但是您不希望仅停留在当前问题上,而是想找出还有哪些需要冗余。 您不必考虑太多,您知道数据库是另一个主要障碍。

数据库复制,定期备份和后备设置

因此,您决定进行数据库的定期备份,并设置一个备用冗余数据库设置。

所有这些都需要几个简单的脚本,而您只是将这些自动化脚本添加到了相同的代码库中。

老化的代码库和重构需求

随着所有这些代码添加到同一位置,代码开始增长。 代码中没有几个单独的内容:部署脚本,监视和警报脚本,分析查询,用户界面,管理功能以及您的主要功能应用程序。 代码库已开始显示其年龄。

在为时已晚之前,您希望基于功能拆分代码库,并开始将它们放在单独的文件夹中,并根据其所属的域对其进行命名。

您的朋友很高兴。 每个人都竖起大拇指。

更多功能和进一步发展

您的应用程序继续获得越来越多的吸引力和高点击率。 客户要求小的但很多新功能。 客户至上一直是您的优势。 您要确保每个人都满意。 您一直在照顾他们所要求的所有小型和大型功能。

但可以肯定的是,您的代码已经变得越来越混乱。

损坏的功能,测试策略和环境

随着多个功能版本的发布,很难仔细考虑所有用例。 愚蠢的错误开始频繁出现,破坏了主要功能。 不满意的客户是您不想要的。 现在该关注最佳工程实践了。 当您已经在进行单元测试和一些功能测试时; 缺少端到端测试。 您决定编写覆盖整个用户体验的多个端到端测试。 您意识到,这些测试需要数据库设置,服务器设置等。 是时候投资测试环境了,您可以在其中复制整个生产设置并运行测试。 良好的测试环境和可靠的测试策略可以显示结果。 客户再次感到高兴。

快乐的客户意味着更多的机会和更多的要求。

进一步增长

人们要求越来越多的新功能。 要求发送日终报告,月度报告,电子邮件,文本等。很少有功能需要与支付处理器,会计等集成。

域隔离

有这么多不同的功能,维护代码库变得很困难。 您已经雇用了几个人来帮助您。 沟通鸿沟很大,人们正在互相踩脚。 有不同的专业领域,例如事务,UI,会计等。

您决定将应用程序分成多个较小的应用程序。 每个都集中在一个领域或领域。

这些应用程序将具有单独的代码库,并由不同的开发人员/团队拥有。 您确定所有这些应用程序都需要独立部署和运行。

服务和服务合同

对于多个应用程序,您要确保端到端功能正常运行。 因此,您得出的结论是这些服务之间具有合同,并且所有这些服务都应严格遵守合同。

异步任务,批处理和守护程序

还要求提供脱机报告和定期电子邮件。 您要编写将定期运行的批处理。 很少有批次每天运行一次,频率更高,频率更低。 您还需要将需要较长时间才能完成的任务异步完成。 您不希望客户盯着屏幕上的纺车。 因此,您开始投资于守护程序和消息传递队列。 服务将进行基本的验证,确保请求能够得到满足,并执行基本的强制步骤,然后与其立即处理非必要的内容(例如发送电子邮件,文本等),而是以特定的格式对请求进行序列化,然后将它们添加到队列中,并以状态成功进行响应,并等待完成非必需的任务。 UI将使用此响应来指示客户已成功处理了请求,并且稍后将异步处理文本,电子邮件。 守护程序将选择它们并稍后处理长时间运行的活动和非必需的东西。 它还会将操作结果推送到电子邮件/移动文本并在数据库中更新。 UI将从数据库中选择最新状态,因此客户不必等待结果

一旦完成所有这些基础架构更改,一切看起来就会很好。

到处都很少有人抱怨React迟钝,但总体看来还是不错的。

加载问题和数据库扩展

在最初的投诉很少的情况下,您便开始探索可以改进以消除此类投诉的方法。 您从基本查询优化开始,但是随着时间的流逝,响应缓慢的问题开始更加频繁地发生。

索引,分区和归档

仔细的分析表明,一些错误的查询正在执行全表扫描,您很快就会发现正确的索引会有所帮助。 渐渐地,使用量的增长非常明显,仅建立索引是无济于事的。 您意识到自从在同一个数据库中启动该应用程序以来,您仍然拥有所有数据,可以选择清除。 因此,您决定对数据进行分区。 在少数几张桌子上,您进行了每月分区,而在少数几张桌子上进行了每日分区。 您还决定制定数据保留和归档策略。

在实施过程中很少出现打h,但值得抓住机会。

随着每个分区数据量的减少,查询变得越来越快,您又获得了满意的客户。 这也意味着增长趋势将继续。

数据库拆分

随着持续增长,数据量再次开始成为瓶颈。 即使在查询优化,优化和硬件升级之后,除了拆分数据库之外,别无选择。

虽然早期的数据库优化本质上是非常孤立的,不会影响代码的其他部分,但是这次并不相同。

大多数代码都假定,所有表都在同一个数据库中,因此您不必担心事务性,数据库默认情况下可以提供所有这些功能。 如果图片中有多个数据库和架构,那将是不一样的。 因此,您需要重新访问整个代码,以了解可以一起访问,读取或写入的表的模式,然后进行相应的分组。 在任何不符合新设计架构的地方,您都必须更改代码或设计,或者提出黑客建议。 这项练习比您想象的要痛苦得多。 但这也验证了您对域分离的想法。 尽管属于一个域的大多数数据都正确地放置在相应的架构中,但很少有架构/表在各个域之间共享。

读/写服务和缓存

您已决定在多个位置进行直接数据库访问会导致问题。 通常,很少有关键的数据库/架构变得非常热,即使拆分后也有很多负载。 您已开始研究是否可以将读写分开并从两个不同的实例提供服务。 您还意识到,对于复制延迟可能给客户造成混乱/问题的方案,这样做可能会导致问题。 您将注意力转移到了内存缓存解决方案中。 所有写操作将同时发生在数据库和缓存中。 读取将首先通过高速缓存进行,如果需要的话,还会从只读数据库实例中进行读取(部分使用情况)。 如果数据在缓存中不可用,则只有它会转到只读数据库实例。 这也意味着从不同位置进行直接db访问不是一个好主意,所有数据库读写操作都应该通过服务进行,这些服务知道何时从缓存中查找与何时查看db的逻辑。

通过此更改,数据库运行状况看起来很好。 读写是分开的,缓存对减少数据库的读取查询命中有很大帮助。

您的应用程序继续吸引更多的客户和指数流量。 随着批次和面向客户的api的引入,峰值负载是平均负载的几倍。

延迟的写入,日记和最终一致性

在高峰流量期间,数据库看起来很脆弱。 如果可以通过某种方式将高峰时段分配给非高峰时段,那应该很好。 您试图弄清楚在峰值负载情况下如何延迟写入。 您提出了一个非常简单的队列和守护程序解决方案。 您总是会写一个临时数据库,然后守护程序会从该临时数据库中拾取数据并写入主数据库。 在写入临时数据库之前,您通过验证数据来确保数据是正确的,基于数据的应用程序逻辑还会更新缓存,以防万一有人立即需要数据。 您还了解到,对于临时数据库表而言,日记将是一个好主意。 万一需要任何回滚。 因此,您还确保插入临时数据库表,这与仅追加日志非常相似,在此情况下,您从不更新行,并且始终为每个操作添加新记录。 这样,它可以帮助您协调记录,并且还提供了一种方法,可以在发生回滚的情况下通过进行语义上的逆操作来进行回滚。现在,您要使用多个临时数据库表,而不是一个主要的数据库,因此消除了瓶颈。 守护程序始终以定义的速度进行选择,并以相同的速率写入主数据库。 万一出现高峰,所有负载仍仅限于临时数据库,而主数据库写入仍保持相同的速度。 您了解在高峰流量期间,对主数据库的实际写入可能会延迟一点。 为了同时进行读取,您已经写入高速缓存。 您的读取服务假定,如果缓存中包含数据,则它将是最新的数据,因此从缓存中读取,否则从数据库中读取。

这样可以解决您的高峰流量问题。 尽管您的代码需要更多的数据验证,但其中许多验证不是明确的,因此您确实必须付出很多中断并修复各种补丁才能使其正常工作。 完成后,您将释怀。 现在,可以更定期地维护主数据库,而不必担心流量下降。

但是故事还没有结束。

您的应用程序的增长势不可挡!

它正在以惊人的速度持续增长,似乎每秒向关键方案写入主表的次数远远超过建议的平均次数。 写入实例又再次热起来,您需要做一些事情。

数据库分片

每个数据库只能承受有限的负载,即使在升级硬件后,您也看不到它可以满足所需的规模。 您进行了一些研究,发现唯一的出路是让多个数据库各自承担一部分工作负载。 您喜欢这种分片的想法。 您刚刚完成分析,似乎已经发现您需要一个分片密钥,该分片密钥将决定需要将数据写入或读取的目标数据库。 您已经具有用于访问数据库的读取和写入服务,因此对您来说会更简单一些。 您已经分析了所有读写模式,并发现可以根据帐号对数据库进行分片。 您将确保所有读取的查询都将帐号作为键之一。 同样,每次写入都必须有一个帐号。 您还将要在物理分片和逻辑分片之间进行分离,以便可以从较少数量的物理数据库开始,但最终在需要时扩展到更多数据库。

有了这个,您已经达到了您的应用程序可能具有的最大规模的极限。

如果您需要进一步扩大规模,下一个选择可能是拆分公司!

参考文献:

翻译自: https://hackernoon.com/from-startup-to-web-scale-a-gentle-introduction-to-scaling-22612beedcdd

简单i+o口扩展实验

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值