ASP.NET 缓存(10)

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
简介:

数据库缓存依赖

数据库缓存依赖,在数据库中的数据更改的时候,它能自动的使缓存中的数据失效。这个特征仅在SQL 2005以及以后的版本中适用。

为了理解SQL 缓存依赖的工作原理,先了解一些过去常用的有缺陷的解决方案。

一个常用的技术是使用标记文件。使用这种技术,你在缓存里增加一个数据对象,然后建立起一个文件依赖。然而,这个文件是空文件,你只是用来做标记。 
当用户调用存储过程改变表里的数据,存储过程会删除或者修改标记文件。ASP.NET会立即侦测到这个改变,然后去除符合的缓存项。这个丑陋的工作环境没有伸缩性,并且多个存储过程一起调用的时候,可能会有并发问题。这也迫使你存储过程代码混乱,因为每个存储过程要有相似的文件修改逻辑。让数据库系统和文件系统交互是一个坏主意,增加复杂度减少安全性。


另一个常用的方法是使用自定义的http handler。在这种情况下,代替交互文件,这些存储过程调用http handler并且船体query string来指示数据被改动。http handler能够使用Cache.Remove来去除数据。

使用这种方法的问题在于,它对存储过程的扩展有相当大的复杂性,而且,http handler请求必须是同步的,这就导致明显延迟。更糟的是,延迟在每次存储过程执行时出现。

 

因此,我们需要的是一个可以异步通知的方法,并且是可伸缩可靠的。也就是说,数据库服务器应该通知ASP.NET而不需要停止当前链接。重要的是,它应该松耦合的建立缓存依赖,存储过程不需要知道缓存这回事情。数据库服务器应该监控数据改变,通过各种方法,包括脚本,sql命令,或者批处理。即使改变不是直接由期望的存储过程引发,这个改变也要被通知到ASP.NET.最终,这个通知方法要能支持web farm。


微软把ASP.net,SQL Server, ADO.NET,IIS开发组中的架构师集中起来,一起实现一个解决方案。他们提出2种不同的架构,一种是关于SQL Server 2000 。另一种是SQL Server 2000后续版本。比如SQL Server 2005.他们都用到了SqlCacheDependency 类,该类从CacheDependency 继承。

使用SQL缓存依赖,相对于基于时间的过期策略来说还是非常复杂。如果对实时性要求不是很高,不需要使用它。

 

缓存通知的工作原理

SQL Server 2005将通知架构和消息系统内建在数据库中,叫做Service Broker。Service Broker管理队列,这个队列和表,存储过程或者试图有相同的地位。


使用Service Broker,你能够从特定的数据库事件中获得通知,最直接的方法是使用CREATE EVENT NOTIFICATION 命令来指示你要监控的事件。但是,.NET提供了一个更高级的模型,和ADO.net整合在一起。使用这个模型,你可以很简单的注册一个查询命令,.NET也会自动指导SQL服务器发送通知。ASP.NET在这个基础上提供一个更高级别的模型,允许你在一个查询无效的时候自动的使cache项无效。

SQL Server通知机制工作起来和索引视图类似。每次执行一个操作,SQL Server决定该操作是否影响了注册的命令,如果是,会发送一个通知消息,并且停止通知进程。

如下图所示:

image

启用通知

仅有的配置就是确定你设置了数据库的ENABLE_BROKER标志 
Use Northwind 
ALTER DATABASE Northwind SET ENABLE_BROKER


通知由Select和存储过程一起工作。然而,使用select语法时有一些限制,你必须遵守:

必须使用表的全名,[Owner].table

不能使用聚集函数,比如count(),MAX()

不能用通配符*来选择所有列。只能写成每个列名。

这些是最重要的规则,联机帮助上还有更多的警告和说明。

创建缓存依赖

当创建缓存依赖时,SQL server需要知道你用来获取数据的数据库命令。如果你使用编程的缓存,你必须创建SqlCacheDependency对象,使用构造器来接受一个SqlCommand对象。 
// Create the ADO.NET objects. 
string connectionString = WebConfigurationManager.ConnectionStrings["Northwind"].ConnectionString; 
SqlConnection con = new SqlConnection(connectionString); 
string query ="SELECT EmployeeID, FirstName, LastName, City FROM dbo.Employees"; 
SqlCommand cmd = new SqlCommand(query, con); 
SqlDataAdapter adapter = new SqlDataAdapter(cmd); 
// Fill the DataSet. 
DataSet ds = new DataSet(); 
adapter.Fill(ds, "Employees"); 
// Create the dependency. 
SqlCacheDependency empDependency = new SqlCacheDependency(cmd); 
// Add a cache item that will be invalidated if one of its records changes 
// (or a new record is added in the same range). 
Cache.Insert("Employees", ds, empDependency); 
你也需要调用静态方法SqlDependency.Start() 来初始化监听Web服务器的服务。这只需要对每个数据库连接执行一次,通常调用的地方是在global.asax文件中的Application_Start() 方法中。

SqlDependency.Start(connectionString);

这个方法打开一个新的,非池化的数据库连接。ASP.NET使用这个连接检查通知队列。初次调用Start(), 生成一个有着独一无二名字的新的队列会自动,新的通知服务也随即生成,然触发一个后监听开始。当通知收到,Web Services把通知放入队列,SqlDependency.OnChange事件,是缓存项无效。

即使你有在几个不同的表上有依赖,他们使用的还是相同的队列。这意味着你只需要调用SqlDependency.Start()。如果你不小心调用SqlDependency.Start()方法多次,不会有任何事发生。最后,你可以使用下面的代码分离监听。

SqlDependency.Stop(connectionString); 
通常,在Application_End() 方法中分离监听,释放资源。



















本文转自cnn23711151CTO博客,原文链接:http://blog.51cto.com/cnn237111/589395 ,如需转载请自行联系原作者


相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情: https://www.aliyun.com/product/rds/sqlserver
相关文章
|
4月前
|
SQL 缓存 开发框架
分享一个 .NET EF6 应用二级缓存提高性能的方法
分享一个 .NET EF6 应用二级缓存提高性能的方法
|
4月前
|
缓存 NoSQL Java
【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常
【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常
|
4月前
|
缓存 NoSQL 网络协议
【Azure Redis 缓存】Redisson 连接 Azure Redis出现间歇性 java.net.UnknownHostException 异常
【Azure Redis 缓存】Redisson 连接 Azure Redis出现间歇性 java.net.UnknownHostException 异常
114 1
|
4月前
|
缓存 程序员
封装一个给 .NET Framework 用的内存缓存帮助类
封装一个给 .NET Framework 用的内存缓存帮助类
|
4月前
|
缓存 开发框架 .NET
看看 Asp.net core Webapi 项目如何优雅地使用内存缓存
看看 Asp.net core Webapi 项目如何优雅地使用内存缓存
110 1
|
4月前
|
存储 缓存 开发框架
看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存
看看 Asp.net core Webapi 项目如何优雅地使用分布式缓存
|
缓存 开发框架 .NET
ASP.NET Core 缓存
Get新知识: 缓存相关概念:缓存的类型:总结:总的来说,私有缓存会减少网络带宽的需求,同时会减少从缓存到API的请求。因为私有缓存是存储在客户端浏览器的,对于请求来说,如果缓存还在有限期内,那么请求连网络请求都不会发出会直接在客户端浏览器获取到响应,这样就减少网络请求次数,同样也会减少API请求次数。而共享缓存不会节省缓存到API的网路带宽,但是它会减少请求到API的请求。因为共享缓存是...
52 0
ASP.NET Core 缓存
|
缓存 监控 NoSQL
一个.Net Core开源缓存中间件,让你更加简单、方便使用缓存
一个.Net Core开源缓存中间件,让你更加简单、方便使用缓存
204 0
|
存储 SQL 缓存
ASP.NET Core MVC 从入门到精通之缓存
ASP.NET Core MVC 从入门到精通之缓存
143 0
|
存储 缓存 开发框架
Asp.Net Core 2.1+的视图缓存(响应缓存)
Asp.Net Core 2.1+的视图缓存(响应缓存)
90 0