NCache 引入了条目处理器以允许我们针对服务器端的一组缓存条目执行函数(或“处理器”)。
通常,要更新我们的缓存条目,我们必须与我们的缓存服务器“对话”两次。 一次从缓存中检索条目,另一次在处理后更新它们。 但是,使用条目处理器,我们直接在服务器上更新我们的缓存条目,从而节省了这些网络传输和不必要的资源消耗。
NCache 无论使用何种缓存拓扑,都运行条目处理器。 在分区拓扑的情况下,条目处理器在包含我们要处理的条目的节点上运行。
一旦我们调用条目处理器,它就会根据我们定义的逻辑处理单个项目或一组项目。 NCache 在集群中运行我们的处理器。 在入口处理器内部,我们可以:
- 返回缓存条目而不处理它,
- 修改条目并将其保存到缓存中,或者,
- 删除条目。
如果一个条目在运行处理器之前被锁定,我们可以忽略锁并访问锁定的条目来处理它。
NCache 更多信息 NCache 入口处理器 输入处理器实现
比较入口处理器和其他缓存操作
条目处理器通过节省获取和更新缓存条目的网络行程,帮助我们直接在服务器上更新或清除缓存或条目。
要查看入口处理器的运行情况,让我们编写一个控制台应用程序以将一些客户加载到缓存中。 让我们存储客户的姓名、奖励积分和上次购买日期。 为了激励我们的客户购买,让我们将过去五天内购买的所有客户的奖励积分加倍。 然后,让我们使用入口处理器和批量缓存操作重新创建相同的场景,以查看这些方法之间执行时间的差异。
在开始我们的示例应用程序之前,我们应该有一个 NCache Enterprise 版本实例启动并运行。 入口处理器仅在企业版中可用。
1.使用批量缓存操作
NCache 支持批量操作以在单个调用中同时检索和更新缓存条目。 通过批量操作,我们有更好的性能,因为我们减少了到缓存服务器的网络访问次数。
要批量检索多个缓存条目,我们需要 GetCacheItemBulk()
带有键列表。 它返回字典中找到的项目。 而且,要批量更新项目,我们需要 InsertBulk()
带有要更新的项目字典的方法。
为了开始我们的比较,让我们使用 NCache GetCacheItemBulk()
和 InsertBulk()
在单个请求中检索和更新缓存条目的方法。
在 Program.cs
我们控制台应用程序的文件,让我们写这样的东西,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
using Alachisoft.NCache.Client; using RewardPoints; using RewardPoints.Shared; const string CacheName = "demoCache"; var customers = new List { new Customer(1, "Alice", DateTime.Today.AddDays(-1), 100), new Customer(2, "Bob", DateTime.Today.AddDays(-6), 5), new Customer(3, "Charlie", DateTime.Today.AddMonths(-1), 1), new Customer(4, "Daniel", DateTime.Today.AddDays(-3), 10), new Customer(5, "Earl", DateTime.Today, 20) }; var keys = customers.Select(c => c.ToCacheKey()); // Load customers into the cache ICache cache = CacheManager.GetCache(CacheName); PopulateCache(cache, customers); // Double customer points using NCache Bulk methods var retrievedItems = cache.GetCacheItemBulk(keys); var itemsToUpdate = new Dictionary<string, CacheItem>(); foreach (var item in retrievedItems) { var customer = item.Value.GetValue(); // Check if the customer has purchased anything in the last 5 days if (customer.LastPurchase >= DateTime.Today.AddDays(-5)) { var updated = customer with { Points = customer.Points * 2 }; itemsToUpdate.Add(updated.ToCacheKey(), updated.ToCacheItem()); } } cache.InsertBulk(itemsToUpdate); |
首先,我们将一些客户加载到缓存中。 我们使用了在创建过程中创建的默认“demoCache”缓存 NCache 安装。 接下来,我们使用 GetCacheItemBulk()
方法。 然后,在检查每个客户的最后购买日期后,我们将他的积分翻倍,并将所有更新的客户放回缓存中。
我们没有单独更新我们的客户,而是使用字典来累积赢得奖励的客户。 然后我们使用了 InsertBulk()
用字典的方法。
随着 GetCacheItemBulk()
和 InsertBulk()
方法,我们将网络行程减少到只有两次。 一个网络调用检索所有客户,另一个网络调用将它们保存回缓存中。
有关这些和其他批量方法的更多详细信息,请检查 CRUD 操作:概述。
2. 使用入口处理器
现在我们已经使用了 Bulk 方法,让我们使用 Entry Processor 将客户的奖励积分加倍。 像这样的东西,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using Alachisoft.NCache.Client; using RewardPoints; using RewardPoints.Shared; const string CacheName = "demoCache"; var customers = new List { new Customer(1, "Alice", DateTime.Today.AddDays(-1), 100), new Customer(2, "Bob", DateTime.Today.AddDays(-6), 5), new Customer(3, "Charlie", DateTime.Today.AddMonths(-1), 1), new Customer(4, "Daniel", DateTime.Today.AddDays(-3), 10), new Customer(5, "Earl", DateTime.Today, 20) }; var keys = customers.Select(c => c.ToCacheKey()); // Load customers ICache cache = CacheManager.GetCache(CacheName); PopulateCache(cache, customers); // Double customer points using Entry Processor var processor = new DoublePointsProcessor(); cache.ExecutionService.Invoke(keys, processor); |
请注意,我们不必使用任何方法来更新缓存条目。 我们只创建了一个处理器,传递了一组密钥,并调用了 Invoke()
方法。 我们必须更新入口处理器本身内部的客户。
NCache 更多信息 NCache 入口处理器 输入处理器实现
配置入口处理器
要编写入口处理器,我们需要创建一个继承自的类 IEntryProcessor
并使用 [Serializable]
属性。 这是我们的入口处理器,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
using Alachisoft.NCache.Runtime.Processor; namespace RewardPoints.Shared; [Serializable] public class DoublePointsProcessor : IEntryProcessor { public bool IgnoreLock() => true; public object Process(IMutableEntry entry, params object[] arguments) { // Check if the cache entry is a customer and // if the customer has purchased something in the last 5 days if (entry.Key.StartsWith(nameof(Customer)) && entry.Value is Customer { LastPurchase: var lastPurchase } customer && lastPurchase >= DateTime.Today.AddDays(-5)) { // Update the customer's points var updatedCustomer = customer with { Points = customer.Points * 2 }; entry.Value = updatedCustomer; return updatedCustomer; } return false; } } |
要更新处理器中的缓存条目,我们需要覆盖 Value
的财产 entry
参数与更新的缓存条目。
如果客户端应用程序正在锁定条目,我们可以使用 IgnoreLock()
方法。 它会忽略锁并访问条目来处理它。
在使用我们的新处理器之前,我们需要将 DLL 与我们的处理器及其依赖项一起部署到 NCache. 我们可以使用 Powershell Install-NCacheModule
命令或 NCache 网络管理器。 有关使用 Web 管理器部署我们的入口处理器的说明,请检查 部署提供者.
例如,让我们停止“demoCache”实例并运行 Powershell Install-NCacheModule
命令,
NCache 更多信息 NCache 入口处理器 输入处理器实现
入口处理器如何处理 操作失败?
一旦入口处理器运行,它返回类型的结果集合 IEntryProcessorResult
. 每个结果包含一个 IsSuccessful
旗帜和一个 Value
我们修改的结果。 对于我们的示例输入处理器, Value
财产将包含 false
,如果客户最近没有任何购买或更新的客户,否则。
如果在入口处理器运行时抛出异常,则 IsSuccessful
标志将是 false
和 Exception
属性将填充抛出的异常。
为了使我们的入口处理器故障安全,我们应该处理任何潜在的异常。 例如,我们可以得到一个 OperationFailedException
如果有任何连接失败。 另外,我们可以得到一个
EntryProcessorException
,在这种情况下,入口处理器没有修改任何缓存条目。
这就是我们如何显示输入结果和可能的异常消息,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
using Alachisoft.NCache.Client; using RewardPoints; using RewardPoints.Shared; const string CacheName = "demoCache"; var customers = new List { new Customer(1, "Alice", DateTime.Today.AddDays(-1), 100), new Customer(2, "Bob", DateTime.Today.AddDays(-6), 5), new Customer(3, "Charlie", DateTime.Today.AddMonths(-1), 1), new Customer(4, "Daniel", DateTime.Today.AddDays(-3), 10), new Customer(5, "Earl", DateTime.Today, 20) }; var keys = customers.Select(c => c.ToCacheKey()); // Load customers ICache cache = CacheManager.GetCache(CacheName); PopulateCache(cache, customers); try { // Double customer points using Entry Processor var processor = new DoublePointsProcessor(); var processedEntries = cache.ExecutionService.Invoke(keys, processor); foreach (IEntryProcessorResult entryResult in processedEntries) { DisplayEntryResult(entryResult); } } catch (EntryProcessorException e) { Console.WriteLine($"Error running the processor: {e.Message}"); } catch (OperationFailedException e) { Console.WriteLine($"Error connecting to the cache server: {e.Message}"); } |
现在,让我们并排运行我们的三个备选方案。 我在我的机器上运行它们 NCache 在本地安装并使用我生成的 20 个随机客户 虚假. 这是结果,
结论
毫无疑问,带有输入处理器的替代方案是最快的。 它在 12 毫秒内完成,而使用 Bulk 方法的那个在 72 毫秒内完成。 使用 Entry Processors,我们注意到性能有所提高,因为我们通过直接在服务器上将客户的点数加倍,从而节省了所有过多的网络访问。
这就是输入处理器及其工作原理。 即使我们没有编写基准来测试它 NCache 功能,这种比较让我们了解如何使用输入处理器。 和他们一起,我们节省了一些往返我们的 NCache 服务器通过直接在一个 NCache 服务器。 下次您需要更新某些缓存条目时,请尝试使用条目处理器。
有关输入处理器如何工作的更多详细信息,请查看 缓存中入口处理器的工作.
为了遵循我们在这篇文章中写的代码,请查看我的 NCache 演示库 在GitHub上。