乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Discuz!NT中集成Memcached分布式緩存

       leo.cn 2009-03-23

            大約在兩年前我寫過一篇關(guān)于Discuz!NT緩存架構(gòu)的文章,在那篇文章的結(jié)尾介紹了在IIS中如果開啟多個(gè)
      應(yīng)用程序池會(huì)造成多個(gè)緩存實(shí)例之間數(shù)據(jù)同步的問題。雖然給出了一個(gè)解決方案,但無形中卻把壓力轉(zhuǎn)移到了
      磁盤I/O上(多個(gè)進(jìn)程并發(fā)訪問cache.config文件)。其實(shí)從那時(shí)起我就開始關(guān)注有什么更好的方案,當(dāng)然今
      天本文中所說的Memcached,以及Velocity等這類的分布式緩存方案之前都考慮過,但一直未能決定該使用那
      個(gè)。起碼Velocity要在.net 4.0之后才會(huì)提供,雖然是原生態(tài),但有些遠(yuǎn)水解不了近火。

            我想真正等到Velocity能堪當(dāng)重任還要等上一段時(shí)間。于是我就開始將注意力轉(zhuǎn)移到了Memcached,必定
      有Facebook這只“超級(jí)小白鼠”使用它并且反響還不錯(cuò)。所以就開始嘗試動(dòng)手在產(chǎn)品中集成Memcached。

            其實(shí)在之前的那篇關(guān)于Discuz!NT緩存架構(gòu)的文章中已提到過,使用了設(shè)計(jì)模式中的“策略模式”來構(gòu)造。
      所以為了與以往使用緩存的代碼格式相兼容,所以這里采用新添加MemCachedStrategy(MemCached策略)
      來構(gòu)造一個(gè)緩存策略類以便于當(dāng)管理后臺(tái)開啟“MemCached”時(shí)以“MemCached策略模式”來做為當(dāng)前系統(tǒng)默認(rèn)
      的策略模式。

          其代碼段如下(Discuz.Cache/MemCached.cs):
          
      /// <summary>
      /// MemCache緩存策略類
      /// </summary>
      public class MemCachedStrategy : Discuz.Cache.ICacheStrategy
      {

          
      /// <summary>
          
      /// 添加指定ID的對(duì)象
          
      /// </summary>
          
      /// <param name="objId"></param>
          
      /// <param name="o"></param>
          public void AddObject(string objId, object o)
          {
              RemoveObject(objId);
              
      if (TimeOut > 0)
              {
                  MemCachedManager.CacheClient.Set(objId, o, System.DateTime.Now.AddMinutes(TimeOut));
              }
              
      else
              {
                  MemCachedManager.CacheClient.Set(objId, o);
              }
          }

          
      /// <summary>
          
      /// 添加指定ID的對(duì)象(關(guān)聯(lián)指定文件組)
          
      /// </summary>
          
      /// <param name="objId"></param>
          
      /// <param name="o"></param>
          
      /// <param name="files"></param>
          public void AddObjectWithFileChange(string objId, object o, string[] files)
          {
              ;
          }

          
      /// <summary>
          
      /// 添加指定ID的對(duì)象(關(guān)聯(lián)指定鍵值組)
          
      /// </summary>
          
      /// <param name="objId"></param>
          
      /// <param name="o"></param>
          
      /// <param name="dependKey"></param>
          public void AddObjectWithDepend(string objId, object o, string[] dependKey)
          {
              ;
          }

          
      /// <summary>
          
      /// 移除指定ID的對(duì)象
          
      /// </summary>
          
      /// <param name="objId"></param>
          public void RemoveObject(string objId)
          {
              
      if (MemCachedManager.CacheClient.KeyExists(objId))
                  MemCachedManager.CacheClient.Delete(objId);
          }

          
      /// <summary>
          
      /// 返回指定ID的對(duì)象
          
      /// </summary>
          
      /// <param name="objId"></param>
          
      /// <returns></returns>
          public object RetrieveObject(string objId)
          {
              
      return MemCachedManager.CacheClient.Get(objId);
          }

          
      /// <summary>
          
      /// 到期時(shí)間
          
      /// </summary>
          public int TimeOut { setget; }
      }

          

          上面類實(shí)現(xiàn)的接口Discuz.Cache.ICacheStrategy定義如下:
          
       
      /// <summary>
       
      /// 公共緩存策略接口
       
      /// </summary>
       public interface ICacheStrategy
       {
           
      /// <summary>
           
      /// 添加指定ID的對(duì)象
           
      /// </summary>
           
      /// <param name="objId"></param>
           
      /// <param name="o"></param>
           void AddObject(string objId, object o);

           
      /// <summary>
           
      /// 添加指定ID的對(duì)象(關(guān)聯(lián)指定文件組)
           
      /// </summary>
           
      /// <param name="objId"></param>
           
      /// <param name="o"></param>
           
      /// <param name="files"></param>
           void AddObjectWithFileChange(string objId, object o, string[] files);

           
      /// <summary>
           
      /// 添加指定ID的對(duì)象(關(guān)聯(lián)指定鍵值組)
           
      /// </summary>
           
      /// <param name="objId"></param>
           
      /// <param name="o"></param>
           
      /// <param name="dependKey"></param>
           void AddObjectWithDepend(string objId, object o, string[] dependKey);

           
      /// <summary>
           
      /// 移除指定ID的對(duì)象
           
      /// </summary>
           
      /// <param name="objId"></param>
           void RemoveObject(string objId);

           
      /// <summary>
           
      /// 返回指定ID的對(duì)象
           
      /// </summary>
           
      /// <param name="objId"></param>
           
      /// <returns></returns>
           object RetrieveObject(string objId);

           
      /// <summary>
           
      /// 到期時(shí)間
           
      /// </summary>
           int TimeOut { set;get;}
      }


           當(dāng)然在MemCachedStrategy類中還有一個(gè)對(duì)象要加以說明,就是MemCachedManager,該類主要是對(duì)
      Memcached一些常操作和相關(guān)初始化實(shí)例調(diào)用的“封裝”,下面是是其變量定義和初始化構(gòu)造方法的代碼:

      /// <summary>
      /// MemCache管理操作類
      /// </summary>
      public sealed class MemCachedManager
      {
          
      #region 靜態(tài)方法和屬性
          
      private static MemcachedClient mc = null;

          
      private static SockIOPool pool = null;

          
      private static MemCachedConfigInfo memCachedConfigInfo = MemCachedConfigs.GetConfig();

          
      private static string [] serverList = null;

          
      static MemCachedManager()
          {
              CreateManager();
          }

          
      private static void CreateManager()
          {
              serverList 
      = Utils.SplitString(memCachedConfigInfo.ServerList, ""r"n");

              pool 
      = SockIOPool.GetInstance(memCachedConfigInfo.PoolName);
              pool.SetServers(serverList);
              pool.InitConnections 
      = memCachedConfigInfo.IntConnections;//初始化鏈接數(shù)
              pool.MinConnections = memCachedConfigInfo.MinConnections;//最少鏈接數(shù)
              pool.MaxConnections = memCachedConfigInfo.MaxConnections;//最大連接數(shù)
              pool.SocketConnectTimeout = memCachedConfigInfo.SocketConnectTimeout;//Socket鏈接超時(shí)時(shí)間
              pool.SocketTimeout = memCachedConfigInfo.SocketTimeout;// Socket超時(shí)時(shí)間
              pool.MaintenanceSleep = memCachedConfigInfo.MaintenanceSleep;//維護(hù)線程休息時(shí)間
              pool.Failover = memCachedConfigInfo.FailOver; //失效轉(zhuǎn)移(一種備份操作模式)
              pool.Nagle = memCachedConfigInfo.Nagle;//是否用nagle算法啟動(dòng)socket
              pool.HashingAlgorithm = HashingAlgorithm.NewCompatibleHash;
              pool.Initialize();
              

              mc 
      = new MemcachedClient();
              mc.PoolName 
      = memCachedConfigInfo.PoolName;
              mc.EnableCompression 
      = false;
          }

          
      /// <summary>
          
      /// 緩存服務(wù)器地址列表
          
      /// </summary>
          public static string[] ServerList
          {
              
      set
              {
                  
      if (value != null)
                      serverList 
      = value;
              }
              
      get { return serverList; }
          }

          
      /// <summary>
          
      /// 客戶端緩存操作對(duì)象
          
      /// </summary>
          public static MemcachedClient CacheClient
          {
              
      get
              {
                  
      if (mc == null)
                      CreateManager();

                  
      return mc;
              }
          }

          
      public static void Dispose()
          {
              
      if (pool != null)
                  pool.Shutdown();
          }
          

          
          上面代碼中構(gòu)造方法會(huì)初始化一個(gè)池來管理執(zhí)行Socket鏈接,并提供靜態(tài)屬性CacheClient以便MemCachedStrategy
      來調(diào)用。


          當(dāng)然我還在這個(gè)管理操作類中添加了幾個(gè)方法分別用于檢測當(dāng)前有效的分布式緩存服務(wù)器的列表,向指定(或全部)
      緩存服務(wù)器發(fā)送特定stats命令來獲取當(dāng)前緩存服務(wù)器上的數(shù)據(jù)信息和內(nèi)存分配信息等,相應(yīng)的方法如下(詳情見注釋):

      /// <summary>
      /// 獲取當(dāng)前緩存鍵值所存儲(chǔ)在的服務(wù)器
      /// </summary>
      /// <param name="key">當(dāng)前緩存鍵</param>
      /// <returns>當(dāng)前緩存鍵值所存儲(chǔ)在的服務(wù)器</returns>
      public static string GetSocketHost(string key)
      {
          
      string hostName = "";
          SockIO sock 
      = null;
          
      try
          {
              sock 
      = SockIOPool.GetInstance(memCachedConfigInfo.PoolName).GetSock(key);
              
      if (sock != null)
              {
                  hostName 
      = sock.Host;
              }
          }
          
      finally
          {
              
      if (sock != null)
                  sock.Close();
          }
          
      return hostName;
      }


      /// <summary>
      /// 獲取有效的服務(wù)器地址
      /// </summary>
      /// <returns>有效的服務(wù)器地</returns>
      public static string[] GetConnectedSocketHost()
      {
          SockIO sock 
      = null;
          
      string connectedHost = null;
          
      foreach (string hostName in serverList)
          {
              
      if (!Discuz.Common.Utils.StrIsNullOrEmpty(hostName))
              {
                  
      try
                  {
                      sock 
      = SockIOPool.GetInstance(memCachedConfigInfo.PoolName).GetConnection(hostName);
                      
      if (sock != null)
                      {
                          connectedHost 
      = Discuz.Common.Utils.MergeString(hostName, connectedHost);
                      }
                  }
                  
      finally
                  {
                      
      if (sock != null)
                          sock.Close();
                  }
              }
          }
          
      return Discuz.Common.Utils.SplitString(connectedHost, ",");
      }

      /// <summary>
      /// 獲取服務(wù)器端緩存的數(shù)據(jù)信息
      /// </summary>
      /// <returns>返回信息</returns>
      public static ArrayList GetStats()
      {
          ArrayList arrayList 
      = new ArrayList();
          
      foreach (string server in serverList)
          {
              arrayList.Add(server);
          }
          
      return GetStats(arrayList, Stats.Default, null);
      }

      /// <summary>
      /// 獲取服務(wù)器端緩存的數(shù)據(jù)信息
      /// </summary>
      /// <param name="serverArrayList">要訪問的服務(wù)列表</param>
      /// <returns>返回信息</returns>
      public static ArrayList GetStats(ArrayList serverArrayList, Stats statsCommand, string param)
      {
          ArrayList statsArray 
      = new ArrayList();
          param 
      =  Utils.StrIsNullOrEmpty(param) ? "" : param.Trim().ToLower();

          
      string commandstr = "stats";
          
      //轉(zhuǎn)換stats命令參數(shù)
          switch (statsCommand)
          {
              
      case Stats.Reset: { commandstr = "stats reset"break; }
              
      case Stats.Malloc: { commandstr = "stats malloc"break; }
              
      case Stats.Maps: { commandstr = "stats maps"break; }
              
      case Stats.Sizes: { commandstr = "stats sizes"break; }
              
      case Stats.Slabs: { commandstr = "stats slabs"break; }
              
      case Stats.Items: { commandstr = "stats"break; }
              
      case Stats.CachedDump:
              {
                  
      string[] statsparams = Utils.SplitString(param, " ");
                  
      if(statsparams.Length == 2)
                      
      if(Utils.IsNumericArray(statsparams))
                          commandstr 
      = "stats cachedump  " + param;

                  
      break;                     
              }
              
      case Stats.Detail:
                  {
                      
      if(string.Equals(param, "on"|| string.Equals(param, "off"|| string.Equals(param, "dump"))
                          commandstr 
      = "stats detail " + param.Trim();

                      
      break;
                  }
              
      default: { commandstr = "stats"break; }
          }
          
      //加載返回值
          Hashtable stats = MemCachedManager.CacheClient.Stats(serverArrayList, commandstr);
          
      foreach (string key in stats.Keys)
          {
              statsArray.Add(key);
              Hashtable values 
      = (Hashtable)stats[key];
              
      foreach (string key2 in values.Keys)
              {
                  statsArray.Add(key2 
      + ":" + values[key2]);
              }
          }
          
      return statsArray;
      }

      /// <summary>
      /// Stats命令行參數(shù)
      /// </summary>
      public enum Stats
      {
          
      /// <summary>
          
      /// stats : 顯示服務(wù)器信息, 統(tǒng)計(jì)數(shù)據(jù)等
          
      /// </summary>
          Default = 0,
          
      /// <summary>
          
      /// stats reset : 清空統(tǒng)計(jì)數(shù)據(jù)
          
      /// </summary>
          Reset = 1,
          
      /// <summary>
          
      /// stats malloc : 顯示內(nèi)存分配數(shù)據(jù)
          
      /// </summary>
          Malloc = 2,
          
      /// <summary>
          
      /// stats maps : 顯示"/proc/self/maps"數(shù)據(jù)
          
      /// </summary>
          Maps =3,
          
      /// <summary>
          
      /// stats sizes
          
      /// </summary>
          Sizes = 4,
          
      /// <summary>
          
      /// stats slabs : 顯示各個(gè)slab的信息,包括chunk的大小,數(shù)目,使用情況等
          
      /// </summary>
          Slabs = 5,
          
      /// <summary>
          
      /// stats items : 顯示各個(gè)slab中item的數(shù)目和最老item的年齡(最后一次訪問距離現(xiàn)在的秒數(shù))
          
      /// </summary>
          Items = 6,
          
      /// <summary>
          
      /// stats cachedump slab_id limit_num : 顯示某個(gè)slab中的前 limit_num 個(gè) key 列表
          
      /// </summary>
          CachedDump =7,
          
      /// <summary>
          
      /// stats detail [on|off|dump] : 設(shè)置或者顯示詳細(xì)操作記錄   on:打開詳細(xì)操作記錄  off:關(guān)閉詳細(xì)操作記錄 dump: 顯示詳細(xì)操作記錄(每一個(gè)鍵值get,set,hit,del的次數(shù))
          
      /// </summary>
          Detail = 8
      }



          當(dāng)然在配置初始化緩存鏈接池時(shí)使用了配置文件方式(memcached.config)來管理相關(guān)參數(shù),其info信息
      類說明如下(Discuz.Config/MemCachedConfigInfo.cs):

      /// <summary>
      /// MemCached配置信息類文件
      /// </summary>
      public class MemCachedConfigInfo : IConfigInfo
      {
          
      private bool _applyMemCached;
          
      /// <summary>
          
      /// 是否應(yīng)用MemCached
          
      /// </summary>
          public bool ApplyMemCached
          {
              
      get
              {
                  
      return _applyMemCached;
              }
              
      set
              {
                  _applyMemCached 
      = value;
              }
          }

          
      private string _serverList;
          
      /// <summary>
          
      /// 鏈接地址
          
      /// </summary>
          public string ServerList
          {
              
      get
              {
                  
      return _serverList;
              }
              
      set
              {
                  _serverList 
      = value;
              }
          }

          
      private string _poolName;
          
      /// <summary>
          
      /// 鏈接池名稱
          
      /// </summary>
          public string PoolName
          {
              
      get
              {
                  
      return Utils.StrIsNullOrEmpty(_poolName) ? "DiscuzNT_MemCache" : _poolName;
              }
              
      set
              {
                  _poolName 
      = value;
              }
          }

          
      private int _intConnections;
          
      /// <summary>
          
      /// 初始化鏈接數(shù)
          
      /// </summary>
          public int IntConnections
          {
              
      get
              {
                  
      return _intConnections > 0 ? _intConnections : 3;
              }
              
      set
              {
                  _intConnections 
      = value;
              }
          }

          
      private int _minConnections;
          
      /// <summary>
          
      /// 最少鏈接數(shù)
          
      /// </summary>
          public int MinConnections
          {
              
      get
              {
                  
      return _minConnections > 0 ? _minConnections : 3;
              }
              
      set
              {
                  _minConnections 
      = value;
              }
          }

          
      private int _maxConnections;
          
      /// <summary>
          
      /// 最大連接數(shù)
          
      /// </summary>
          public int MaxConnections
          {
              
      get
              {
                  
      return _maxConnections > 0 ?_maxConnections : 5;
              }
              
      set
              {
                  _maxConnections 
      = value;
              }
          }

          
      private int _socketConnectTimeout;
          
      /// <summary>
          
      /// Socket鏈接超時(shí)時(shí)間
          
      /// </summary>
          public int SocketConnectTimeout
          {
              
      get
              {
                  
      return _socketConnectTimeout > 1000 ? _socketConnectTimeout : 1000;
              }
              
      set
              {
                  _socketConnectTimeout 
      = value;
              }
          }

          
      private int _socketTimeout;
          
      /// <summary>
          
      /// socket超時(shí)時(shí)間
          
      /// </summary>
          public int SocketTimeout
          {
              
      get
              {
                  
      return _socketTimeout > 1000 ? _maintenanceSleep : 3000;
              }
              
      set
              {
                  _socketTimeout 
      = value;
              }
          }

          
      private int _maintenanceSleep;
          
      /// <summary>
          
      /// 維護(hù)線程休息時(shí)間
          
      /// </summary>
          public int MaintenanceSleep
          {
              
      get
              {
                  
      return _maintenanceSleep > 0 ? _maintenanceSleep : 30;
              }
              
      set
              {
                  _maintenanceSleep 
      = value;
              }
          }

          
      private bool _failOver;
          
      /// <summary>
          
      /// 鏈接失敗后是否重啟,詳情參見http://baike.baidu.com/view/1084309.htm
          
      /// </summary>
          public bool FailOver
          {
              
      get
              {
                  
      return _failOver;
              }
              
      set
              {
                  _failOver 
      = value;
              }
          }

          
      private bool _nagle;
          
      /// <summary>
          
      /// 是否用nagle算法啟動(dòng)socket
          
      /// </summary>
          public bool Nagle
          {
              
      get
              {
                  
      return _nagle;
              }
              
      set
              {
                  _nagle 
      = value;
              }
          }
      }     



           這些參數(shù)我們通過注釋應(yīng)該有一些了解,可以說memcached的主要性能都是通過這些參數(shù)來決定的,大家
      應(yīng)根據(jù)自己公司產(chǎn)品和應(yīng)用的實(shí)際情況配置相應(yīng)的數(shù)值。

           當(dāng)然,做完這一步之后就是對(duì)調(diào)用“緩存策略”的主體類進(jìn)行修改來,使其根據(jù)對(duì)管理后臺(tái)的設(shè)計(jì)來決定
      加載什么樣的緩存策略,如下:

      /// <summary>
      /// Discuz!NT緩存類
      /// 對(duì)Discuz!NT論壇緩存進(jìn)行全局控制管理
      /// </summary>
      public class DNTCache
      {
          .
          
          
      //通過該變量決定是否啟用MemCached
          private static bool applyMemCached = MemCachedConfigs.GetConfig().ApplyMemCached;     

          
      /// <summary>
          
      /// 構(gòu)造函數(shù)
          
      /// </summary>
          private DNTCache()
          {
              
      if (applyMemCached)
                  cs 
      = new MemCachedStrategy();
              
      else
              {
                  cs 
      = new DefaultCacheStrategy();

                  objectXmlMap 
      = rootXml.CreateElement("Cache");
                  
      //建立內(nèi)部XML文檔.
                  rootXml.AppendChild(objectXmlMap);

                  
      //LogVisitor clv = new CacheLogVisitor();
                  
      //cs.Accept(clv);

                  cacheConfigTimer.AutoReset 
      = true;
                  cacheConfigTimer.Enabled 
      = true;
                  cacheConfigTimer.Elapsed 
      += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
                  cacheConfigTimer.Start();
              }
          }
          
          

          
          到這里,主要的開發(fā)和修改基本上就告一段落了。下面開始介紹一下如果使用Stats命令來查看緩存的
      分配和使用等情況。之前在枚舉類型Stats中看到該命令有幾個(gè)主要的參數(shù),分別是:
       
          stats
          stats reset
          stats malloc
          stats maps
          stats sizes
          stats slabs
          stats items
          stats cachedump slab_id limit_num
          stats detail [on|off|dump]
          
          而JAVAEYE的 robbin 寫過一篇文章:貼一段遍歷memcached緩存對(duì)象的小腳本,來介紹如何使用其中的  
      “stats cachedump”來獲取信息。受這篇文章的啟發(fā),我將MemCachedClient.cs文件中的Stats方法加以修
      改,添加了一個(gè)command參數(shù)(字符串型),這樣就可以向緩存服務(wù)器發(fā)送上面所說的那幾種類型的命令了。

          測試代碼如下:
          
      protected void Submit_Click(object sender, EventArgs e)
      {
          ArrayList arrayList 
      = new ArrayList();
          arrayList.Add(
      "10.0.1.52:11211");//緩存服務(wù)器的地址

          StateResult.DataSource 
      = MemCachedManager.GetStats(arrayList, (MemCachedManager.Stats)         
                                           Utils.StrToInt(StatsParam.SelectedValue, 
      0), Param.Text);
          StateResult.DataBind();            
      }


          頁面代碼如下:
          
         

         

          

           我這樣做的目的有兩個(gè),一個(gè)是避免每次都使用telnet協(xié)議遠(yuǎn)程登陸緩存服務(wù)器并輸入相應(yīng)的命令行
      參數(shù)(我記憶力不好,參數(shù)多了之后就愛忘)。二是將來會(huì)把這個(gè)頁面功能內(nèi)置到管理后臺(tái)上,以便后臺(tái)
      管理員可以動(dòng)態(tài)監(jiān)測每臺(tái)緩存服務(wù)器上的數(shù)據(jù)。


           好了,到這里今天的內(nèi)容就差不多了。在本文中我們看到了使用設(shè)計(jì)模式的好處,通過它我們可以讓
      自己寫的代碼支持“變化”。這里不妨再多說幾句,大家看到了velocity在使用上也是很方便,如果可以
      的話,未來可以也會(huì)將velocity做成一個(gè)“緩存策略”,這樣站長或管理員就可以根據(jù)自己公司的實(shí)際情
      況來加以靈活配置了。
          
          
            

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請遵守用戶 評(píng)論公約