网站架构之缓存应用
2021年1月12日 | by tgcode
这篇来讲如何利用memcached实现一级缓存,以及如何让一级缓存组件支持在企业库,memcached或者其它第三方实施方案之间的切换。memcached本人并没有太多经验,如果文中有说的不对的地方,还希望批评指出,且文中关于memcached的代码大多来自网络。
创建memcached实现类MemcachedWebCacheProvider,由它来继承缓存提供者接口IWebCacheProvider,主里memcached客户端我采用.NET memcached client library ,这个类库很久没有更新这过了,没有和java版同步,有部分功能目前没有实现。
1:初始化memcached服务,这段初始化代码在程序中保证执行一次就够,一般可以放在gloabl文件中,或者是设置一个静态变量来存储服务的状态。

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
–>privatevoidSetup()
{
String[]serverlist={“127.0.0.1:11211“};
this._pool=SockIOPool.GetInstance(“default“);
this._pool.SetServers(serverlist);//设置服务器列
//各服务器之间负载均衡的设置
this._pool.SetWeights(newint[]{1});
//socketpool设置
this._pool.InitConnections=5;//初始化时创建的连接数
this._pool.MinConnections=5;//最小连接数
this._pool.MaxConnections=250;//最大连接数
//连接的最大空闲时间,下面设置为6个小时(单位ms),超过这个设置时间,连接会被释放掉
this._pool.MaxIdle=1000*60*60*6;
//通讯的超时时间,下面设置为3秒(单位ms),.NET版本没有实现
this._pool.SocketTimeout=1000*3;
//socket连接的超时时间,下面设置表示连接不超时,即一直保持连接状态
this._pool.SocketConnectTimeout=0;
this._pool.Nagle=false;//是否对TCP/IP通讯使用Nalgle算法,.NET版本没有实现
//维护线程的间隔激活时间,下面设置为60秒(单位s),设置为0表示不启用维护线程
this._pool.MaintenanceSleep=60;
//socket单次任务的最大时间,超过这个时间socket会被强行中断掉(当前任务失败)
this._pool.MaxBusy=1000*10;
this._pool.Initialize();
}
2:获取一个memcached客户端。
Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
–>privateMemcachedClientGetClient()
{
MemcachedClientclient=newMemcachedClient();
client.PoolName=“default“;
returnclient;
tgcode
}
3:根据memcached提供的功能实现IWebCacheProvider,代码就不贴了,大家可以自己去试试。
到此我们就利用memcached实现了一级缓存,由于.NET memcached client library 实现了分布式,我们只需要在多台服务器上安装上memcached服务,在初始化memcached代码中增加了服务器相关配置即可。String[]serverlist={“127.0.0.1:11211“};
如何让一级缓存组件支持多实现方案之间的切换。
MyWebCacheServiceClient:客户端缓存组件实例,它来完成一级缓存与二级缓存之间的联系,以及根据配置文件来选择一级缓存的实施方案。
第一:CacheServiceMode,根据它就可以决定缓存是只缓存二级缓存还是两级都缓存。
1:LocalCacheOnlyMode,只启用web server上的二级缓存。
2:BufferedLCacheServerMode,即启用web server上的二级缓存也启用cache server上的缓存。
3:Off,关闭缓存功能。
第二:IWebCacheProvider service = this .GetPrimaryCacheProvider(hashKey);方式决定了一级缓存的实施方案。


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
–>///
///获取一级缓存
///
///
///
///
privateIWebCacheProviderGetPrimaryCacheProvider(uinthashKey)
{
IWebCacheProviderprovider=null;
stringcacheType=WebConfig.ChannelConfig[“CacheType“].ToString().ToLower();
switch(cacheType)
{
case“memcached“:
provider=WebCacheProviderFactory.GetMemcachedWebCacheProvider(configFilePath);
break;
case“entlib“:
provider=servicePool.GetServiceClient(hashKey)asIWebCacheProvider;
break;
}
returnprovider;
}
插入缓存的逻辑:原理就是根据配置文件中的CacheMode来完成缓存级别的判定以及一级缓存的方案。


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
–>publicvoidInsert(stringkey,objectvalue,stringregion,stringsubRegion,CacheItemConfigcacheItemConfig)
{
if(string.IsNullOrEmpty(key)||value==null)
return;
//关闭模式,不使用缓存
if(Options.CacheServiceMode==ECacheServiceMode.Off)
{
return;
}
elseif(Options.CacheServiceMode==ECacheServiceMode.BufferedLCacheServerMode
||Options.CacheServiceMode==ECacheServiceMode.LocalAndCacheServerAndSql
||Options.CacheServiceMode==ECacheServiceMode.LocalCacheOnlyMode)
{//使用带缓冲的模式
if(Options.BufferType==ECacheDependencyType.SlidingTime)
{
SecondaryCacheProvider.Insert(key,value,region,subRegion,MyCacheItemPriority.Normal,Options.BufferSlidingTime);
}
elseif(Options.BufferType==ECacheDependencyType.AbsoluteTime)
{
SecondaryCacheProvider.Insert(key,value,region,subRegion,MyCacheItemPriority.Normal,Options.BufferAbsoluteTime);
}
if(Options.CacheServiceMode==ECacheServiceMode.LocalCacheOnlyMode)
{//只使用本地缓存
return;
}
}
checkKey(key);
uinthashKey=hash(key);
try
{
if(Options.CacheServiceMode==ECacheServiceMode.CacheServerMode
||Options.CacheServiceMode==ECacheServiceMode.BufferedLCacheServerMode
||Options.CacheServiceMode==ECacheServiceMode.CacheServerAndSql
||Options.CacheServiceMode==ECacheServiceMode.LocalAndCacheServerAndSql)
{//CacheServer模式使用Cache服务器保存Cache
IWebCacheProviderservice=this.GetPrimaryCacheProvider(hashKey);
byte[]byteValue=SerializationHelper.SaveToBinaryBytes(value);
varcachePriority=ModelConverter.ToRefClass(cacheItemConfig.CachePriority);
if(cacheItemConfig.CacheType==ECacheDependencyType.AbsoluteTime)
{
AbsoluteTimeCacheDependencyabsTime=newAbsoluteTimeCacheDependency();
absTime.AbsoluteTime=DateTime.Now.AddMinutes(cacheItemConfig.CacheTimeMinutes);
service.Insert(key,byteValue,region,subRegion,cachePriority,absTime);
}
elseif(cacheItemConfig.CacheType==ECacheDependencyType.SlidingTime)
{
SlidingTimeCacheDependencyslTime=newSlidingTimeCacheDependency();
slTime.SlidingTime=newTimeSpan(0,cacheItemConfig.CacheTimeMinutes,0);
service.Insert(key,byteValue,region,subRegion,cachePriority,slTime);
}
}
}
catch(Exceptionex)
{//出现异常,保存到数据库中
servicePool.ReplaceServiceClient(hashKey);
this.SendLogEmail(ex);
}
}
客户端调用代码:为了调用方便,创建一个CacheHelper来帮助完成:


Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/
–>publicclassCacheHelper
{
///
///主分区
///
publicconststringREGION=“MyBlog“;
///
///子分区
///
publicconststringSUB_REGION=“default“;
publicconststringBlogListConfigKey=“BlogListConfigKey“;
#region页面间数据传递
///
///新增页面间传递数据到WebCache
///
///返回PageKeyID,用于页面间传递的键值
publicstaticstringInsertPageParams(stringconfigKey,objectobj,stringpageKey)
{
stringresult=null;
MyWebCacheServiceClientcacheClient=CacheClientFactory.GetWebCacheServiceClient(REGtgcodeION,SUB_REGION,configKey);
cacheClient.Insert(
MyWebCacheServiceClient.BuildKey(configKey,pageKey),
obj,
REGION,
SUB_REGION);
returnresult;
}
///
///从Cache里获取页面传递Cache
///
///FlightCacheKey里的常量
///页面传递的键值
publicstaticobjectGetPageParams(stringconfigKey,stringpageKey)
{
objectresult=null;
MyWebCacheServiceClientcacheClient=CacheCltgcodeientFactory.GetWebCacheServiceClient(REGION,
SUB_REGION,configKey);
result=cacheClient.Get(
MyWebCacheServiceClient.BuildKey(configKey,pageKey),
REGION,
SUB_REGION);
returnresult;
}
#endregion
}
两级缓存类结构图:
以上代码贴出来看起来有点乱,这里贴出网站两级缓存类结构图:
js给初学者的印象总是那么的“杂而乱”,相信很多初学者都在找轻松学习js的途径。我试着总结自己学习多年js的经验,希望能给后来的学习者探索出一条“轻松学习js之路”。js给人那种感觉的原因多半是因为它如下的特点: A:本身知识很抽象、晦涩难懂,如:闭包、内置对…