memcached+net缓存

最近对线上项目进行了一次缓存方面的优化,本来6月就该写的,但是项目一直忙,就给自己理由偷懒了

缓存方面的思考参考代震军的文章比较多,文章地址:

http://www.cnblogs.com/daizhj/archive/2009/11/17/1604436.html

http://www.cnblogs.com/daizhj/archive/2009/03/23/1386652.html

我以前项目上一直都是,直接使用memcached或者直接使用net本地缓存,二者都是单独使用

这次对项目调整修改了下结构。主要目的是结合二者优势更有效使用缓存,二来也是为了解决网站更新代码缓解数据库查询压力的问题。

先大致说下它们的优点缺点:

1.memcached 优点是,稳定,受外因素影响较小,安全性高。缺点是速度方面不如net缓存,序列化和传输产生的额外开销比较大

2.net缓存,优点是高效,速度极快。缺点是稳定性,安全性差,受应用程序池回收设置影响。

针对以上优缺点,决定使用二级缓存模式:客户端-》NET本地缓存-》memcached缓存-》数据库  (NET本地缓存默认5分钟失效,memcached缓存时间设置,一般30分钟以上,个人觉得最后把memcached缓

存当成个永久缓存来设置,缺点就是缓存更新方面的策略需要考虑周全)

这样,当客户端访问本地缓存:
有数据->直接返回
无数据->读取下级缓存(“memcached缓存”)->有数据->返回,同步写份net缓存(无数据则数据库查询,并建立memcached缓存)

-------------------------------------------------------------------------------------------

以上设计经过实际应用,服务器内网和memcached之间的通讯量大大减少,CPU占用资源方面也相对保持稳定状态,不如同之前浮动从10%-30%(现在是10%-15%)。该项目网站日PV大概在250W+

网站缓存方面算是有了个初步的完成,以上还有个很大的优点就是在站点重启的时候,尤其是高并发访问的情况下,net缓存一失效,就可直接通过memcached,而不会直接造成高并发查询数据库,导致

数据库压力上升,如果有一句sql语句查询稍慢,就有可能导致查询死锁的状况出现。哈,这个可是很实际的优点。现在的代码部署了,在网站有用户访问的情况下更新代码不再是问题了

 ----------------------------------------------------------------

上面说了这么多,引入正题,C#网站应用程序中,使用memcached,在windos服务重启会有个情况,网站和memcached之间的socks连接失败,需要网站也同步重启下,服务才能重新连接。那么我刚上面说

的高并发查询情况导致数据库堵了的情况又会出现,而且是net本地缓存,和memcached缓存都丢失了,二者加起来至少3个G的数据
需要解决上面的问题,重新启动网站,而重新启动网站无非也就重新建立了下同memcahced之间的socks连接池,所以解决这问题的关键点是重新构建网站和memcached之间的socks连接池.本着这样的思路

,我这对Memcached.ClientLibrary 进行了扩展
1.
首先扩展定义了接口 ICacheManageConfig.cs

里面定义里个必须实现的方法 void Memcached_Restart(string LogMessage);  用来重建连接池

2.在调用memcached客户端组件的数据层,增加了接口实现类CacheManageConfig.cs

ExpandedBlockStart.gif 代码
    public   class  CacheManageConfig : Memcached.ClientLibrary.ICacheManageConfig
    {
        
private   static  Memcached.ClientLibrary.SockIOPool pool  =   null ;
        
        
///   <summary>
        
///  实现接口方法,memcached客户端组件反射调用接口的实现方法
        
///   </summary>
        
///   <param name="message"></param>
         public   void  Memcached_Restart( string  message)
        {
            _Restart(message);
        } 

        
///   <summary>
        
///  初始化连接池
        
///   </summary>
         public   static   void  Memcached_Init()
        {
            Memcached.ClientLibrary.MemcachedSocksMonitor.CacheManageConfigPath 
=   " KM.Brand.DBLib.Cache.CacheManageConfig " ;
            
// 每次初始化都用新的连接池名
            Memcached.ClientLibrary.MemcachedSocksMonitor.CachePoolName  =   " pool "   +  Guid.NewGuid().ToString();
           
string  memcachedserver  =  System.Configuration.ConfigurationManager.AppSettings[ " memcachedserver " ];
            
string [] serverlist  =  {memcachedserver};
            pool 
=  Memcached.ClientLibrary.SockIOPool.GetInstance(Memcached.ClientLibrary.MemcachedSocksMonitor.CachePoolName);
            pool.SetServers(serverlist);
            pool.InitConnections 
=   15 ;
            pool.MinConnections 
=   15 ;
            pool.MaxConnections 
=   200 ;
            pool.SocketTimeout 
=   3000 ;
            pool.SocketConnectTimeout 
=   1000 ;
            pool.MaintenanceSleep 
=   30 ;
            pool.Failover 
=   true ;
            pool.Nagle 
=   false ;
            
// socket单次任务的最大时间,超过这个时间socket会被强行中断掉(当前任务失败)
            pool.MaxBusy  =   1000   *   10 ;
            pool.Initialize();
            
// 由于有旧代码使用默认的程序池名字,所以同时初始化一个默认名字的连接池
             pool  =  Memcached.ClientLibrary.SockIOPool.GetInstance();
            pool.SetServers(serverlist);
            pool.InitConnections 
= 10 ;
            pool.MinConnections 
=   10 ;
            pool.MaxConnections 
=   50 ;
            pool.SocketTimeout 
=   3000 ;
            pool.SocketConnectTimeout 
=   1000 ;
            pool.MaintenanceSleep 
=   30 ;
            pool.Failover 
=   true ;
            pool.Nagle 
=   false ;
            
// socket单次任务的最大时间,超过这个时间socket会被强行中断掉(当前任务失败)
             pool.MaxBusy  =   1000   *   10 ;
            pool.Initialize();
         }

        
#region   连接池重建
        
///   <summary>
        
///  连接池重建
        
///   </summary>
        
///   <param name="message"></param>
         private   static   void  _Restart( string  message)
        {
            
if  (pool  !=   null )
            {
// 其实可以把缓存管理模块整合到这个项目一起的。哎!               
                pool.Shutdown(Memcached.ClientLibrary.MemcachedSocksMonitor.CachePoolName);
            }
            
// 重新初始化
              Memcached_Init();
            KM.Brand.DBLib.Cache.CacheManage.Dispose(message);
        }
        
#endregion
    }

3.在网站应用global.asax中配置连接池启动

  protected   void  Application_Start( object  sender, EventArgs e)
 {
           
// 初始化memcached连接池
            KM.Brand.DBLib.Cache.CacheManageConfig.Memcached_Init();
}

4。最关键点,修改memcached客户端源代码实现,回收连接池

主要有新建立了个类,MemcachedSocksMonitor.cs 实现连接池基本操作

ExpandedBlockStart.gif 代码
  public   static   class  MemcachedSocksMonitor
    { 
        
private   static   string  _CacheManageConfigPath;
        
private   static   int  _SocksMaxErrCount;
        
private   static   string  _CachePoolName;
        
///   <summary>
        
///  连接池名字
        
///   </summary>
         public   static   string  CachePoolName
        {
            
get  {  return  _CachePoolName; }
            
set  { _CachePoolName  =  value;}
        }

        
/// <summary>
        
/// 初始化一定要设置
        
/// 实现接口ICacheManageConfig的类完整命名空间路径(包含类名),重新建立缓存管理模块单件实例的方法实现名称
        
///   </summary>
         public   static   string  CacheManageConfigPath
        {
            
get  {  return  _CacheManageConfigPath; }
            
set  { _CacheManageConfigPath  =  value; }
        }

        
///   <summary>
        
///  执行重建的条件,该数字累加到20就重建连接池,并清零,次数累计保留1分钟
        
///   </summary>
         public   static   int  SocksMaxErrCount
        {
            
get  {  return  _SocksMaxErrCount; }
            
set  { _SocksMaxErrCount  =  value; }
        } 

        
///   <summary>
        
///  重建连接池
        
///   </summary>
         public    static   void  Restart()
        {
// 识别需要重启,看日志错误 log.Error(GetLocalizedString("set IOException"), exception5);
            ICacheManageConfig CacheDispose  =  (ICacheManageConfig)Assembly.Load(CacheManageConfigPath).CreateInstance( " Memcached_Restart " );  // (ICacheManageConfig)Create(DisposeMonthodName);
            CacheDispose.Memcached_Restart( " memcached服务连接池传输数据失败,重新生成了连接池!\r\n 无法将数据写入传输连接: 远程主机强迫关闭了一个现有的连接!!一分钟内连续出错次数 "   +  SocksMaxErrCount);
        }

        
///   <summary>
        
///  记录传输错误的失败次数,并决定是否要重建连接池
        
///  这里用了本地缓存,一般情况下这缓存都是不存在的,该方法也很少会执行到
        
///   </summary>
         public   static   void  SockIOErrRestatr()
        {
            
// 执行一次就进行一次逻辑处理
             string  key  =   " MemcachedClientLibrarySockIOErrRestatr " ;
            
object  value  =  System.Web.HttpRuntime.Cache.Get(key);
            
if  (value  !=   null )
            {
                
if  (SocksMaxErrCount  >   20 )
                {
                    
// 执行重建memcached连接池
                    Restart();
                    SocksMaxErrCount 
=   0 ;
                }
                
else
                {
                    SocksMaxErrCount 
=  SocksMaxErrCount  +   1 ;
                }
            }
            
else
            {
                SocksMaxErrCount 
=   1 ;
                System.Web.HttpRuntime.Cache.Add(key,
1 null ,DateTime.Now.AddMinutes( 1 ), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.High,  null );
            } 
        } 
    }

5.SockIOPool.cs 修改Shutdown 函授,也忘记有没其他地方修改了


 

ExpandedBlockStart.gif 代码
   [MethodImpl(MethodImplOptions.Synchronized)]
        
public   void  Shutdown( string  poolName)
        {
            
bool  isDebugEnabled  =  Log.IsDebugEnabled;
            
if  (( this ._maintenanceThread  !=   null &&   this ._maintenanceThread.IsRunning)
            {
                
this .StopMaintenanceThread();
            } 
            
bool  flag2  =  Log.IsDebugEnabled;
            ClosePool(
this ._availPool);
            ClosePool(
this ._busyPool);
            
this ._availPool  =   null ;
            
this ._busyPool  =   null ;
            
this ._buckets  =   null ;
            
this ._hostDeadDuration  =   null ;
            
this ._hostDead  =   null ;
            
this ._initialized  =   false ;
            
bool  flag3  =  Log.IsDebugEnabled;
            
// 下面方法是增加的,当memcached重启后,导致当前连接池连接不上,执行停止命令后
            
// 移除失败的连接池,这样重新初始化就会重新建立sock连接池
             if  (poolName  ==   "" )
            {
                poolName 
=  GetLocalizedString( " default instance " );
            }
            Pools.Remove(GetLocalizedString(poolName));
        }

 6 MemcachedClient.cs修改,具体忘记改了哪些,全部复制上来好了

ExpandedBlockStart.gif 代码
namespace  Memcached.ClientLibrary
{
    
using  ICSharpCode.SharpZipLib.GZip;
    
using  log4net;
    
using  System;
    
using  System.Collections;
    
using  System.Globalization;
    
using  System.IO;
    
using  System.Resources;
    
using  System.Runtime.Serialization;
    
using  System.Runtime.Serialization.Formatters.Binary;
    
using  System.Text;
    
using  System.Text.RegularExpressions;

    
public   class  MemcachedClient
    {
        
private   bool  _compressEnable;
        
private   long  _compressThreshold;
        
private   string  _defaultEncoding;
        
private   string  _poolName;
        
private   bool  _primitiveAsString; // Memcached.ClientLibrary.StringMessages
         private   static  ResourceManager _resourceManager  =   new  ResourceManager( " Memcached.ClientLibrary.StringMessages " typeof (MemcachedClient).Assembly);
        
private   const   string  CLIENT_ERROR  =   " CLIENT_ERROR " ;
        
private   const   int  COMPRESS_THRESH  =   0x7800 ;
        
private   const   string  DELETED  =   " DELETED " ;
        
private   const   string  END  =   " END " ;
        
private   const   string  ERROR  =   " ERROR " ;
        
private   const   int  F_COMPRESSED  =   2 ;
        
private   const   int  F_SERIALIZED  =   8 ;
        
private   static  ILog log  =  LogManager.GetLogger( typeof (MemcachedClient));
        
private   const   string  NOTFOUND  =   " NOT_FOUND " ;
        
private   const   string  NOTSTORED  =   " NOT_STORED " ;
        
private   const   string  OK  =   " OK " ;
        
private   const   string  SERVER_ERROR  =   " SERVER_ERROR " ;
        
private   const   string  STATS  =   " STAT " ;
        
private   const   string  STORED  =   " STORED " ;
        
private   const   string  VALUE  =   " VALUE " ;

        
public  MemcachedClient():  this ( " default instance " )
        {
          
        } 
        
public  MemcachedClient( string  name)
        {
            
if  (name  !=   "" )
            {
                
this .Init(name);
            }
            
else
            {
                
this .Init();
            }
        }
        
private   void  Init( string  key)
        {
            
this ._primitiveAsString  =   false ;
            
this ._compressEnable  =   true ;
            
this ._compressThreshold  =   0x7800L ;
            
this ._defaultEncoding  =   " UTF-8 " ;
            
this ._poolName  =  GetLocalizedString(key);
        }
        
public   bool  Add( string  key,  object  value)
        {
            
return   this .Set( " add " , key, value, DateTime.MaxValue,  null this ._primitiveAsString);
        }

        
public   bool  Add( string  key,  object  value, DateTime expiry)
        {
            
return   this .Set( " add " , key, value, expiry,  null this ._primitiveAsString);
        }

        
public   bool  Add( string  key,  object  value,  int  hashCode)
        {
            
return   this .Set( " add " , key, value, DateTime.MaxValue, hashCode,  this ._primitiveAsString);
        }

        
public   bool  Add( string  key,  object  value, DateTime expiry,  int  hashCode)
        {
            
return   this .Set( " add " , key, value, expiry, hashCode,  this ._primitiveAsString);
        }

        
public   long  Decrement( string  key)
        {
            
return   this .IncrementOrDecrement( " decr " , key,  1L null );
        }

        
public   long  Decrement( string  key,  long  inc)
        {
            
return   this .IncrementOrDecrement( " decr " , key, inc,  null );
        }

        
public   long  Decrement( string  key,  long  inc,  int  hashCode)
        {
            
return   this .IncrementOrDecrement( " decr " , key, inc, hashCode);
        }

        
public   bool  Delete( string  key)
        {
            
return   this .Delete(key,  null , DateTime.MaxValue);
        }

        
public   bool  Delete( string  key, DateTime expiry)
        {
            
return   this .Delete(key,  null , expiry);
        }

        
public   bool  Delete( string  key,  object  hashCode, DateTime expiry)
        {
            
if  (key  ==   null )
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" null key delete " ));
                }
                
return   false ;
            }
            SockIO sock 
=  SockIOPool.GetInstance( this ._poolName).GetSock(key, hashCode);
            
if  (sock  !=   null )
            {
                StringBuilder builder 
=   new  StringBuilder( " delete  " ).Append(key);
                
if  (expiry  !=  DateTime.MaxValue)
                {
                    builder.Append(
"   "   +  (GetExpirationTime(expiry)  /   0x3e8 ));
                }
                builder.Append(
" \r\n " );
                
try
                {
                    sock.Write(Encoding.UTF8.GetBytes(builder.ToString()));
                    sock.Flush();
                    
string  newValue  =  sock.ReadLine();
                    
if  ( " DELETED "   ==  newValue)
                    {
                        
bool  isInfoEnabled  =  log.IsInfoEnabled;
                        sock.Close();
                        sock 
=   null ;
                        
return   true ;
                    }
                    
if  ( " NOT_FOUND "   ==  newValue)
                    {
                        
if  ( ! log.IsInfoEnabled)
                        {
                        }
                    }
                    
else   if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" delete key error " ).Replace( " $$Key$$ " , key).Replace( " $$Line$$ " , newValue));
                    }
                }
                
catch  (IOException exception)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" delete IOException " ), exception);
                    }
                    
try
                    {
                        sock.TrueClose();
                    }
                    
catch  (IOException exception2)
                    {
                        
if  (log.IsErrorEnabled)
                        {
                            log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , sock.ToString()), exception2);
                        }
                    }
                    sock 
=   null ;
                }
                
if  (sock  !=   null )
                {
                    sock.Close();
                }
            }
            
return   false ;
        }

        
public   bool  FlushAll()
        {
            
return   this .FlushAll( null );
        }

        
public   bool  FlushAll(ArrayList servers)
        {
            SockIOPool instance 
=  SockIOPool.GetInstance( this ._poolName);
            
if  (instance  ==   null )
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" unable to get socket pool " ));
                }
                
return   false ;
            }
            
if  (servers  ==   null )
            {
                servers 
=  instance.Servers;
            }
            
if  ((servers  ==   null ||  (servers.Count  <=   0 ))
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" flushall no servers " ));
                }
                
return   false ;
            }
            
bool  flag  =   true ;
            
for  ( int  i  =   0 ; i  <  servers.Count; i ++ )
            {
                SockIO connection 
=  instance.GetConnection(( string ) servers[i]);
                
if  (connection  ==   null )
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" unable to connect " ).Replace( " $$Server$$ " , servers[i].ToString()));
                    }
                    flag 
=   false ;
                }
                
else
                {
                    
string  s  =   " flush_all\r\n " ;
                    
try
                    {
                        connection.Write(Encoding.UTF8.GetBytes(s));
                        connection.Flush();
                        
string  str2  =  connection.ReadLine();
                        flag 
=  ( " OK "   ==  str2)  ?  flag :  false ;
                    }
                    
catch  (IOException exception)
                    {
                        
if  (log.IsErrorEnabled)
                        {
                            log.Error(GetLocalizedString(
" flushall IOException " ), exception);
                        }
                        
try
                        {
                            connection.TrueClose();
                        }
                        
catch  (IOException exception2)
                        {
                            
if  (log.IsErrorEnabled)
                            {
                                log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , connection.ToString()), exception2);
                            }
                        }
                        flag 
=   false ;
                        connection 
=   null ;
                    }
                    
if  (connection  !=   null )
                    {
                        connection.Close();
                    }
                }
            }
            
return  flag;
        }

        
public   object  Get( string  key)
        {
            
return   this .Get(key,  null false );
        }

        
public   object  Get( string  key,  int  hashCode)
        {
            
return   this .Get(key, hashCode,  false );
        }

        
public   object  Get( string  key,  object  hashCode,  bool  asString)
        {
            SockIO sock 
=  SockIOPool.GetInstance( this ._poolName).GetSock(key, hashCode);
            
if  (sock  !=   null )
            {
                
try
                {
                    
string  s  =   " get  "   +  key  +   " \r\n " ;
                    
bool  isDebugEnabled  =  log.IsDebugEnabled;
                    sock.Write(Encoding.UTF8.GetBytes(s));
                    sock.Flush();
                    Hashtable hm 
=   new  Hashtable();
                    
this .LoadItems(sock, hm, asString);
                    
bool  flag2  =  log.IsDebugEnabled;
                    sock.Close();
                    
return  hm[key];
                }
                
catch  (IOException exception)
                { 
                    
// ##监测##
                    
// exception.Message=无法将数据写入传输连接: 远程主机强迫关闭了一个现有的连接。。
                    
// 原因:memcached重启类造成的连接池无法再通信的错误
                    
// 解决:判断上面的message出现次数几次,就考虑重新建立连接池
                     if  (exception.Message.Contains( " 无法将数据写入传输连接: 远程主机强迫关闭了一个现有的连接 " ))
                    {
                       MemcachedSocksMonitor.SockIOErrRestatr();
                    }
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" get IOException " ).Replace( " $$Key$$ " , key), exception);
                    }
                    
try
                    {
                        sock.TrueClose();
                    }
                    
catch  (IOException exception2)
                    {
                        
if  (log.IsErrorEnabled)
                        {
                            log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , sock.ToString()), exception2);
                        }
                    }
                    sock 
=   null ;
                }
                
if  (sock  !=   null )
                {
                    sock.Close();
                }
            }
            
return   null ;
        }

        
public   long  GetCounter( string  key)
        {
            
return   this .GetCounter(key,  null );
        }

        
public   long  GetCounter( string  key,  object  hashCode)
        {
            
if  (key  ==   null )
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" getcounter null key " ));
                }
                
return   - 1L ;
            }
            
long  num  =   - 1L ;
            
try
            {
                num 
=   long .Parse(( string this .Get(key, hashCode,  true ),  new  NumberFormatInfo());
            }
            
catch  (ArgumentException)
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" getcounter counter not found " ).Replace( " $$Key$$ " , key));
                }
            }
            
return  num;
        }

        
private   static   int  GetExpirationTime(DateTime expiration)
        {
            
if  (expiration  <=  DateTime.Now)
            {
                
return   0 ;
            }
            TimeSpan span 
=   new  TimeSpan( 0x1d 0x17 0x3b 0x3b );
            
if  (expiration.Subtract(DateTime.Now)  >  span)
            {
                
return  ( int ) span.TotalSeconds;
            }
            
return  ( int ) expiration.Subtract(DateTime.Now).TotalSeconds;
        }

        
private   static   string  GetLocalizedString( string  key)
        {
            
if  (key  !=   " default instance " )
            {
                
return  key;
            }
            
else
            {
                
return  _resourceManager.GetString(key);
            }
        }

        
public  Hashtable GetMultiple( string [] keys)
        {
            
return   this .GetMultiple(keys,  null false );
        }

        
public  Hashtable GetMultiple( string [] keys,  int [] hashCodes)
        {
            
return   this .GetMultiple(keys, hashCodes,  false );
        }

        
public  Hashtable GetMultiple( string [] keys,  int [] hashCodes,  bool  asString)
        {
            
if  (keys  ==   null )
            {
                
return   new  Hashtable();
            }
            Hashtable hashtable 
=   new  Hashtable();
            
for  ( int  i  =   0 ; i  <  keys.Length; i ++ )
            {
                
object  hashCode  =   null ;
                
if  ((hashCodes  !=   null &&  (hashCodes.Length  >  i))
                {
                    hashCode 
=  hashCodes[i];
                }
                SockIO sock 
=  SockIOPool.GetInstance( this ._poolName).GetSock(keys[i], hashCode);
                
if  (sock  !=   null )
                {
                    
if  ( ! hashtable.ContainsKey(sock.Host))
                    {
                        hashtable[sock.Host] 
=   new  StringBuilder();
                    }
                    ((StringBuilder) hashtable[sock.Host]).Append(
"   "   +  keys[i]);
                    sock.Close();
                }
            }
            
bool  isInfoEnabled  =  log.IsInfoEnabled;
            Hashtable hm 
=   new  Hashtable();
            ArrayList list 
=   new  ArrayList();
            
foreach  ( string  str  in  hashtable.Keys)
            {
                SockIO connection 
=  SockIOPool.GetInstance( this ._poolName).GetConnection(str);
                
try
                {
                    
string  s  =   " get "   +  ((StringBuilder) hashtable[str])  +   " \r\n " ;
                    
bool  flag2  =  log.IsDebugEnabled;
                    connection.Write(Encoding.UTF8.GetBytes(s));
                    connection.Flush();
                    
this .LoadItems(connection, hm, asString);
                }
                
catch  (IOException exception)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" getmultiple IOException " ), exception);
                    }
                    list.Add(str);
                    
try
                    {
                        connection.TrueClose();
                    }
                    
catch  (IOException exception2)
                    {
                        
if  (log.IsErrorEnabled)
                        {
                            log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , connection.ToString()), exception2);
                        }
                    }
                    connection 
=   null ;
                }
                
if  (connection  !=   null )
                {
                    connection.Close();
                }
            }
            
foreach  ( string  str3  in  list)
            {
                hashtable.Remove(str3);
            }
            
bool  isDebugEnabled  =  log.IsDebugEnabled;
            
return  hm;
        }

        
public   object [] GetMultipleArray( string [] keys)
        {
            
return   this .GetMultipleArray(keys,  null false );
        }

        
public   object [] GetMultipleArray( string [] keys,  int [] hashCodes)
        {
            
return   this .GetMultipleArray(keys, hashCodes,  false );
        }

        
public   object [] GetMultipleArray( string [] keys,  int [] hashCodes,  bool  asString)
        {
            
if  (keys  ==   null )
            {
                
return   new   object [ 0 ];
            }
            Hashtable hashtable 
=   this .GetMultiple(keys, hashCodes, asString);
            
object [] objArray  =   new   object [keys.Length];
            
for  ( int  i  =   0 ; i  <  keys.Length; i ++ )
            {
                objArray[i] 
=  hashtable[keys[i]];
            }
            
return  objArray;
        }

        
public   long  Increment( string  key)
        {
            
return   this .IncrementOrDecrement( " incr " , key,  1L null );
        }

        
public   long  Increment( string  key,  long  inc)
        {
            
return   this .IncrementOrDecrement( " incr " , key, inc,  null );
        }

        
public   long  Increment( string  key,  long  inc,  int  hashCode)
        {
            
return   this .IncrementOrDecrement( " incr " , key, inc, hashCode);
        }

        
private   long  IncrementOrDecrement( string  cmdname,  string  key,  long  inc,  object  hashCode)
        {
            SockIO sock 
=  SockIOPool.GetInstance( this ._poolName).GetSock(key, hashCode);
            
if  (sock  !=   null )
            {
                
try
                {
                    
string  s  =   string .Concat( new   object [] { cmdname,  "   " , key,  "   " , inc,  " \r\n "  });
                    
bool  isDebugEnabled  =  log.IsDebugEnabled;
                    sock.Write(Encoding.UTF8.GetBytes(s));
                    sock.Flush();
                    
string  input  =  sock.ReadLine();
                    
if  ( new  Regex( @" \d+ " ).Match(input).Success)
                    {
                        sock.Close();
                        
return   long .Parse(input,  new  NumberFormatInfo());
                    }
                    
if  ( " NOT_FOUND "   ==  input)
                    {
                        
if  ( ! log.IsInfoEnabled)
                        {
                        }
                    }
                    
else   if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" incr-decr key error " ).Replace( " $$Key$$ " , key));
                    }
                }
                
catch  (IOException exception)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" incr-decr IOException " ), exception);
                    }
                    
try
                    {
                        sock.TrueClose();
                    }
                    
catch  (IOException)
                    {
                        
if  (log.IsErrorEnabled)
                        {
                            log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , sock.ToString()));
                        }
                    }
                    sock 
=   null ;
                }
                
if  (sock  !=   null )
                {
                    sock.Close();
                }
            }
            
return   - 1L ;
        }

        
private   void  Init()
        {
            
this ._primitiveAsString  =   false ;
            
this ._compressEnable  =   true ;
            
this ._compressThreshold  =   0x7800L ;
            
this ._defaultEncoding  =   " UTF-8 " ;
            
this ._poolName  =  GetLocalizedString( " default instance " );
        }

        
public   bool  KeyExists( string  key)
        {
            
return  ( this .Get(key,  null true !=   null );
        }

        
private   void  LoadItems(SockIO sock, Hashtable hm,  bool  asString)
        {
            
string  str;
            
object  obj2;
        Label_0000:
            str 
=  sock.ReadLine();
            
bool  isDebugEnabled  =  log.IsDebugEnabled;
            
if  ( ! str.StartsWith( " VALUE " ))
            {
                
if  ( " END "   ==  str)
                {
                    
if  (log.IsDebugEnabled)
                    {
                    }
                    
return ;
                }
                
goto  Label_0000;
            }
            
string [] strArray  =  str.Split( new   char [] {  '   '  });
            
string  newValue  =  strArray[ 1 ];
            
int  num  =   int .Parse(strArray[ 2 ],  new  NumberFormatInfo());
            
int  num2  =   int .Parse(strArray[ 3 ],  new  NumberFormatInfo());
            
bool  flag2  =  log.IsDebugEnabled;
            
byte [] bytes  =   new   byte [num2];
            sock.Read(bytes);
            sock.ClearEndOfLine();
            
if  ((num  &   2 !=   0 )
            {
                
try
                {
                    
int  num3;
                    GZipInputStream stream 
=   new  GZipInputStream( new  MemoryStream(bytes));
                    MemoryStream stream2 
=   new  MemoryStream(bytes.Length);
                    
byte [] buffer  =   new   byte [ 0x800 ];
                    
while  ((num3  =  stream.Read(buffer,  0 , buffer.Length))  >   0 )
                    {
                        stream2.Write(buffer, 
0 , num3);
                    }
                    bytes 
=  stream2.ToArray();
                    stream.Close();
                }
                
catch  (IOException exception)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" loaditems uncompression IOException " ).Replace( " $$Key$$ " , newValue), exception);
                    }
                    
throw   new  IOException(GetLocalizedString( " loaditems uncompression IOException " ).Replace( " $$Key$$ " , newValue), exception);
                }
            }
            
if  ((num  &   8 ==   0 )
            {
                
if  ( this ._primitiveAsString  ||  asString)
                {
                    
bool  isInfoEnabled  =  log.IsInfoEnabled;
                    obj2 
=  Encoding.GetEncoding( this ._defaultEncoding).GetString(bytes);
                    
goto  Label_022A;
                }
                
try
                {
                    obj2 
=  NativeHandler.Decode(bytes);
                    
goto  Label_022A;
                }
                
catch  (Exception exception2)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" loaditems deserialize error " ).Replace( " $$Key$$ " , newValue), exception2);
                    }
                    
throw   new  IOException(GetLocalizedString( " loaditems deserialize error " ).Replace( " $$Key$$ " , newValue), exception2);
                }
            }
            
try
            {
                MemoryStream serializationStream 
=   new  MemoryStream(bytes);
                obj2 
=   new  BinaryFormatter().Deserialize(serializationStream);
                
bool  flag4  =  log.IsInfoEnabled;
            }
            
catch  (SerializationException exception3)
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" loaditems SerializationException " ).Replace( " $$Key$$ " , newValue), exception3);
                }
                
throw   new  IOException(GetLocalizedString( " loaditems SerializationException " ).Replace( " $$Key$$ " , newValue), exception3);
            }
        Label_022A:
            hm[newValue] 
=  obj2;
            
goto  Label_0000;
        }

        
public   bool  Replace( string  key,  object  value)
        {
            
return   this .Set( " replace " , key, value, DateTime.MaxValue,  null this ._primitiveAsString);
        }

        
public   bool  Replace( string  key,  object  value, DateTime expiry)
        {
            
return   this .Set( " replace " , key, value, expiry,  null this ._primitiveAsString);
        }

        
public   bool  Replace( string  key,  object  value,  int  hashCode)
        {
            
return   this .Set( " replace " , key, value, DateTime.MaxValue, hashCode,  this ._primitiveAsString);
        }

        
public   bool  Replace( string  key,  object  value, DateTime expiry,  int  hashCode)
        {
            
return   this .Set( " replace " , key, value, expiry, hashCode,  this ._primitiveAsString);
        }

        
public   bool  Set( string  key,  object  value)
        {
            
return   this .Set( " set " , key, value, DateTime.MaxValue,  null this ._primitiveAsString);
        }

        
public   bool  Set( string  key,  object  value, DateTime expiry)
        {
            
return   this .Set( " set " , key, value, expiry,  null this ._primitiveAsString);
        }

        
public   bool  Set( string  key,  object  value,  int  hashCode)
        {
            
return   this .Set( " set " , key, value, DateTime.MaxValue, hashCode,  this ._primitiveAsString);
        }

        
public   bool  Set( string  key,  object  value, DateTime expiry,  int  hashCode)
        {
            
return   this .Set( " set " , key, value, expiry, hashCode,  this ._primitiveAsString);
        }

        
private   bool  Set( string  cmdname,  string  key,  object  obj, DateTime expiry,  object  hashCode,  bool  asString)
        {
            
byte [] bytes;
            
if  (expiry  <  DateTime.Now)
            {
                
return   true ;
            }
            
if  (((cmdname  ==   null ||  (cmdname.Trim().Length  ==   0 ))  ||  ((key  ==   null ||  (key.Length  ==   0 )))
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" set key null " ));
                }
                
return   false ;
            }
            SockIO sock 
=  SockIOPool.GetInstance( this ._poolName).GetSock(key, hashCode);
            
if  (sock  ==   null )
            {
                
return   false ;
            }
            
if  (expiry  ==  DateTime.MaxValue)
            {
                expiry 
=   new  DateTime( 0L );
            }
            
int  num  =   0 ;
            
int  count  =   0 ;
            
if  (NativeHandler.IsHandled(obj))
            {
                
if  (asString)
                {
                    
if  (obj  !=   null )
                    {
                        
bool  flag1  =  log.IsInfoEnabled;
                        
try
                        {
                            bytes 
=  Encoding.UTF8.GetBytes(obj.ToString());
                            count 
=  bytes.Length;
                            
goto  Label_01DF;
                        }
                        
catch  (ArgumentException exception)
                        {
                            
if  (log.IsErrorEnabled)
                            {
                                log.Error(GetLocalizedString(
" set invalid encoding " ).Replace( " $$Encoding$$ " this ._defaultEncoding), exception);
                            }
                            sock.Close();
                            sock 
=   null ;
                            
return   false ;
                        }
                    }
                    bytes 
=   new   byte [ 0 ];
                    count 
=   0 ;
                    
goto  Label_01DF;
                }
                
bool  isInfoEnabled  =  log.IsInfoEnabled;
                
try
                {
                    bytes 
=  NativeHandler.Encode(obj);
                    count 
=  bytes.Length;
                    
goto  Label_01DF;
                }
                
catch  (ArgumentException exception2)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" set failed to native handle object " ), exception2);
                    }
                    sock.Close();
                    sock 
=   null ;
                    
return   false ;
                }
            }
            
if  (obj  !=   null )
            {
                
bool  flag3  =  log.IsInfoEnabled;
                
try
                {
                    MemoryStream serializationStream 
=   new  MemoryStream();
                    
new  BinaryFormatter().Serialize(serializationStream, obj);
                    bytes 
=  serializationStream.GetBuffer();
                    count 
=  ( int ) serializationStream.Length;
                    num 
|=   8 ;
                    
goto  Label_01DF;
                }
                
catch  (IOException exception3)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" set failed to serialize " ).Replace( " $$Object$$ " , obj.ToString()), exception3);
                    }
                    sock.Close();
                    sock 
=   null ;
                    
return   false ;
                }
            }
            bytes 
=   new   byte [ 0 ];
            count 
=   0 ;
        Label_01DF:
            
if  ( this ._compressEnable  &&  (count  >   this ._compressThreshold))
            {
                
bool  flag4  =  log.IsInfoEnabled;
                
try
                {
                    MemoryStream baseOutputStream 
=   new  MemoryStream();
                    GZipOutputStream stream3 
=   new  GZipOutputStream(baseOutputStream);
                    stream3.Write(bytes, 
0 , count);
                    stream3.Finish();
                    bytes 
=  baseOutputStream.GetBuffer();
                    count 
=  ( int ) baseOutputStream.Length;
                    num 
|=   2 ;
                    
bool  flag5  =  log.IsInfoEnabled;
                }
                
catch  (IOException exception4)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" set compression failure " ), exception4);
                    }
                }
            }
            
try
            {
                
string  s  =   string .Concat( new   object [] { cmdname,  "   " , key,  "   " , num,  "   " , GetExpirationTime(expiry),  "   " , count,  " \r\n "  });
                sock.Write(Encoding.UTF8.GetBytes(s));
                sock.Write(bytes, 
0 , count);
                sock.Write(Encoding.UTF8.GetBytes(
" \r\n " ));
                sock.Flush();
                
string  newValue  =  sock.ReadLine();
                
bool  flag6  =  log.IsInfoEnabled;
                
if  ( " STORED "   ==  newValue)
                {
                    
bool  flag7  =  log.IsInfoEnabled;
                    sock.Close();
                    sock 
=   null ;
                    
return   true ;
                }
                
if  ( " NOT_STORED "   ==  newValue)
                {
                    
if  ( ! log.IsInfoEnabled)
                    {
                    }
                }
                
else   if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" set error " ).Replace( " $$Key$$ " , key).Replace( " $$Size$$ " , count.ToString( new  NumberFormatInfo())).Replace( " $$Line$$ " , newValue));
                }
            }
            
catch  (IOException exception5)
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" set IOException " ), exception5);
                }
                
// ##监测##
                
// exception.Message=无法将数据写入传输连接: 远程主机强迫关闭了一个现有的连接。。
                
// 原因:memcached重启类造成的连接池无法再通信的错误
                
// 解决:判断上面的message出现次数几次,就考虑重新建立连接池
                 if  (exception5.Message.Contains( " 无法将数据写入传输连接: 远程主机强迫关闭了一个现有的连接 " ))
                {
                    MemcachedSocksMonitor.SockIOErrRestatr();
                }
                
try
                {
                    sock.TrueClose();
                }
                
catch  (IOException exception6)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , sock.ToString()), exception6);
                    }
                }
                sock 
=   null
            }
            
if  (sock  !=   null )
            {
                sock.Close();
            }
            
return   false ;
        }

        
public  Hashtable Stats()
        {
            
return   this .Stats( null );
        }

        
public  Hashtable Stats(ArrayList servers)
        {
            SockIOPool instance 
=  SockIOPool.GetInstance( this ._poolName);
            
if  (instance  ==   null )
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" unable to get socket pool " ));
                }
                
return   null ;
            }
            
if  (servers  ==   null )
            {
                servers 
=  instance.Servers;
            }
            
if  ((servers  ==   null ||  (servers.Count  <=   0 ))
            {
                
if  (log.IsErrorEnabled)
                {
                    log.Error(GetLocalizedString(
" stats no servers " ));
                }
                
return   null ;
            }
            Hashtable hashtable 
=   new  Hashtable();
            
for  ( int  i  =   0 ; i  <  servers.Count; i ++ )
            {
                SockIO connection 
=  instance.GetConnection(( string ) servers[i]);
                
if  (connection  ==   null )
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" unable to connect " ).Replace( " $$Server$$ " , servers[i].ToString()));
                    }
                    
continue ;
                }
                
string  s  =   " stats\r\n " ;
                
try
                {
                    connection.Write(Encoding.UTF8.GetBytes(s));
                    connection.Flush();
                    Hashtable hashtable2 
=   new  Hashtable();
                    
while  ( true )
                    {
                        
string  str2  =  connection.ReadLine();
                        
bool  isDebugEnabled  =  log.IsDebugEnabled;
                        
if  (str2.StartsWith( " STAT " ))
                        {
                            
string [] strArray  =  str2.Split( new   char [] {  '   '  });
                            
string  str3  =  strArray[ 1 ];
                            
string  str4  =  strArray[ 2 ];
                            
bool  flag2  =  log.IsDebugEnabled;
                            hashtable2[str3] 
=  str4;
                        }
                        
else   if  ( " END "   ==  str2)
                        {
                            
if  ( ! log.IsDebugEnabled)
                            {
                            }
                            
goto  Label_01E4;
                        }
                        hashtable[servers[i]] 
=  hashtable2;
                    }
                }
                
catch  (IOException exception)
                {
                    
if  (log.IsErrorEnabled)
                    {
                        log.Error(GetLocalizedString(
" stats IOException " ), exception);
                    }
                    
try
                    {
                        connection.TrueClose();
                    }
                    
catch  (IOException)
                    {
                        
if  (log.IsErrorEnabled)
                        {
                            log.Error(GetLocalizedString(
" failed to close some socket " ).Replace( " $$Socket$$ " , connection.ToString()));
                        }
                    }
                    connection 
=   null ;
                }
            Label_01E4:
                
if  (connection  !=   null )
                {
                    connection.Close();
                }
            }
            
return  hashtable;
        }

        
public   bool  StoreCounter( string  key,  long  counter)
        {
            
return   this .Set( " set " , key, counter, DateTime.MaxValue,  null true );
        }

        
public   bool  StoreCounter( string  key,  long  counter,  int  hashCode)
        {
            
return   this .Set( " set " , key, counter, DateTime.MaxValue, hashCode,  true );
        }

        
public   long  CompressionThreshold
        {
            
get
            {
                
return   this ._compressThreshold;
            }
            
set
            {
                
this ._compressThreshold  =  value;
            }
        }

        
public   string  DefaultEncoding
        {
            
get
            {
                
return   this ._defaultEncoding;
            }
            
set
            {
                
this ._defaultEncoding  =  value;
            }
        }

        
public   bool  EnableCompression
        {
            
get
            {
                
return   this ._compressEnable;
            }
            
set
            {
                
this ._compressEnable  =  value;
            }
        }

        
public   string  PoolName
        {
            
get
            {
                
return   this ._poolName;
            }
            
set
            {
                
this ._poolName  =  value;
            }
        }

        
public   bool  PrimitiveAsString
        {
            
get
            {
                
return   this ._primitiveAsString;
            }
            
set
            {
                
this ._primitiveAsString  =  value;
            }
        }
    }
}

大致就以上内容,修改的地方也不算多,总结发现自己写博文很吃力,平时的缺点很明显,不知道如何去描述一个问题及解决方法,虽然自己都知道,但是就是表达不出来

这文章算是靠代码说话了,很惭愧,有兴趣的话就给点意见以及错误的地方

转载于:https://www.cnblogs.com/wyxy2005/archive/2010/08/23/1806785.html

猜你喜欢

转载自blog.csdn.net/weixin_33860147/article/details/94510659