奥兰多代码营

使用分布式缓存扩展 .NET 应用程序

伊克巴尔汗
总裁兼技术传播者

由于事务负载的增长,您的 .NET 应用程序可能会遇到数据库或存储瓶颈。 了解如何使用分布式缓存消除瓶颈并扩展您的 .NET 应用程序。 本次演讲涵盖:

  • .NET 应用程序中可扩展性瓶颈的快速概览
  • 分布式缓存的描述以及它如何解决性能问题
  • 您在哪里可以在应用程序中使用分布式缓存
  • 分布式缓存中的一些重要特性
  • 使用分布式缓存的动手示例

今天的话题不是 NCache,它是关于分布式缓存的。 我会参考 NCache 作为示例,但概念是整体的,因此它们适用于所有缓存。

什么是可扩展性

好的! 让我们先弄清楚一些定义。 第一个定义是可扩展性。 可扩展性不是应用程序性能。 如果您有 XNUMX 个用户并且您的应用程序执行得非常快,那么您的应用程序是不可扩展的,直到它可以与五千、五万或五十万用户具有相同的良好性能。 因此,可扩展性与峰值负载下的高性能有关。 人们有时会将性能与可扩展性混淆。 您的应用程序可能在五个用户时性能不佳,在这种情况下缓存对您没有帮助,您还有其他问题需要解决。

线性可伸缩性

线性可扩展性是,如果您的应用程序的架构方式可以添加更多服务器,并且通过添加更多服务器可以增加事务容量。 同样,我们在事务容量方面定义的可扩展性,即您的应用程序每秒可以处理多少个用户的事务。 因此,如果您的应用程序可以在您添加更多服务器时处理更多线性事务,那么您的线性可扩展性和我们的目标是成为线性扩展,以便在我们的应用程序中具有线性可扩展性。

线性可扩展性

非线性可扩展性

而且,我们绝对不希望非线性可扩展性,即您的应用程序的架构方式是,在某个点之后,如果您添加更多服务器并不重要,您的应用程序不会增加,事实上它可能会增加降低。 这意味着在某个地方存在一些尚未解决的瓶颈。

非线性可扩展性

哪些应用需要可扩展性?

那么,为什么我们需要可扩展性以及哪些应用程序需要可扩展性?

应用程序需要可扩展性

通常,这些是服务器端应用程序。 这些是 ASP.NET 现在是 ASP.NET core、网络服务、物联网后端、大数据处理。 虽然大数据处理在 .NET 方面并不常见,但它更多地是在 Java 现象中,但它应该可以,你应该也可以用 .NET 来做,但是大数据处理应用程序还需要可伸缩性和任何其他服务器应用程序。 例如,您可能是一家银行,您有数百万客户,他们致电并更改地址,或者可能发行或要求新卡,或者他们可能转移资金,您必须以批处理模式处理所有这些请求晚上,您必须在下一个工作日之前完成一些合规性要求。 因此,随着您获得越来越多的这些,甚至您的其他批处理应用程序也需要可扩展。 因此,不仅仅是这些应用程序。 任何其他只需要在压缩时间内处理大量事务的应用程序,在这些情况下的压缩时间是每秒事务数,在这种情况下,压缩时间可能在合规性要求范围内。 因此,如果您有任何这些高流量或高交易量的应用程序,那么您就来对了。

可扩展性问题

那么,可扩展性问题在哪里? 为什么我们还要进行这样的对话? 绝对不是在应用程序层中,您的应用程序层可以很好地扩展,您有一个负载均衡器,您可以添加越来越多的服务器。 一切看起来都很好。 问题确实出在您的数据库中,即您的数据存储中。 而且,我的意思是关系数据库或大型机遗留数据。 而且,您无法以与扩展应用程序层相同的方式扩展它们。 原因是因为这里的数据不是分布式的。 数据库的本质是它必须放在一起。 而且,大型机也是如此。 因此,数据库可能非常快。 它可能在服务器端的内存缓存中进行,但它没有扩展和 NoSQL databases.

虽然人们使用的原因之一 NoSQL 一个是交易的可扩展性,另一个是数据的可扩展性,比如说,你有 TB 和 TB 的数据 NoSQL 更适合那个。 而且,人们使用它的第三个原因是 JSON 文档提供了这种模式的灵活性。 但, NoSQL databases 并不总是能够帮助您,原因是因为它们要求您将数据从关系数据库移到 NoSQL database. 如果由于各种原因(包括技术和业务原因)您无法做到这一点怎么办。 一些数据必须保留在您的关系数据库和旧的大型机数据中。 虽然, NoSQL databases 很棒,我们有一个 NoSQL database 我们去年推出的我们自己称为 NosDB,正如我所提到的,但除非您可以将数据放入其中,否则它们不会解决您的问题。 因此,如果您必须使用关系数据库,则必须解决它们带来的可伸缩性问题,而这正是分布式缓存真正发挥作用的地方。

分布式缓存部署

分布式缓存本质上是内存中的分布式存储。

分布式缓存部署

从逻辑上讲,它只是在应用层和数据层之间。 从物理上讲,它可能是一堆独立的虚拟机,也可能与应用程序位于同一个盒子上,或者其中一些可能在这里,一些可能在这里,这些就是我们将要讨论的内容。 但从逻辑上讲,它位于应用层和数据库层之间。 而且,基本论点是,如果您缓存数据,您就不会经常访问数据库。 因为,你不去数据库它不会得到所有的负载,所以它不会成为瓶颈。 如果 80% 的时间可以转到缓存层,并且缓存层没有数据库的瓶颈,因为它也像数据库一样分布 NoSQL database 缓存层也在分发。 这是一个键/值。 实际上,分布式缓存的另一个词是内存中 NoSQL 键值存储,因为您放入分布式缓存中的所有内容都有一个键,并且有一个值是您的对象。 因此,通过执行这 80% 的时间,您将有 20% 的时间访问数据库。 这 20% 主要是更新。

当然有一些读取,这些更新也执行得更快,因为没有与读取事务的竞争,这不再是瓶颈。 为什么? 因为一个分布式缓存会形成一个由两台或多台服务器组成的集群。 这些不是昂贵的盒子,它们不是您的数据库服务器类型的盒子。 这些是典型的 Web 服务器配置,就像一个四核或八核的盒子,只是有很多内存。 很多意味着 16 到 32 演出是我们向客户推荐的。 我们的一些客户超过 32 个,但我们几乎从不建议超过 64 个。最好再加一个盒子,然后在这里再放更多。 因为,如果您添加更多内存,则必须升级处理能力。 为什么? 因为 .NET 应用程序有一个叫做垃圾收集的东西,而且你必须收集的内存越多,垃圾收集器或 GC 必须工作的越多,在这种情况下 CPU 就会成为瓶颈,你的应用程序就会开始出现问题。 因此,最佳点是这些 VM 或物理机柜中的 16 到 32 gig 内存,我们的大多数客户在这里使用 VM。 并且,大约8核作为硬件配置,通常是两张网卡,一张网卡用于集群,一张用于客户端与之通信。 客户端一词表示您的应用程序服务器,因此,它不是您的客户端。 您的应用程序服务器是缓存客户端。

因此,至少有两个缓存服务器,然后应用层和缓存层之间的比例为四比一或五比一。 而且,这个比例主要基于我们多年来所看到的并且我们已经在这个领域工作了十多年,如果您在这里添加更多服务器以增加更多活动,那么我们的四比一或以上五比一的比例会给你很好的容量。 当然,您出于以下三个原因之一添加更多服务器。 您要么需要更多存储空间,因为您有我们刚才谈到的内存需求,要么您需要更多事务容量,因为您有两台服务器开始,并且您一直在此处添加框,直到丢弃最大化。 在关系数据库中,如果发生这种情况,您将陷入困境。 你受够了。 在这种情况下,您所做的就是添加第三个盒子,直到第三个盒子的容量达到最大值,然后再添加第四个,依此类推。 因此,您可以在此处拥有任意数量的盒子。 我们有客户,这里平均有大约 40 到 50 个盒子,我们的一些客户在应用层有 XNUMX 到 XNUMX 个盒子,然后他们也有相应的。 因此,对于十个盒子或十个服务器应用程序层,您将在缓存层中拥有大约三台服务器。 所以,这就是你做计划的方式。

因此,到目前为止,谈话的目标是让您相信,通过拥有一个缓存层,您将不再有可伸缩性瓶颈。 因此,无论您使用哪种产品,无论您使用哪种缓存解决方案,都必须在您的应用程序中加入缓存层。 因此,您必须构建您的应用程序以在您的图片中拥有缓存,这样您就永远不会遇到瓶颈。

分布式缓存的用例

所以,既然我们确信您应该作为 .NET 开发人员使用缓存,接下来想到的问题是您应该在哪里使用它? 你应该如何使用它?

用例

而且,第一个用例是应用程序数据缓存,直到现在我一直在谈论它是您在数据库中拥有应用程序数据并将其缓存在这里,因此您不必访问数据库,同样的事情.

应用数据缓存

关于这个用例要记住的一件事是,数据现在存在于两个地方,一个是主数据库,一个是数据库,另一个是缓存,而不是另一个地方。 那么,如果您的数据存在于两个地方,会出现什么问题呢? 如果你有它的两个副本,最大的问题是,缓存是否是新的,缓存是否与数据库具有相同版本的数据,因为如果缓存不具有相同版本的数据,那么你将被强制缓存只读数据。 而且,只读数据约占总数据的 10-15%。 所以,你并没有真正受益。 您正在受益,但您并没有真正使您的应用程序可扩展地受益。

所以,事实上它是如此之多,以至于如果你问一个普通人缓存的用途是什么。 他们会说好,我只会将我的只读数据放入其中。 每个人都害怕缓存事务数据。 您的客户、您的帐户或活动数据每 30 秒、每 XNUMX 分钟、每 XNUMX 分钟或以不可预测的方式更改。 因此,出于这个原因,人们害怕缓存它,因为它有两个副本,如果缓存不知道您已经在数据库中更改了它怎么办。 因此,让我们在继续前进时牢记这一点。

ASP.NET 特定缓存

第二个用例是,如果您有一个 ASP.NET 应用程序,最常见的是 会话状态. 这也是,第一个例子是会话状态。 会话是默认的,你有两个存储选项。 一个是 InProc,另一个是 Microsoft 提供的 SQL。 在本地也有一个状态服务器,但所有三个选项都存在可伸缩性问题。 SQL Server 存在性能问题。 与我们一开始就没有缓存的原因相同。 在 SQL 中存储会话时,它们将存储为 blob。 关系是 SQL,就像所有关系数据库都不是为 blob 存储设计的,它是为结构化数据设计的。 所以,它不执行。 有很多问题。 我们的大多数客户去的时候 NCache,第一个用例是会话状态。 那是因为这会立即使他们受益。 而且,关于会话状态的真正好处是没有编程,因为微软提供了一个框架,它允许第三方缓存,如 NCache 插入,这里的所有内容都存储在缓存中。

ASP.NET 的另一个方面是,如果您没有 MVC 框架,如果您处于许多 ASP.NET 应用程序仍然存在的前 MVC 框架中,那么就会有一种称为视图状态的东西。 而且,对于那些不知道什么是视图状态的人来说,它是一个加密字符串,由您的网络服务器发送到浏览器,只是在回发时被带回。 因此,它可能是数百千字节的加密强度,然后又回来了。 而且,当您将其乘以应用程序将要处理的数百万个事务时,至少会占用大量带宽。 而且,带宽不是免费的,因为它非常昂贵。

而且,第二个当然是,但是当您必须发送如此重的负载时,您的响应时间会变慢。 因此,如果您可以在服务器端缓存视图状态发送一个小键,那么当回发发生时,键会返回并从缓存中获取视图状态并呈现到页面。 所以,这是第二个用例。 同样,不涉及任何编程,您只需插入第三方缓存,例如 NCache.

第三个用例是 ASP.NET 输出缓存. 此缓存是页面输出。 如果页面输出没有改变,微软已经有一个框架将它缓存在本地独立的 InProc 中。 最好放置第三个分布式缓存来代替它,这样在 Web 场中第一次缓存页面输出时,整个 Web 场都可以使用它,而不是每个 Web 服务器都缓存自己的副本。

因此,除了应用程序数据缓存之外,这些是 ASP.NET 应用程序的三个用例。

现在这里问题的性质在这里完全不同。 在这个中,您有两个数据副本。 在这里,缓存是主存储。 因此,您不再将会话存储在数据库中。 您不再在其他任何地方存储视图状态。 因此,缓存是主存储,它是内存中的存储。 那么,当内存存储是主存储时,会出现什么问题呢? 内存不稳定! 是的。 所以,没有坚持。 因此,良好的分布式缓存必须跨多个服务器复制数据以提供数据可靠性,这样您就不会丢失该会话。 因为,你可能是一家航空公司,你为夏威夷做了这个特别的周末促销活动,你的网站访问量是你网站的两到三倍,他们是进行各种搜索的人,他们即将点击提交按钮,他们失去了他们的会话。 您可能会因为每位客户的数千美元销售额而失去该客户。 因此,您绝对不想丢失会话。 因此,除非它进行复制,否则不要将会话放入缓存中。

运行时数据共享

第三个用例是运行时数据共享。 这是很多人很久以来都不知道的事情。 人们使用消息队列来跨多个应用程序共享事件。 但是,分布式缓存为您提供了一个非常简单且功能强大的以数据为中心的事件机制,现在将其视为服务总线或消息总线,那么这些是您的应用程序可以通过它相互通信。 所以不要使用 MSMQ 或 RabbitMQ,它们有自己的好处,缓存不会在这里取代它们。 但是,如果您的需求更多地围绕数据,或者如果您的消息传递需要更多地围绕数据并且在同一个数据中心内,分布式缓存为您提供更简单的界面,但更重要的是它更具可扩展性。 所以,如果你有一个更高的事务应用程序,那么整个讨论都是关于可伸缩性的。

因此,尽管您可以使用此常规消息队列来完成所有这些工作。 当您进入一个非常高的事务环境时,它们的分布方式与分布式缓存不同。 因此,分布式缓存将允许您完成所有这些工作。 假设 Pub/Sub 类型的数据共享,有事件通知,有一个持续查询功能 NCache 有哪些 Java 缓存也有, Redis 没有,您可以通过它以非常无缝的方式跨应用程序共享数据。 而且,这里的问题也类似于 ASP.NET 特定缓存的应用程序,因为虽然这些数据可能存在于数据库中,但不以您共享它的形式存在。

因此,您可能在尝试共享它之前已将其转换为某些形式,以便将转换后的形式保存在缓存中。 因此,您不想丢失该数据,因此缓存必须复制数据。 实际上,即使对于应用程序数据缓存,虽然从技术上讲,如果由于一台缓存服务器出现故障并且您没有复制而丢失一些数据,您也可以这样做。 从技术上讲,您可以从数据库中重新加载该数据。 除了性能受到影响之外没有问题,因为不管怎么说,如果您丢失了 16 gig 的数据,那么现在您必须经历 16 gig 的数据库命中,而您不想这样做。 因此,我们的大多数客户,即使是应用程序数据缓存,也选择复制,因为内存非常便宜。 他们甚至不想受到这种性能的影响。 当然,有了这两个,你必须拥有它,但在这一个中,它们是一种很好的拥有。

动手演示

好的,在我们继续讨论如何执行此操作之前,我想先向您展示缓存的外观。 我要使用 NCache 作为这里的例子。

快速演示天蓝色

设置环境

所以,我在天蓝色中有三个虚拟机 demo1、demo2 和 demo-client。 demo1 和 2 将是我的缓存服务器 VM,而 demo-client 是我的应用程序服务器 VM。 在您的情况下,假设您将拥有两个缓存 VM,然后是四比五、四比一或五比一的客户端 VM。

所以,我登录到演示客户端,我将使用这个工具 NCache 呼吁 NCache 经理。 所以,我从这里开始。 我要来这里说创建一个新的集群缓存。

创建集群缓存

所有缓存在 NCache 被命名了,所以我只是将它命名为 democache,我不打算详细说明它们各自的含义我会稍微讨论一下,但我会选择一个 分区副本拓扑。 的情况下 NCache,拓扑意味着数据如何存储和复制? 分区副本拓扑是这样的……如果我要回来,如果我来到这里,可以把它想象成一个即将创建的双节点缓存集群。

创建集群缓存

如果它是一个分区副本,那么每个服务器都将有一个分区。 所以,总共会有两个分区。 的情况下 NCache,整个缓存有大约一千个桶,所以大约一半会去分区一,一半会去分区二。

缓存拓扑

每个分区都备份到称为副本的不同服务器上。 复制品以防万一 NCache 是被动的,这意味着没有客户端与副本通信,只有分区与副本通信。 并且,副本仅在其主分区或分区关闭时才变为活动状态。

数据平衡

这意味着,假设这台服务器要关闭,假设我们有一个三节点集群和分区,假设服务器 1 宕机,分区 2 现在宕机。 所以,replica XNUMX会自动变成partition XNUMX,这样就不会丢失任何数据。 因此,分区副本为您提供了这种存储和复制策略。 它基本上告诉您必须复制数据。 还有一个同步和异步复制。 所以,无论如何,所以我会回到这个,但我只想告诉你这意味着什么。 因此,我将选择分区和副本之间的异步复制。 然后我会指定我的缓存服务器,所以第一个是demoXNUMX,第二个是demoXNUMX。 现在,我所说的一切,以防万一 NCache,您可以完全编写脚本,以便自动化。 我将保留所有默认值。 那是形成缓存集群的 TCP 端口。 我将指定我希望缓存在此服务器上使用多少内存,并且缓存不会使用超过此内存。 所以,我在这里指定的都是两次,因为。 有一个分区,有一个副本。

所以,这是一个分区的大小。 因此,在您的情况下,它当然会比这更多,因为如果您在缓存服务器中有 16 个演出,您应该为操作系统和其他进程留下大约 2 到 2.5 个演出并分配其余部分。 因此,假设从 16 个演出开始,您还剩下 13 个半演出,但 13 个半除以 2 将是一个分区大小,然后 NCache 将确保它使用的内存不超过此内存。 因此,当消耗了这么多内存时,缓存被认为已满,以防万一 NCache. 进而 NCache 有两个选项之一。 一,你可以告诉 NCache 将拒绝任何新添加的数据,直到某些数据自动过期,或者您可以执行所谓的驱逐。 所以, NCache 为您提供三种驱逐算法 LRU、LFU 和优先级 FIFO。 所以,你可以说在这种情况下,驱逐 5% 的缓存。

所以现在我想在上下文中讨论一下这个,假设你存储在每个 用例 这里。 如果您正在执行应用程序数据缓存,则驱逐是完全可以的。 这里没有问题。 您只是用完了一些最近最少使用的内存,然后为新数据腾出空间。 所以,它就像一个移动的窗口,对吧? 因此,随着您使用越来越多的数据,旧的数据会被删除,而新的数据会被删除。 所以,这是最常用的。 但是,如果是会话呢? 如果缓存被用于存储会话,您不希望驱逐。 你为什么不想驱逐它? 因为,会话可能仍然处于活动状态。 它可能没有经过那 20 分钟或您的超时时间。 如果是这种情况并且您仍然驱逐会话,那么您正在强制执行我们刚刚讨论的相同问题,即用户尚未注销但您正在踢。 因此,您需要做的是,进行容量规划。 的情况下 NCache,您可以非常轻松地做到这一点,可以查看平均会话消耗多少内存,然后进行容量规划。 推断将使用多少内存。 做这个其他会话存储永远不会被驱逐的容量。 应用程序数据存储或应用程序数据缓存可以被驱逐,没问题。 但是,不应驱逐会话缓存。 它应该只在用户不再使用会话时过期。

所以,我只想说完成,我有一个两节点缓存集群。 我会来这里,我会添加一个客户端节点。 就我而言,正如我所说,我只有一个客户端节点。 我想我可能没有缓存,所以我们开始了。 我需要这项服务,所以 NCache 经理可以与此对话并进行配置。 好的! 现在我已经完成了这个,我要来这里说启动缓存。 所以现在通过启动缓存, NCache 正在这两个盒子之间建立一个集群,到那个 TCP。

ncache-创建集群

模拟压力并监控缓存统计信息

因此,您实际上并没有详细了解哪些盒子有哪些数据以及是否有集群。 你只知道有一个演示缓存。 每当您连接到该缓存时,如果出现分区副本,您的应用程序将自动连接到所有服务器。 所以, NCache 负责所有细节,我会来这里说查看统计数据,这些是一些 PerfMon 计数器,以便您可以看到 NCache 会做,但一旦你开始使用它。 我还将启动这个名为 NCache 监视器。 而且,它就像一个仪表板风格的工具。 并且,如果发生 NCache,您可以选择使用压力测试工具,它允许您非常快速地模拟您的应用程序使用情况,而无需任何编程。

因此,例如,我会说压力测试工具 democache,所以它会做一个得到一个放置和类似的东西。 突然之间,现在您会看到这个工具正在与两个缓存服务器通信,并且它在每个机器上每秒执行大约 700 个请求,大约 7 到 800 个甚至高达 XNUMX 个。 假设我想增加负载。 所以,我想再推出一款压力测试工具。

压力测试工具

这就像您对应用程序所做的那样。 我的意思是,当您想测试您的应用程序时,您将使用一些压力测试工具运行您的应用程序,然后您将不断增加压力,然后您想查看整个系统是否正常工作。 所以,现在你只是在测试它的缓存组件。 我们的大多数客户在评估时会做什么 NCache,他们做这个基准测试。 因此,一旦他们在他们的环境中配置了所有内容,即使我们发布了我们的基准测试,他们也没有。 我的意思是他们在自己的环境中验证一切。 因此,随着您添加越来越多的内容,您会看到此负载刚刚翻了一番。

让我再来一个压力测试工具。 你会看到它一直在上涨。 就在那儿,看! 所以,我可以继续添加越来越多的压力测试工具,直到我可以最大化我的客户端 CPU。 所以,我的应用程序服务器已经使用了大约 50%。 所以,我绝对可以添加更多的压力测试工具。 一旦我最大限度地利用了该客户,我将再添加一个客户。 所以,我只能这样。 因此,即使是现在,例如,我们仅使用三个压力测试工具每秒就可以处理大约 5,000 个请求。 所以,有了这个,你也可以在这里监控所有这些东西。 所以,有了这个,您实际上可以看到缓存的样子。 现在,让我们从开发的角度进行更多讨论。

ASP.NET 特定缓存

所以,既然您知道缓存是什么样的,那么让我们看看如何在您的应用程序中使用该缓存。 因此,对于 ASP.NET,正如我所说,您应该做的第一件事是使用会话缓存。 为什么? 因为这是最简单的。 没有编程,没有努力可以做到。 我刚刚向您展示了配置缓存的速度有多快 NCache,假设我要来这里并进入一些示例代码应该已经打开它们,但我没有。 因此,这是一个供您使用的 ASP.NET 应用程序 NCache 使用 ASP.NET 进行会话。 你只需要去修改web.config。 所以,我有 web.config。 您要做的第一件事是在装配时添加这条装配线。 NCache,这个会话存储提供者是 NCache 已实现 ASP.NET 会话存储提供程序接口的程序集。 所以,这就是允许 NCache 插入。因此,您可以在这里复制该行,然后您就来到会话状态标签,就在这里。 的情况下 NCache,您只需复制该标签。 确保此模式是自定义的,因为这是允许第三方缓存插入的原因。超时是您想要的,然后是您唯一需要的以防万一 NCache 是确保指定了缓存名称。

所以,一旦你安装了 NCache 然后在缓存服务器上安装服务器部分,在应用程序服务器上安装客户端部分 NCache,您像我们刚才一样创建缓存,然后更新它,仅此而已。 这就是您开始使用所需的全部努力 NCache 然后每个会话都是缓存中的一个对象。 当您在该 PerfMon 计数器中执行此操作时,您将看到您正在查看多少个会话。 通常情况下,我们的客户会创建三个缓存。 所以,我们只是在这里做了一个缓存,对吧? 因此,我们的客户将制作三个缓存。 其中一个缓存用于会话。 因此,它们有一个单独的会话缓存。 缓存之一和两个缓存用于应用程序数据。 一种是他们所说的参考数据。 另一个是交易数据。 事务数据是变化非常频繁的东西。 而且,他们这样做的原因是因为我将介绍其他一些功能。 但是,在同一个 VM 上,您可以创建多个缓存。 所以,这就是你对会话状态存储所要做的一切,这很容易,不需要编程,然后你就可以开始了。

应用数据缓存

但是,如果您想做应用程序数据缓存,不幸的是,在 .NET 空间中,EF 核心现在终于提供了一种架构,您可以在其中插入第三方缓存。

应用数据缓存

NCache 也支持它。 但是,在包括 EF6 在内的 EF6 之前,该架构并不真正支持插入第三方缓存。 NHibernate 长期以来一直支持这种架构。 所以,对于 NHibernate NCache 无需任何编程即可插入。 因此,即使是具有最少功能的应用程序数据缓存,您也可以不进行任何 API 调用。 但是,在大多数情况下,您必须为应用程序数据缓存做好心理准备,您将不得不进行编程。 但这是一个非常简单的 API。 这个 API 看起来很像 ASP.NET 缓存对象。 您使用缓存名称连接缓存。

让我快速向您展示这是什么样的。 让我打开……我遇到了一些 Azure VM 问题。 我在这一切都打开了其他东西。 所以,假设我有这个非常基本的控制台应用程序。 您要做的第一件事是链接两个 NCache 组件,一个是 NCache.Runtime,另一个是 NCache.Web。 NCache.Web 是您正在调用的实际 API。 然后你链接这两个或者你再次使用这两个命名空间 NCache.Runtime,然后是 .Web.Caching。 在您的应用程序开始时,您根据名称连接到缓存,并获得一个缓存句柄,就像数据库一样。 当然,在 ASP.NET 应用程序中,您可能会在应用程序启动中的 global.ASAX 或 InIt 方法中执行此操作。 然后,您只需创建对象并执行 Cache.Add。 Cache.Add 将使用一个键,某种字符串。 这不是一个好的密钥,您的密钥需要更具体,然后这是您的对象,仅此而已。 你打了那个电话,现在在幕后。 比方说,如果您有分区副本拓扑,那么您的应用程序将发生连接。 所以,每个盒子都连接着所有的缓存服务器。 所以,你刚刚做了一个 Cache.Add 对吗? 所以,Cache.Add 会去查看类似于桶图的分布图。 每个桶都有一个键值范围,就哈希键值范围而言,哪些键可以进入这个桶。 因此,它将使用该存储桶映射来了解它应该去哪个服务器并与之交谈,因为它已连接到所有服务器,对吗?

而且,它会去,假设你在这里添加第三个项目。 它将在此处添加第 XNUMX 项,如果您启用了异步复制,应用程序将返回并完成应用程序。 缓存现在,这个分区知道它需要在这里复制它。 因此,它将在批量操作中异步地将其复制到另一个盒子,您将立即在两个地方拥有该项目。 所以,这就是 Cache.Add 在幕后所做的。

好的,我来来回回,因为我只是想给你一个概述,但缓存看起来像,如何创建它,API 是什么样的。

应用数据缓存功能

现在,让我们讨论在使用缓存进行应用程序数据缓存时必须解决的问题。

保持缓存新鲜

我们谈到了保持缓存新鲜,对吧? 那么,如何保持缓存新鲜呢? 你如何确保缓存是新鲜的?

保持缓存新鲜
使用基于时间的过期

最常见且每个人都支持的一种,包括 Redis 是到期。 绝对到期。 因此,当您向缓存添加内容时,假设您在此处指定过期时间,也就是说您要在一分钟后过期。 当你这么说的情况下 NCache, NCache 将在服务器上创建索引,我们将监控该数据并在一分钟后过期。 所以,实际上就是这样,它实际上会指定一个绝对日期时间值,该值是从现在开始的一分钟。 NCache 知道在那天的时间值它需要使该项目过期。 因此,这就是缓存自动确保删除数据的方式。 而且,这到底意味着什么? 这意味着您对缓存说,我真的不愿意将这些数据保存超过一分钟或超过五分钟,因为我认为有人会在数据库中更改它。 因此,只有将它保存在缓存中这么长时间才是安全的。 还有另一种到期称为滑动到期,听起来相同,但其目的完全不同。 滑动到期主要用于清理。 因此,如果您有会话,您可以在没有人使用此会话后使用滑动到期来清理。 因此,当有人在 20 分钟不活动后注销时,会话将被视为过期。 所以,它会被自动删除。

使用数据库依赖

但是,这与保持缓存新鲜无关。 绝对过期是使缓存保持新鲜的一种。 但是,绝对到期存在一个大问题。 而且,问题在于您正在猜测将数据保存在缓存中很长时间是安全的,而这种猜测并不总是准确的。 那么,在这种情况下你会怎么做? 然后,在这种情况下,您必须能够让缓存自行同步。 如果它注意到数据库的变化,这意味着缓存必须知道你的数据库是什么。 这意味着缓存必须在缓存项和数据库中某些数据中的某些内容之间建立关系,您必须告诉缓存,这就是 ADO.NET 中称为 SQL 缓存依赖项的地方 NCache 使用,这是SQL依赖,这也称为Oracle依赖,它实际上以一种非常简单的方式工作。 但是,这是一个非常强大的功能。 而且,我们来到这里。 我将只使用 SQL 依赖项。 因此,当您向缓存添加内容时,您执行相同的 Cache.Add,对吗? 你有一个缓存键。 现在,您指定的缓存项不是值,而是 NCache自己的数据结构,其中包含值,但它也包含这称为 SQL 缓存依赖项的东西。

此 SQL 缓存依赖项是 NCache自己的类,但它映射到 ADO.NET SQL 缓存依赖项。 注意,这里有一个连接字符串,然后有一个 SQL 语句。 因此,本例中的 SQL 语句映射到产品表中的一行。 那么,这里到底发生了什么? 我的意思是,您实际上是在此处运行此代码。 你的数据库在这里,所以你要求缓存集群现在根据你刚刚传递的连接字符串与数据库连接,基于那个连接字符串,你正在传递 SQL 服务器,你说请连接到我的 SQL 服务器数据库。 并且,如果此数据集发生任何更改,监视 SQL 服务器以通知您(您是缓存服务器)。 这意味着如果该行被更新或删除。 如果发生这种情况,SQL 服务器会向客户端发送数据库通知,在这种情况下,客户端就是缓存服务器。 其中之一。 那么缓存服务器是做什么的呢? 缓存服务器从缓存中删除该项目。 删除意味着由于它不再在缓存中,您的应用程序被迫从现在具有最新副本的数据库中获取它。 因此,虽然到期是有根据的猜测,但这不是猜测。 这是一个实际可预测的同步,它确保缓存始终与数据库一致。

现在,万一 NCache,您可以通过三种不同的方式执行此操作。 一种是 SQL 依赖,它使用数据库事件,就像实时一样。 另一个是 NCaches自己的数据库依赖,他使用轮询,这适用于那些没有事件通知机制甚至SQL服务器的数据库,如果你认为你有太多的SQL依赖并且对于每个SQL依赖都会创建一个SQL缓存依赖SQL server 是一个额外的数据结构。 想想如果你创建了数十万个这样的,你的 SQL 服务器就会窒息。 因此,如果您有很多 SQL 依赖项来采用这种同步方式,那么这可能不是一个好主意。 那么也许 DB 依赖会好得多,因为它有一个可以监控的轮询表,因此在一次调用中它可以同步数千行。

而且,还有第三种方法,实际上只是编写一个 CLR 存储过程,让它由您的触发器调用。 因此,如果您有更新、插入、更新或删除触发器,请调用此 CLR 过程。 而且,CLR 过程从该行获取数据,构造应用程序正在使用的 .NET 对象并将其存储在缓存中。 现在,这是异步 API 非常有用的地方,因为您不想在数据库事务中等待缓存更新。 它只是减慢了往往很快超时的数据库事务。 所以,如果你要实现这个机制,你真的建议你使用异步方法去更新数据。

因此,这些是您可以同步缓存的三种方式。 此功能非常重要,因为它可以让您确保缓存始终是新鲜的,否则您只是在猜测。 而且,您可以用同样的方式将缓存与非关系数据库同步。 有一个自定义依赖功能, NCache 有哪个是你的代码 NCache 您可以调用并监控您的自定义数据存储。 您的自定义数据源可以是云存储。 它可以是任何东西,它只是你可以去检查的任何代码。 因此,保持缓存新鲜非常重要,这些是您可以确保这一点的方法。

通读和通写

因此,下一个功能是通读和通写。

读通写通

通读基本上是你的代码。 现在,我正在谈论的所有这些功能 NCache 有但没有 NCache 只要。 Java 缓存都有它们。 Redis 可能有也可能没有。 所以,如果你想做一个详细的,如果你想知道是否 Redis 有或没有,如果 NCache 只是来这里,只是去比较,有一个 Redis 与 NCache 功能比较。 这是基于他们的文档和缓存文档。 因此,您实际上可以下载它并使用所有这些功能。 因此,通读基本上是位于缓存服务器上的代码。 所以,它看起来像这样。 所以,这是你实施的。 所以,让我给你看那个界面,这样通读界面看起来像…… 所以,这里是一个通读界面,对吧? 手形光标 NCache 并且有一个 InIt 连接到您的数据源,dispose 并且有一个加载方法。 所以,加载给你一个密钥,你根据你得到的任何数据返回一个对象。 然后,您可以指定它应该何时到期和填充。 与 write-through 相同的是,您拥有 InIt 和 dispose,然后写入源代码。 因此,写入可以是添加、更新或删除。 你在哪里使用通读通写,为什么它们如此重要?

通读,首先,它的工作方式让你有一个 Cache.Get 并且缓存没有数据。 缓存将调用您的通读并从数据库中获取它。 这是一个好处。 第二个好处是您可以将通读与过期和数据库同步结合起来。 因此,不是从缓存中删除它,而是重新加载它。 直写的工作方式相同,只是有一个后写,这意味着您只更新缓存,因为缓存更新您的数据库。 因此,您的更新也会变得超快。 因此,无论数据库性能何时成为瓶颈,您都可以使用缓存来帮助您摆脱困境。 一旦实现了通读、通写,就可以将所有持久性代码或大部分持久性代码合并到缓存层中,并且可以从我们刚刚讨论的这两个特性中受益。

数据分组和搜索数据

因此,一旦您使缓存保持新鲜并且还进行了通读通写,您现在就开始缓存大量数据。 因此,缓存不再只是键值存储。 我的意思是把所有东西都拿来做钥匙很不方便。

数据分组

你必须能够搜索。 您必须能够进行 SQL 搜索。 所以,你必须能够做你习惯用数据库做的事情。

发现数据

如果缓存不允许您进行 SQL 搜索,那么它会变得非常有限,并且方式相同,因为您不能在缓存中进行连接,因为它是分布式缓存,还有其他功能分组和子分组以及允许您对数据和分组进行分组的标签一次通话即可获取所有内容。

再说一遍,如果您要缓存大量数据,那么让您在缓存中轻松查找数据非常重要。 因此,这些功能非常重要。

分布式缓存功能

我将快速介绍一些,我真正想接触的一项功能称为近缓存或客户端缓存。

近缓存

一旦那些习惯于做独立 InProc 缓存的人,当他们转移到分布式缓存时,他们的性能突然下降,因为他们正在穿越网络。 他们必须经过序列化,突然性能不再快速。 我们的许多客户抱怨,好吧,我期待我的表现会上升,它实际上已经下降了。 而且,原因是您无法与将对象存储在堆上的独立 InProc 缓存竞争。 因此,如果您有一个客户端缓存功能,它本质上就是一个本地缓存,它将对象保持在本地,但它连接到集群缓存。

同样,这是一个功能 NCache 拥有并且大多数 Java 缓存都拥有,它可以真正为您提供同样快速的性能而不会丢失任何东西。

针对 NCache,您可以访问我们的网站并下载它是一个开源缓存。 因此,您可以下载开源缓存或企业版,正如我所说,您可以获得两者之间的所有比较 NCache 和 Redis 在这一点。

接下来做什么?

 

注册每月电子邮件通讯以获取最新更新。

联系我们

联系电话
©版权所有 Alachisoft 2002 - 版权所有。 NCache 是 Diyatech Corp. 的注册商标。