memcached缓存服务器.net开发应用

本文介绍Memcached缓存系统的配置与应用,包括环境搭建、Web.config配置、log4net日志初始化、缓存读写类设计、缓存与数据库交互流程、数据集转JSON以及WebService调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

要点

  memcached, Enyim, log4net, Newtonsoft.Json

 一 环境
   注意Enyim,log4net,memcached的版本,如果与下面不一至,调试运行中有可能出现问题

1.memcached客户端
   Enyim.Caching.dll  v2.12.0.0
   Enyim.Caching.Log4NetAdapter.dll  v2.12.0.0
   log4net.dll   v1.2.10.0
2.memcached服务端
   memcached-win32  v1.4.4-14
3.数据输出及提供
   数据输出格式:json
   数据提供:WebService
4.dataSet转json
   组件:Newtonsoft.Json.dll  v4.0.8.14612 
5.开发工具
   visual studio 2010
6.dotNet
   开发版本:.net  v3.5
   运行版本:.net  v2.0.50727

二 memcached安装启动
1.安装 
  memcached.exe -d install
  服务启动后, memcached 默认使用 64M 内存和 11211 端口作为服务器参数。
  如果你希望调整参数,请参考: memcached.exe -h

2.启动
  memcached.exe -m 512 -p 33000 -d start
  -d为守护进程启动
  -m为指定内存大小
  -p指定端口,默认端口11211

3.测试memcached
d:\>telnet localhost 11211  
add firstKey 0 0 15  
Hello Memcached  
STORED  
get firstKey  
VALUE firstKey 0 15  
Hello Memcached  
END  
quit 


三 memcached及log4net配置(Web.config)

  1. <!--配置memcached服务器及log4net日志-->  
  2. <configuration>  
  3.   <configSections>  
  4.     <!--  ... 其它配置 -->  
  5.   
  6.     <!--log4net日志配置-->  
  7.     <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>  
  8.     <!--缓存客户端配置-->  
  9.     <sectionGroup name="enyim.com">  
  10.       <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>  
  11.       <section name="log" type="Enyim.Caching.Configuration.LoggerSection, Enyim.Caching"/>  
  12.     </sectionGroup>  
  13.     <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>  
  14.   </configSections>  
  15.   <!--缓存客户端配置-->  
  16.   <enyim.com>  
  17.     <log factory="Enyim.Caching.Log4NetFactory, Enyim.Caching.Log4NetAdapter"/>  
  18.     <memcached>  
  19.       <servers>  
  20.         <add address="192.168.0.45" port="11211"/>  
  21.       </servers>  
  22.       <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>  
  23.     </memcached>  
  24.   </enyim.com>  
  25.   <memcached>  
  26.     <servers>  
  27.       <add address="192.168.0.45" port="11211"/>  
  28.     </servers>  
  29.     <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>  
  30.   </memcached>  
  31.   <!--log4net日志配置-->  
  32.   <!--Basic log4net config. Don't forget to call log4net.Config.XmlConfigurator.Configure(); at the start of your app.-->  
  33.   <log4net>  
  34.     <root>  
  35.       <level value="ALL"/>  
  36.       <appender-ref ref="RollingLogFileAppender"/>  
  37.       <appender-ref ref="ConsoleAppender"/>  
  38.       <appender-ref ref="TraceAppender"/>  
  39.     </root>  
  40.     <logger name="Enyim.Caching.Memcached.DefaultNodeLocator">  
  41.       <level value="Debug"/>  
  42.     </logger>  
  43.     <logger name="Enyim.Caching.Memcached.PooledSocket">  
  44.       <level value="Info"/>  
  45.     </logger>  
  46.     <logger name="Enyim.Caching.Memcached.Protocol">  
  47.       <level value="Info"/>  
  48.     </logger>  
  49.     <logger name="Membase.VBucketAwareOperationFactory">  
  50.       <level value="Info"/>  
  51.     </logger>  
  52.     <logger name="Enyim.Caching.Memcached.MemcachedNode">  
  53.       <level value="Info"/>  
  54.     </logger>  
  55.     <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">  
  56.       <param name="File" value="LogFiles/"/>  
  57.       <param name="AppendToFile" value="true"/>  
  58.       <param name="MaxSizeRollBackups" value="10"/>  
  59.       <param name="StaticLogFileName" value="false"/>  
  60.       <param name="DatePattern" value="yyyy-MM-dd".txt""/>  
  61.       <param name="RollingStyle" value="Date"/>  
  62.       <layout type="log4net.Layout.PatternLayout">  
  63.         <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}[%thread] %-5level %c %L %F - %message%newline"/>  
  64.       </layout>  
  65.       <footer value="by anyx"/>  
  66.     </appender>  
  67.     <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">  
  68.       <layout type="log4net.Layout.PatternLayout,log4net">  
  69.         <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>  
  70.       </layout>  
  71.     </appender>  
  72.     <appender name="TraceAppender" type="log4net.Appender.TraceAppender">  
  73.       <layout type="log4net.Layout.PatternLayout,log4net">  
  74.         <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>  
  75.       </layout>  
  76.     </appender>  
  77.   </log4net>  
  78.   <!-- 缓存期限 -->  
  79.   <appSettings>  
  80.     <add key="cachingTime" value="120"/>  
  81.   </appSettings>  
  82.   <!-- 数据库连接 -->  
  83.   <connectionStrings>  
  84.     <add name="dbConnStr" connectionString="Data Source=APPCtl;User ID=appuser;Password=appuser123;Integrated Security = false" providerName="System.Data.OracleClient"/>  
  85.   </connectionStrings>  
  86.   <system.web>  
  87.     <!-- 用于跨域调用 -->  
  88.     <webServices>  
  89.       <protocols>  
  90.         <add name="HttpGet"/>  
  91.         <add name="HttpPost"/>  
  92.       </protocols>  
  93.     </webServices>  
  94.     <!--  ... 其它配置 -->  
  95.   </system.web>  
  96.   <!--  ... 其它配置 -->  
  97. </configuration>  
<!--配置memcached服务器及log4net日志-->
<configuration>
  <configSections>
    <!--  ... 其它配置 -->

    <!--log4net日志配置-->
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
    <!--缓存客户端配置-->
    <sectionGroup name="enyim.com">
      <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
      <section name="log" type="Enyim.Caching.Configuration.LoggerSection, Enyim.Caching"/>
    </sectionGroup>
    <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/>
  </configSections>
  <!--缓存客户端配置-->
  <enyim.com>
    <log factory="Enyim.Caching.Log4NetFactory, Enyim.Caching.Log4NetAdapter"/>
    <memcached>
      <servers>
        <add address="192.168.0.45" port="11211"/>
      </servers>
      <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>
    </memcached>
  </enyim.com>
  <memcached>
    <servers>
      <add address="192.168.0.45" port="11211"/>
    </servers>
    <socketPool minPoolSize="1000" maxPoolSize="2000" connectionTimeout="00:00:10" deadTimeout="00:05:00"/>
  </memcached>
  <!--log4net日志配置-->
  <!--Basic log4net config. Don't forget to call log4net.Config.XmlConfigurator.Configure(); at the start of your app.-->
  <log4net>
    <root>
      <level value="ALL"/>
      <appender-ref ref="RollingLogFileAppender"/>
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="TraceAppender"/>
    </root>
    <logger name="Enyim.Caching.Memcached.DefaultNodeLocator">
      <level value="Debug"/>
    </logger>
    <logger name="Enyim.Caching.Memcached.PooledSocket">
      <level value="Info"/>
    </logger>
    <logger name="Enyim.Caching.Memcached.Protocol">
      <level value="Info"/>
    </logger>
    <logger name="Membase.VBucketAwareOperationFactory">
      <level value="Info"/>
    </logger>
    <logger name="Enyim.Caching.Memcached.MemcachedNode">
      <level value="Info"/>
    </logger>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <param name="File" value="LogFiles/"/>
      <param name="AppendToFile" value="true"/>
      <param name="MaxSizeRollBackups" value="10"/>
      <param name="StaticLogFileName" value="false"/>
      <param name="DatePattern" value="yyyy-MM-dd".txt""/>
      <param name="RollingStyle" value="Date"/>
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss}[%thread] %-5level %c %L %F - %message%newline"/>
      </layout>
      <footer value="by anyx"/>
    </appender>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
      </layout>
    </appender>
    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n"/>
      </layout>
    </appender>
  </log4net>
  <!-- 缓存期限 -->
  <appSettings>
    <add key="cachingTime" value="120"/>
  </appSettings>
  <!-- 数据库连接 -->
  <connectionStrings>
    <add name="dbConnStr" connectionString="Data Source=APPCtl;User ID=appuser;Password=appuser123;Integrated Security = false" providerName="System.Data.OracleClient"/>
  </connectionStrings>
  <system.web>
    <!-- 用于跨域调用 -->
    <webServices>
      <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
      </protocols>
    </webServices>
    <!--  ... 其它配置 -->
  </system.web>
  <!--  ... 其它配置 -->
</configuration>


四 log4net初始化
  初始化Web.config中配置的log4net
  在Global.asax下:

[csharp] view plain copy print ?
  1. protected void Application_Start(object sender, EventArgs e)  
  2.   {  
  3.       //log4net初始化   
  4.       //程序启动加入,在Web.config log4net:RollingLogFileAppender:file对应的日志目录或日志文件   
  5.        log4net.Config.XmlConfigurator.Configure();  
  6.   }  
protected void Application_Start(object sender, EventArgs e)
  {
      //log4net初始化
      //程序启动加入,在Web.config log4net:RollingLogFileAppender:file对应的日志目录或日志文件
       log4net.Config.XmlConfigurator.Configure();
  }

五 读取写入缓存的类
    注意,以下读取写入Memcached是基于memcached v1.4以后的版本
    建一个类,用于读取和写入Memcached.

[csharp] view plain copy print ?
  1. public class CachedService  
  2.     {  
  3.         private static MemcachedClient mc = new MemcachedClient();  
  4.         /// <summary>   
  5.         /// 从缓存服务器取出数据   
  6.         /// </summary>   
  7.         /// <param name="key"></param>   
  8.         /// <returns></returns>   
  9.         public static object getObjectFromCached(string key)  
  10.         {  
  11.             //...   
  12.                 Object obj = null;  
  13.                 IGetOperationResult result = mc.ExecuteGet(key);  
  14.                 if (result.HasValue)  
  15.                 {  
  16.                     obj = result.Value;  
  17.                 }  
  18.                 return obj;  
  19.             //...   
  20.         }  
  21.   
  22.         /// <summary>   
  23.         /// 存入数据到缓存服务器   
  24.         /// </summary>   
  25.         /// <param name="key"></param>   
  26.         /// <returns></returns>   
  27.         public static bool setObjectToCached(string key, object obj)  
  28.         {  
  29.             //读取Web.config配置中的缓存时间   
  30.             double cachintTime = 0;  
  31.             string ct = System.Configuration.ConfigurationManager.AppSettings["cachingTime"];  
  32.             if (!string.IsNullOrEmpty(ct))  
  33.             {  
  34.                 cachintTime = Convert.ToDouble(ct);  
  35.             }  
  36.             //缓存数据   
  37.             IStoreOperationResult result = mc.ExecuteStore(StoreMode.Set, key, obj, DateTime.Now.AddMinutes(cachintTime));  
  38.             if (result.Success)  
  39.             {  
  40.                 return true;  
  41.             }  
  42.             else  
  43.             {  
  44.                 string me = result.Message;  
  45.                 int code = Convert.ToInt32(result.StatusCode);  
  46.   
  47.                 return false;  
  48.             }  
  49.         }  
  50.     }  
public class CachedService
    {
        private static MemcachedClient mc = new MemcachedClient();
        /// <summary>
        /// 从缓存服务器取出数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object getObjectFromCached(string key)
        {
            //...
                Object obj = null;
                IGetOperationResult result = mc.ExecuteGet(key);
                if (result.HasValue)
                {
                    obj = result.Value;
                }
                return obj;
            //...
        }

        /// <summary>
        /// 存入数据到缓存服务器
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool setObjectToCached(string key, object obj)
        {
            //读取Web.config配置中的缓存时间
            double cachintTime = 0;
            string ct = System.Configuration.ConfigurationManager.AppSettings["cachingTime"];
            if (!string.IsNullOrEmpty(ct))
            {
                cachintTime = Convert.ToDouble(ct);
            }
            //缓存数据
            IStoreOperationResult result = mc.ExecuteStore(StoreMode.Set, key, obj, DateTime.Now.AddMinutes(cachintTime));
            if (result.Success)
            {
                return true;
            }
            else
            {
                string me = result.Message;
                int code = Convert.ToInt32(result.StatusCode);

                return false;
            }
        }
    }

六 缓存与数据库
   取数据首先查看Memcached缓存服务器是否有对应键的数据对象,如果有,就直接取出,如果没有,就从数据库取出,再按相应键存入Memcached.

[csharp] view plain copy print ?
  1.      /// <summary>   
  2.     /// 每日龙虎榜:最近交易日:缺省数据:分页(缓存服务器)   
  3.     /// </summary>   
  4.     /// <returns>返回Json格式字符串</returns>   
  5. public class SomeClass  
  6. {      
  7.     public string getSomeData(int start,int limit,string sf,string sr)  
  8.     {  
  9.         if (string.IsNullOrEmpty(sf) || string.IsNullOrEmpty(sr))  
  10.         {  
  11.             //某些参数为空,返回   
  12.             return "{\"total\":0,\"rows\":[]}"; ;  
  13.         }  
  14.   
  15.         string json = "";  
  16.           
  17.         //缓存服务器唯一标识,命名很重要   
  18.         //在这里我采用的是查询条件作为缓存标识   
  19.         string key = "edaylhb:" + start + ":" + limit + ":" + sf + ":" + sr;  
  20.   
  21.         //从缓存服务器中取对应key的数据   
  22.         Object obj = CachedService.getObjectFromCached(key);  
  23.   
  24.         if (obj != null)  
  25.         {  
  26.             //缓存服务器中有数据   
  27.             json = (string)obj;  
  28.         }  
  29.         else  
  30.         {  
  31.             //缓存服务器中无数据,去数据库取,再保存到缓存服务器   
  32.   
  33.             //查询数据库,返回dataset ds   
  34.   
  35.             //...各种sql查询   
  36.   
  37.             try{  
  38.                 string ds2Str = "";  
  39.   
  40.                 //如果ds不为空,转换为Json格式   
  41.                 ds2Str = DbUtil.dataSet2Json(ds);  
  42.                 ds.Dispose();  
  43.                   
  44.   
  45.                 //拼接成Json格式   
  46.                 if (ds.Tables[0].Rows.Count == 0)  
  47.                 {  
  48.                     json = "{\"total\":0,\"rows\":[]}";  
  49.                 }  
  50.                 else  
  51.                 {  
  52.                     json = "{\"total\":" + ds.Tables[0].Rows.Count + ",\"rows\":" + ds2Str + "}";  
  53.                 }  
  54.                 //保存数据到缓存服务器   
  55.                 CachedService.setObjectToCached(key, json);  
  56.             }  
  57.             catch (Exception ex)  
  58.             {  
  59.                 //异常记录到日志   
  60.                 Log4netService.log4netFatal(MethodBase.GetCurrentMethod().DeclaringType, ex);  
  61.                 throw ex;  
  62.             }  
  63.         }  
  64.         return json;  
  65.     }  
  66. }  
         /// <summary>
        /// 每日龙虎榜:最近交易日:缺省数据:分页(缓存服务器)
        /// </summary>
        /// <returns>返回Json格式字符串</returns>
    public class SomeClass
    {    
        public string getSomeData(int start,int limit,string sf,string sr)
        {
            if (string.IsNullOrEmpty(sf) || string.IsNullOrEmpty(sr))
            {
                //某些参数为空,返回
                return "{\"total\":0,\"rows\":[]}"; ;
            }

            string json = "";
            
            //缓存服务器唯一标识,命名很重要
            //在这里我采用的是查询条件作为缓存标识
            string key = "edaylhb:" + start + ":" + limit + ":" + sf + ":" + sr;

            //从缓存服务器中取对应key的数据
            Object obj = CachedService.getObjectFromCached(key);

            if (obj != null)
            {
                //缓存服务器中有数据
                json = (string)obj;
            }
            else
            {
                //缓存服务器中无数据,去数据库取,再保存到缓存服务器

                //查询数据库,返回dataset ds

                //...各种sql查询

                try{
                    string ds2Str = "";

                    //如果ds不为空,转换为Json格式
                    ds2Str = DbUtil.dataSet2Json(ds);
                    ds.Dispose();
                    

                    //拼接成Json格式
                    if (ds.Tables[0].Rows.Count == 0)
                    {
                        json = "{\"total\":0,\"rows\":[]}";
                    }
                    else
                    {
                        json = "{\"total\":" + ds.Tables[0].Rows.Count + ",\"rows\":" + ds2Str + "}";
                    }
                    //保存数据到缓存服务器
                    CachedService.setObjectToCached(key, json);
                }
                catch (Exception ex)
                {
                    //异常记录到日志
                    Log4netService.log4netFatal(MethodBase.GetCurrentMethod().DeclaringType, ex);
                    throw ex;
                }
            }
            return json;
        }
    }

七 dataSet转json

[csharp] view plain copy print ?
  1. public static string dataSet2Json(DataSet ds)  
  2.         {  
  3.             string jsonStr = null;  
  4.               
  5.             //Newtonsoft.Json在转换日期的时候,会出现格式和时区(差8小时)差别  Trade_Status_Name   
  6.             //如果不作如下格式转换,会出现形如Date(1335247957000+0800)/的日期   
  7.             IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();  
  8.             //这里使用自定义日期格式,如果不使用的话,默认是ISO8601格式   
  9.             timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";  
  10.             jsonStr = JsonConvert.SerializeObject(ds.Tables[0], Formatting.Indented, timeConverter);  
  11.             //jsonStr = "[{Stk_Code:'601398',Stk_name:'工商银行'},{Stk_Code:'500999',Stk_name:'农业银行'}]";   
  12.               
  13.             return jsonStr;  
  14.         }  
public static string dataSet2Json(DataSet ds)
        {
            string jsonStr = null;
            
            //Newtonsoft.Json在转换日期的时候,会出现格式和时区(差8小时)差别  Trade_Status_Name
            //如果不作如下格式转换,会出现形如Date(1335247957000+0800)/的日期
            IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
            //这里使用自定义日期格式,如果不使用的话,默认是ISO8601格式
            timeConverter.DateTimeFormat = "yyyy'-'MM'-'dd' 'HH':'mm':'ss";
            jsonStr = JsonConvert.SerializeObject(ds.Tables[0], Formatting.Indented, timeConverter);
            //jsonStr = "[{Stk_Code:'601398',Stk_name:'工商银行'},{Stk_Code:'500999',Stk_name:'农业银行'}]";
            
            return jsonStr;
        }

八  WebService调用及返回Json数据

[csharp] view plain copy print ?
  1. [System.Web.Script.Services.ScriptService]  
  2.     public class TestWebService : System.Web.Services.WebService  
  3.     {  
  4.         /// <summary>   
  5.         /// </summary>   
  6.         [WebMethod]  
  7.         public void getTestData()  
  8.         {  
  9.             string cb = Context.Request["callback"];   //跨域服务器发送jsonp的参数key   
  10.             int start = Convert.ToInt32(string.IsNullOrEmpty(Context.Request["start"]) ? "1" : Context.Request["start"]);  //从第几页开始:默认第一次从1开始,next_start=start+limit   
  11.             int limit = Convert.ToInt32(string.IsNullOrEmpty(Context.Request["limit"]) ? "20" : Context.Request["limit"]);  //每次取的条数(步进):默认每页20条   
  12.             string sf = string.IsNullOrEmpty(Context.Request["sf"]) ? "se_code" : Context.Request["sf"]; //sortField 排序字段,默认:se_code   
  13.             string sr = string.IsNullOrEmpty(Context.Request["sr"]) ? "asc" : Context.Request["sr"];  //sortRule 排序规则,默认:asc   
  14.   
  15.             SomeClass svr = new SomeClass();  
  16.             string json = svr.getSomeData(start, limit, sf, sr);  
  17.   
  18.             Context.Response.ContentType = "text/plain; charset=utf-8";  
  19.             //Context.Response.Write(cb + "({\"total\":30,\"rows\":[{\"ID\":1,\"NAME\":\"John\"},{\"ID\":2,\"NAME\":\"Mike\"}]})");   
  20.             Context.Response.Write(cb + "(" + json + ")");  
  21.         }  
  22.     }  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值