随着时间的推移,分布式缓存变得越来越流行,因为它提高了应用程序性能并提供了可伸缩性。 由于需要一种快速且可扩展的方法,人们将越来越多的数据缓存到缓存中。 应用程序的性能越高,客户端应用程序的数量就越多。 但是,当多个客户端向数据源放置数据和从数据源获取数据时,您的数据库和缓存很可能会不同步。 为了解决这个问题,大多数人使用称为生存时间 (TTL) 或 绝对到期. 此到期会在指定时间后自动删除指定的缓存项。 虽然它很流行,但这种机制是对数据在缓存中保持多长时间不变的有根据的猜测。
如果您确信您的数据在这段时间内不太可能发生变化,或者您的数据不是很敏感,这意味着您可以负担得起从缓存中读取旧的陈旧数据,那么您可以使用 呼气. 但是,如果您的数据是业务敏感的,并且您无力从缓存中读取不准确的数据,那么陈旧的数据将让您付出巨大的代价。 在这种情况下,访问过时数据是您不应该承担的风险。
NCache 更多信息 数据过期类型 NCache 配套文档
正在同步 NCache 使用 SQL Server
为避免在您的 .NET 应用程序中出现上述情况,您需要确保您的缓存始终与数据库保持同步。 为了这个确切的目的, NCache 为您提供称为数据库同步功能 SQL 依赖 使您的缓存与 SQL Server 数据库保持同步。 如果数据集中发生任何更改,SQL 依赖项使用查询通知将缓存与数据库同步。
NCache 更多信息 SQL 依赖 NCache 配套文档
SQL Server 中的查询通知
查询通知是 SQL Server 的一项功能,可在数据库中的数据集更改时通知所有数据库客户端。 NCache Server利用这个特性成为一个SQL Server客户端,通过SQL Dependency向SQL Server注册自己。
这样,SQL Server 通知 NCache 当数据库中的特定数据发生变化时。 和 NCache 保持缓存项和数据库相应数据集的映射。 有了这个, NCache 可以使缓存项无效,因此下次应用程序需要时从数据库中获取新副本。
NCache 通过其 Client API 为您提供 SQL Dependency API。 但是,在将缓存项添加到时,您必须通过此 API 提供以下参数 NCache.
NCache 更多信息 SQL 依赖 设置 SQL Server 环境
Sync NCache 使用 SQL Server:一个快速示例
假设您有一个基于 .NET 的在线购物系统,其中有数百个客户同时访问的一系列可搜索项目。 购物门户网站在圣诞节开放,所有库存均有 40% 的折扣。 应用服务器更新数据库中产品的单价,而缓存不知道这一变化。
如果客户端访问缓存中的项目,这些项目的旧副本仍然可用,没有折扣。 当客户搜索产品时,他们会得到旧的圣诞节单价——这导致客户对企业感到沮丧和不满。
但是如果你使用 NCache 与SQL服务器的数据库同步功能,用户可以启用通知以保持数据与数据库的每次更新同步。 在这种情况下,应用程序不会面临此数据完整性问题,因为缓存始终具有正确的数据。
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 |
// Creating connection string to get connected with database. string connectionString = "Server=SERVERNAME; Database=NORTHWIND; UserId=USERID; Password=PASSWORD;"; // Getting products from database. List products = FetchProductFromDB(); // Creating dictionary of CacheItems. Dictionary<string, CacheItem> cacheItems = new Dictionary<string, CacheItem>(); foreach(Product product in products) { string productKey = $"Product: {product.ProductID}"; // Creating an SQL dependency on the unit price of product. Whenever the Unitprice changes, the product is removed from the cache. string query = $"Select UnitPrice from dbo.Products where ProductID = {product.ProductID}"; // Creating dependency on all the products. SqlCacheDependency dependency = new SqlCacheDependency(connectionString, query); CacheItem productItem = new CacheItem(product); // Adding Dependency to product item productItem.Dependency = dependency; } // Adding CacheItems in cache cache.Add(productKey, productItem); |
你应该使用的原因 NCache SqlCacheDependency 与SQL Server同步数据的方法很简单。 您的缓存数据永远不会过时,您可以自信地放入和获取各种数据,而不会遇到数据完整性问题。
NCache 更多信息 SqlCacheDependency NCache 配套文档
通过 ReadThru 提供程序自动重新加载缓存项
如果您希望缓存在数据库中相应数据发生更改时自动重新加载它,而不是使缓存项无效,那么您需要实现 IReadThruProvider 界面 NCache. 现在,无论何时 NCache 从 SQL Server 接收更新通知而不是从缓存中删除该项目, NCache 调用您的 ReadThru 提供程序以从数据库中获取更新的数据。
在将数据插入缓存之前添加以下代码行,并且 NCache 为您处理数据的自动同步。
1 2 3 4 5 6 7 8 9 |
// Create a new cache item and add sql dependency to it CacheItem item = new CacheItem(product); item.Dependency = sqlDependency; // Resync if enabled, will automatically resync cache with SQL server item.ResyncOptions = new ResyncOptions(true); // Add cache item in the cache with SQL Dependency and Resync option enabled cache.Insert(key, item); |
NCache 更多信息 数据源提供者通读 NCache 配套文档
SQL 依赖项中的参数化查询
数据库中太多的更改需要缓存项的频繁失效。 对于每个数据失效,都需要提供一个 SELECT 查询。 这意味着 SQL Server 需要在执行之前编译这个 SQL 查询。 这会导致性能下降,因为查询编译需要很长时间。
为了解决这个性能问题, NCache 允许您使用参数化 SQL 查询,您可以在运行时指定参数值,并且这些值在每次执行时都会更改。 在这里,SQL 查询本身在第一次执行时就被编译,不再需要重新编译,这节省了大量时间并提高了性能。
要在您的应用程序中使用参数化查询,而不是编写普通的选择查询,您可以实现以下查询。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Creating Param to be passed in stored procedure dictionary. SqlCmdParams paramProductID = new SqlCmdParams { Type = CmdParamsType.Int, Value = product.ProductID }; // Creating stored procedure params. Dictionary<string, SqlCmdParams> parameter = new Dictionary<string, SqlCmdParams>(); parameters.Add("@ProductID", paramProductID); CacheItem productItem = new CacheItem(product); /*Creating an SQL dependency on the unit price of the product. Whenever the unit price changes, the product is removed from the cache*/ SqlCacheDependency dependency = new SqlCacheDependency(connectionString, query, SqlCommandType.Text, parameters); // Adding Dependency to the product item productItem.Dependency = dependency; cache.Add(productKey, productItem); |
NCache 更多信息 SqlCacheDependency SqlCacheDependency
基于存储过程的 SQL 依赖
许多组织更喜欢以存储过程的形式将应用程序使用的所有 SQL 查询保存在数据库中。 这提高了性能,因为所有这些存储过程都是预编译的,并且运行速度比动态 SQL 查询快得多。 其次,他们可以将所有数据库访问 SQL 查询保存在一个地方,而不是分散在每个应用程序中,如果他们想更新他们的 SQL 查询,那么很难修改。
对于这些组织, NCache 支持基于存储过程的 SQL 依赖关系,而不是指定动态 SQL 查询甚至参数化 SQL 查询,您可以指定存储过程调用。
以下 SQL 查询创建一个以 ProductID 作为参数的过程。 此存储过程可用于您的应用程序中以将缓存与数据库同步。
1 2 3 4 |
create PROCEDURE sp_GetUnitPriceByProductID @ProductID int as Select UnitPrice from dbo.Products where ProductID = @ProductID; |
要在 .NET 应用程序中调用此存储过程,请使用以下代码片段。
1 2 3 4 5 6 7 8 9 10 11 |
// Specifying stored procedure, created in database. string spGetUnitPriceByProductID = "sp_GetUnitPriceByProductID"; /*Creating an SQL dependency on the unit price of product. Whenever the unitprice changes, the product is removed from the cache*/ SqlCacheDependency dependency = new SqlCacheDependency(connectionString, spGetUnitPriceByProductID, SqlCommandType.StoredProcedure, parameters); // Adding Dependency to product item productItem.Dependency = dependency; cache.Add(productKey, productItem); |
结论
如果你不使用 NCache 作为基于 ASP.NET 的应用程序的主要数据源,现在开始使用它:
- NCache 是一种内存解决方案,不需要任何客户端干预来自动重新平衡数据,使您的应用程序非常灵活。
- 它允许您在运行时添加任意数量的服务器,为您的 .NET 应用程序提供最具扩展性的解决方案。
如果您有一个 ASP.NET 应用程序,但您使用的数据库不支持通知, NCache 为您提供了一个名为 基于轮询的依赖.