萍乡做网站的公司有哪些,html页面转WordPress文章,网页设计作品田田田田田田田田田田田田田田,找合伙人做红木家具网站在构建需要高吞吐量和最小响应时间的系统的API时#xff0c;缓存几乎是不可避免的。每个在分布式系统上工作的开发人员都曾在某个时候使用过某种缓存机制。在本文中#xff0c;我们将探讨如何使用CDN构建读取缓存设计#xff0c;不仅可以优化您的API#xff0c;还可以降低基… 在构建需要高吞吐量和最小响应时间的系统的API时缓存几乎是不可避免的。每个在分布式系统上工作的开发人员都曾在某个时候使用过某种缓存机制。在本文中我们将探讨如何使用CDN构建读取缓存设计不仅可以优化您的API还可以降低基础架构成本。 了解一些关于缓存和CDN的知识将有助于理解本文。如果您对此一无所知建议您先了解一些相关知识然后再回到这里。 背景 作为后端开发人员我们始终在努力构建高度优化的API以为用户提供良好的体验。故事从这里开始我们如何面对一个特定的问题然后如何解决它。我希望您在阅读本文后能够从中学到一些关于大规模系统设计的东西。 问题 我们需要开发一些API这些API具有以下特征 1.数据不会经常更改。2.对所有用户来说响应是相同的没有意外的查询参数只是简单的GET API。3.响应数据量最多为约600 KB。4.我们预计API的吞吐量非常高最终约为每秒5-6万次查询。 当您第一次看到这个问题时你的第一反应是什么对我来说首先想到的是只需在节点上添加内存缓存例如Google Guava使用Kafka发送失效消息因为我喜欢Kafka它很可靠设置服务实例的自动缩放因为流量在一天中不均匀。类似于下面的示意图 1*F60S9SCN5JVmgutDCOwPKg.jpeg 嘭问题解决了很容易对吧嗯事实并非如此像任何其他设计一样这个设计也带来了一些缺陷。例如对于一个简单的用例来说这个设计略微复杂基础架构成本将会增加因为现在我们必须生成一个Kafka Zookeeper集群而且为了处理每秒5-6万次请求我们需要水平扩展服务实例对于我们来说是Kubernetes Pod这意味着需要增加更多的物理节点或虚拟机。 因此我们寻找了一种更简单和经济有效的方法这就是我们最终开发了一种具有“使用CDN构建读取缓存”的解决方案。不久之后我将讨论架构的细节以及权衡。 但在进一步探讨之前让我们先了解设计的构建块。 读取缓存 标准的缓存更新策略有 1.旁路缓存Cache-Aside2.读取通过缓存Read-Through3.写入通过缓存Write-Through4.写入后缓存Write-Behind5.提前刷新Refresh-Ahead 我将不详细讨论其他策略而只关注读取缓存因为本文只涉及此内容。让我们深入研究并了解它的工作原理。 1*CZ3W153osigEQh1u09NFNQ.png 上图很容易理解但简要总结一下 1.应用程序永远不直接与数据库交互而始终通过缓存进行。2.在缓存未命中时缓存将从数据库中读取数据并丰富缓存存储。3.在缓存命中时数据将从缓存中提供。 您可以看到数据库很少被频繁访问响应速度很快因为缓存主要是内存中的如Redis或Memcached。已经解决了很多问题。 CDN 互联网上关于CDN的定义是“内容传递网络CDN是一种全球分布的代理服务器网络用于在离用户更近的位置提供内容并用于提供静态文件如图像、视频、HTML、CSS文件”。但我们将违反潮流使用CDN提供动态内容JSON响应而不是JSON文件。 此外从概念上说通常有两种CDN 1.推送CDNPush CDN您负责将数据上传到CDN服务器。2.拉取CDNPull CDNCDN将从您的服务器源服务器拉取数据。 我们将使用拉取CDN因为使用推送方法我必须处理重试、幂等性和其他内容这对我来说是一个额外的麻烦而且对于这个用例并没有真 正添加任何价值。 将CDN作为读取缓存 这个想法很简单我们将CDN作为用户和实际后端服务之间的缓存层。如下图所示 1*fn-zmPouY7r3XoWS5c-mzQ.jpeg 正如您所看到的CDN位于客户端和我们的后端服务之间并成为缓存。数据流顺序如下 1*4oGxf26V7E7MYAGKl4MtnA.png 让我们深入探讨一下因为这是设计的精髓。 用于缩写的缩写 •T1 - 时间实例1 毫秒数•T2 - 时间实例1 1分钟某些毫秒数•TTL - 存活时间•源服务器 - 您实际的后端服务 1.T1客户端请求获取user1。2.T1请求着陆在CDN上。3.T1CDN发现在其缓存存储中没有user1相关的键。4.T1CDN到上游即实际的后端服务以获取user1。5.T1后端服务返回user1作为标准的JSON响应。6.T1CDN接收到JSON现在它需要存储它。7.所以现在需要决定这个数据的TTL它是如何做到的8.通常有两种设置TTL的方式要么源服务器指定数据应该被缓存多长时间要么在CDN配置中设置了一个恒定值它使用该时间来设置TTL。9.最好让源服务器控制TTL这样我们有能力根据需要控制TTL或具有条件的TTL。10.那么问题就产生了源服务器如何指定TTL。缓存控制头Cache-Control headers来拯救。来自源服务器的响应可以包含像 cache-control: public, max-age: 180 这样的缓存控制头。这将转化为该数据可以被公开缓存有效期为180秒。11.T1现在CDN看到这一点并使用180秒的TTL缓存了数据。12.T1CDN向调用者响应user1 JSON。13.T2另一个客户端请求user1。14.T2请求着陆在CDN上。15.T2CDN看到它的缓存中有user1键因此不会到源服务器而是返回缓存的JSON响应。16.T3CDN在180秒后缓存失效。17.T4某个客户端请求user1但由于缓存为空流程再次从第3步开始。这种情况一直重复。 不一定要将TTL设置为180秒。选择TTL是根据您能够提供过期数据多长时间以及是否接受它而选择的。如果这引发了一个问题为什么不能在数据更改时使缓存失效那么请稍等我马上在缺点部分回答。 实施 1*vrlRYFpBKKy5IqDSbrUidA.jpeg 请求合并 但还有一个问题CDN承担了所有负载我们不必进行扩展。但我们的吞吐量达到了每秒60,000次查询这意味着在缓存未命中的情况下会有60,000个请求同时命中我们的源服务假设需要1秒来填充CDN缓存这可能会使服务不堪重负。 这就是请求合并的工作方式 1*ze0WtYQVhFRtClZq0GEoVQ.jpeg 顾名思义它基本上将具有相同查询参数的多个请求合并在一起并将很少的请求发送到源服务器。 我们设计的美妙之处在于我们不必自己执行请求合并CDN将帮助我们执行。正如我已经提到的我们使用的是Google Cloud CDN它有请求合并的概念这只是请求合并的另一种名称。因此当在同一时间进行大量的缓存填充请求时CDN会识别出这一点每个CDN节点只发送一个请求到源服务器然后从该响应中响应所有这些请求。这就是如何保护我们的源服务器免受高流量的影响。 好的我们现在接近结束了任何设计在没有经过利弊分析之前都是不完整的。因此让我们稍微分析一下这个设计看看它如何有所帮助以及它的不足之处。 设计的优点 1.简单性 这个设计非常简单易于实现和维护。2.响应时间 您已经知道CDN服务器的地理位置优化了数据传输因此我们的响应时间也变得非常快。例如忽略TCP连接建立时间60毫秒听起来如何3.减少负载 由于实际的后端服务器现在只收到约每180秒1个请求负载非常低。 设计的缺点 1.缓存失效 缓存失效是计算机科学中最难正确执行的事情之一而且由于CDN成为缓存它变得更加困难。在CDN上的任意即兴的缓存失效是一个昂贵的过程通常不会实时发生。如果数据发生更改由于我们无法使CDN上的缓存失效您的客户端可能会在一段时间内获得旧数据。但这又取决于您设置的TTL如果TTL为几小时那么您也可以在CDN上调用缓存失效。但如果TTL以秒/分钟为单位这可能会有问题。此外请记住并非所有CDN提供商都提供API以使CDN缓存失效。2.控制较少 由于请求现在不会着陆在我们的服务器上因此会有这样一种感觉即作为开发人员您对系统没有足够的控制。可观察性可能会受到轻微影响您可以在CDN上设置日志记录和监控但这通常会带来一定的成本。 最后 在分布式世界中的任何设计都具有一定程度的主观性并且总会有一些权衡。作为开发人员/架构师我们的职责是权衡各种权衡并选择适合我们的设计。说到这里没有哪种设计足够具体以继续下去因此鉴于约束条件我们选择了一种设计根据它的运作方式我们可能会进一步演化它。