惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
TaoSecurity Blog
TaoSecurity Blog
H
Heimdal Security Blog
Help Net Security
Help Net Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
N
News | PayPal Newsroom
V2EX - 技术
V2EX - 技术
博客园 - 【当耐特】
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Secure Thoughts
C
CERT Recently Published Vulnerability Notes
罗磊的独立博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
有赞技术团队
有赞技术团队
S
Schneier on Security
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
H
Hacker News: Front Page
The Last Watchdog
The Last Watchdog
Schneier on Security
Schneier on Security
PCI Perspectives
PCI Perspectives
IT之家
IT之家
Project Zero
Project Zero
博客园 - 司徒正美
P
Privacy International News Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Jina AI
Jina AI
Security Latest
Security Latest
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
C
CXSECURITY Database RSS Feed - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
V
Vulnerabilities – Threatpost
W
WeLiveSecurity
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity

博客园 - Kevin Lin

Happy New Year! HTTP状态码大全 [转]jquery的一个模板引擎-zt - Kevin Lin - 博客园 2009年3月 跟ASP.NET MVC一起使用jQuery [摘自千寻网]给鼠标右键增加“见好就收”的功能 ASP.NET 2.0中的URL映射 在.net中使用Gmail发送邮件 [绝对原创]从VS2003(.net1.1)升级到vs2005(.net2.0)全程跟踪记录 使用Asp.net mvc + Linq + mvc_scaffold_gen_setup.exe 生成一个完整的家庭帐册大管家程序 之三 使用Asp.net mvc + Linq + mvc_scaffold_gen_setup.exe 生成一个完整的家庭帐册大管家程序 之二 2008年4月-5月 使用Asp.net mvc + Linq + mvc_scaffold_gen_setup.exe 生成一个完整的家庭帐册大管家程序 之一 XNA Game Studio 2.0 Released版 发布了,好像是前几天的事,但园子里似乎没有讯息嘛 向大家推荐一个不错的休闲游戏 VS2003(.net framework1.1)中,如果让日历控件的“星期”去掉? 农历js脚本 - Kevin Lin - 博客园 WEB开发碰到的问题及经验十八则 - Kevin Lin - 博客园 根据分辨率不同调用不同的css文件 - Kevin Lin - 博客园
2008年9月-10月
Kevin Lin · 2008-09-23 · via 博客园 - Kevin Lin

http://see.stanford.edu/default.aspx 在线课程

http://www.limboy.com/category/coder/js/  中世纪风格网站

目前正在做的一个Web应用,是做了负载均衡的。在应用中,对某些实体数据做了Memory级别的缓存处理,以减少数据库访问次数,提高性能。缓存的实现是采用Asp.net 2.0的System.Web.Caching命名空间中的类。实体数据在某些情况下会有变更,所以需要对缓存进行处理,或清除或同步。在这种情况下产生了一个问题:实体数据发生变更之后,如何通知到后台的N多个Web应用中的缓存?下面方法是做的一些尝试。

1. 采用服务的方式
    这是一种最直接的方式。当然服务的方式可以多种多样,比较简单的方式是提供一个ClearCache.aspx的页面,当实体数据发生变更之后调用N多台Web应该的这个页面。

2. 采用File Dependency的策略
    这种策略让缓存依赖于一个指定的文件,通过改变文件的更新日期来清除缓存。这种方式的缺点是,如果缓存的数据比较多,相关的依赖文件比较松散,对管理这些依赖文件有一定的麻烦。对于负载均衡环境下,还需要同时更新多台Web服务器下的缓存文件,如果多个Web应用中的缓存依赖于同一个共享的文件,可能会省掉这个麻烦,但是对Web应用中运行帐号的权限所限,终归不是那么简洁。

HttpRuntime.Cache.Add(
    
"Key1",
    
new CacheDependency("C:\\test.txt"),
    System.Web.Caching.Cache.NoAbsoluteExpiration,
    System.Web.Caching.Cache.NoSlidingExpiration,
    CacheItemPriority.Default,
    
null
    );

3. 采用SqlCacheDependency的策略
    这种策略让缓存依赖与数据库中指定的数据(查询结果)。可以用Poll的方式主动调用,设定一个周期,循环调用查询语句,如果查询结果发生变化,就会清除缓存。也可以配合Sql Server 2005,采用Push的方式被动的被通知什么时候会清楚缓存。这种Push的方式是基于Sql Server 2005中Broker Service的订阅服务,SqlCacheDependency需要配合SqlDependency来实现这种方式。

using System;
using System.Collections;
using System.Web;
using System.Web.Caching;
using System.Net;
using System.IO;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace CacheManagement
{
    
public interface IWebCache
    
{
        
void Add(string key, object value);
        
object Get(string key);
        
void Remove(string key, bool useDependency);
    }


    
public class WebCacheBase : IWebCache
    
{
        
protected bool CheckParameters(string key)
        
{
            
return !string.IsNullOrEmpty(key);
        }


        
protected virtual CacheDependency GetCacheDependency(string key)
        
{
            
return null;
        }


        
protected virtual void OnBeforeAdd(string key)
        
{
        }

        
        
public virtual void Add(string key, object value)
        
{
            
if (!this.CheckParameters(key)) return;
            
this.OnBeforeAdd(key);
            HttpRuntime.Cache.Insert(
                key,
                value,
                
this.GetCacheDependency(key),
                System.Web.Caching.Cache.NoAbsoluteExpiration,
                System.Web.Caching.Cache.NoSlidingExpiration,
                System.Web.Caching.CacheItemPriority.Default,
                
null);
        }


        
public virtual object Get(string key)
        
{
            
if (!this.CheckParameters(key)) return null;
            
return HttpRuntime.Cache.Get(key);
        }


        
public virtual void Remove(string key, bool useDependency)
        
{
            
if (!this.CheckParameters(key)) return;
            HttpRuntime.Cache.Remove(key);
        }

    }


    
public class SqlDependencyWebCache : WebCacheBase
    
{
        
private string _connectionString;

        
private SqlConnection GetConnection()
        
{
            
return new SqlConnection(this._connectionString);
        }


        
private SqlCommand GetSelectCommand(string key)
        
{
            SqlConnection conn 
= this.GetConnection();
            SqlCommand cmd 
= new SqlCommand();
            cmd.Connection 
= conn;
            cmd.CommandType 
= CommandType.Text;
            cmd.CommandText 
= "select Flag from dbo.CacheDependency where CacheKey=@CacheKey";
            SqlParameter sqlParam 
= cmd.Parameters.Add("@CacheKey", SqlDbType.VarChar, 50);
            sqlParam.Value 
= key;
            
return cmd;
        }


        
private SqlCommand GetUpdateCommand(string key)
        
{
            SqlConnection conn 
= this.GetConnection();
            SqlCommand cmd 
= new SqlCommand();
            cmd.Connection 
= conn;
            cmd.CommandType 
= CommandType.Text;
            cmd.CommandText 
= @"
if exists (select 1 from dbo.CacheDependency where CacheKey=@CacheKey)
  update dbo.CacheDependency set Flag=case when isnull(flag,0)=0 then 1 else 1 end where CacheKey=@CacheKey
else
  insert into dbo.CacheDependency (CacheKey,Flag)
  values (@CacheKey, 0)
";
            SqlParameter sqlParam 
= cmd.Parameters.Add("@CacheKey", SqlDbType.VarChar, 50);
            sqlParam.Value 
= key;
            
return cmd;
        }


        
private void UpdateCacheDependency(string key)
        
{
            SqlCommand cmd 
= this.GetUpdateCommand(key);
            
using (cmd.Connection)
            
{
                cmd.Connection.Open();
                cmd.Prepare();
                cmd.ExecuteNonQuery();
            }

        }


        
protected override void OnBeforeAdd(string key)
        
{
            
this.UpdateCacheDependency(key);
        }


        
protected override CacheDependency GetCacheDependency(string key)
        
{
            SqlCommand cmd 
= this.GetSelectCommand(key);
            SqlCacheDependency sqlCacheDependency 
= new SqlCacheDependency(cmd);
            
using (cmd.Connection)
            
{
                cmd.Connection.Open();
                cmd.Prepare();
                cmd.ExecuteNonQuery();
            }

            
return sqlCacheDependency;
        }


        
public SqlDependencyWebCache(string connectionString)
        
{
            
this._connectionString = connectionString;
        }


        
public override void Remove(string key, bool useDependency)
        
{
            
if (!this.CheckParameters(key)) return;
            
if (useDependency)
            
{
                
this.UpdateCacheDependency(key);
            }

            
else
            
{
                
base.Remove(key, useDependency);
            }

        }

    }


    
public class WebCacheFactory
    
{
        
public static IWebCache GetWebCache()
        
{
            
string connectionString = ConfigurationManager.AppSettings["ConnectionString"];
            
return new SqlDependencyWebCache(connectionString);
        }

    }

}

<%@ Application Language="C#" %>

<script runat="server">

    
private string GetConnectionString()
    
{
        
return "Server=.;User ID=sa;Password=sa;database=TestDB;Connection Timeout=30";
    }

    
    
void Application_Start(object sender, EventArgs e) 
    
{
        System.Data.SqlClient.SqlDependency.Start(
this.GetConnectionString());
    }

    
    
void Application_End(object sender, EventArgs e) 
    
{
        System.Data.SqlClient.SqlDependency.Stop(
this.GetConnectionString());
    }

       
</script>
注1:数据库中新建一个CacheDependency的表,主键为CacheKey varchar(50),另一个字段为Flag bit。缓存项依赖与CacheDependency中对应的一行。
注2:数据库中需要启动Broker Service。命令为:
alter database [dbname] set enable_broker (需要断开其他的数据库连接)。
注3:在Applicantion Start和End的时候需要开启和停止SqlDependency。

结束语:
    缓存的实现除了可以用Asp.net自带的Cache外,还可以用Entlib的Cache Application Block,没有仔细研究过。以上的三种方式是参考网上N多资源以及自己实践的结果。如果有建议或有其他方式,欢迎盖楼。