Memcache知识点总结:
一、Memcache安装及使用
参考地址:https://www.jb51.net/article/66525.htm
1.将下载的Memcache安装文件放到某盘下,如下:
dos命令下运行命令进入该目录下:
2.Memcached参数说明:
memcached -d start|stop|shutdown|restart|uninstall|install 启动|停止|关闭|重启|卸载|安装。
-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
服务器操作完成后,我们可以在本机telnet 到服务测试一个下。(如果提示telnet命令不存在,需要去控件面板开启windows的tel服务功能, win7的开启tel功能操作步骤是:【控制面板】->【程序和功能】->【打开或关闭window功能】,然后找到并勾选tel相关即可。其他window系统步骤类似。)
测试telnet是否正常运行 telnet 172.21.0.192 11211
进入后先按ctrl+]启动回示功能,否则无法看到输入信息。回示功能启动成功后如下图:
然后按回车输入参数stats:
安装和测试工作已完成..
实例代码
有很多C#版本的Memcached客户端程序。在这里我们使用的是Memcached.ClientLibrary.dll客户端调用方法,调用需要二个DLL:
Memcached.ClientLibrary.dll (Memcached客户端类库)
log4net.dll (log4net是为Memcached提供日志记录)
在项目中引用这个二个dll,引用log4net.dll后还需进行一系列配置工作。
注意:Memcached.ClientLibrary.dll和log4net.dll有版本对应关系。
2.如果使用WinForm或控制台应用程序把log4net的配置文件独立出现,和写在App.config里面需要小小设置一下。
如图:Log4Net.config属性“复制到输出目录”:“始终复制”。不然在bin目录下找不到对应配置信息会产生报错。
项目目录如下:
LogConfig中的Log4Net.config源码如下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!--添加自定义节点:log4net type:解析类名,程序集名(log4net.dll)-->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<!--定义输出到文件中-->
<appender name="Log4Net_INFO" type="log4net.Appender.RollingFileAppender">
<!--定义文件存放位置-->
<file value="D:/log4net/"/>
<!--是否追加到文件,默认为true,通常无需设置-->
<appendToFile value="true"/>
<RollingStyle value="Date"/>
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<DatePattern value="INFO_yyyyMMdd".log"" />
<!--日志文件名是否为静态-->
<StaticLogFileName value="false"/>
<!--多线程时采用最小锁定-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--布局(向用户显示最后经过格式化的输出信息)-->
<layout type="log4net.Layout.PatternLayout">
<!--
%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息
%n(new line):换行
%d(datetime):输出当前语句运行的时刻
%r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数
%t(thread id):当前语句所在的线程ID
%p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等
%c(class):当前日志对象的名称,例如:
%L:输出语句所在的行号
%F:输出语句所在的文件名
%-数字:表示该项的最小长度,如果不够,则用空格填充
-->
<Header value="[Header] "/>
<Footer value="[Footer] "/>
<!--正文-->
<ConversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline" />
</layout>
</appender>
<!--<appender></appender>定义输出信息设置节点,决定日志输出的方式(可设置多个节点,如对INFO,ERROR等设置不同的输出方式)-->
<appender name="Log4Net_ERROR" type="log4net.Appender.RollingFileAppender">
<file value="D:/log4net/"/>
<appendToFile value="true"/>
<RollingStyle value="Date"/>
<DatePattern value="ERROR_yyyyMMdd".log"" />
<StaticLogFileName value="false"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<Header value="[Header] "/>
<Footer value="[Footer] "/>
<!--正文-->
<ConversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline" />
</layout>
</appender>
<!--<root></root>定义日志的输出媒介-->
<root>
<level value="ERROR"/>
<appender-ref ref="Log4Net_ERROR" />
<level value="INFO"/>
<appender-ref ref="Log4Net_INFO" />
</root>
</log4net>
</configuration>
program.cs中源码如下:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Memcached.ClientLibrary;
using MemcacheProject.Model;
namespace MemcacheProject
{
/*
* Memcache项目实例应用
*
* 需引用Memcached.ClientLibrary.dll、 log4net.dll
* 注明:在项目的nuget中下载Memcached.ClientLibrary时log4net.dll也会一并下载
* 学习地址:https://www.jb51.net/article/66525.htm
*
*/
class Program
{
static void Main(string[] args)
{
Program pro =new Program();
pro.OperateMemcacheMethod();
}
/// <summary>
/// memcache的基本操作:增,删,查,改,设置过期时间
/// </summary>
public void OperateMemcacheMethod()
{
//参数设置
string SockIOPoolName = "Test_SockIOPoolName";
string[] MemcacheServiceList = {"127.0.0.1:11211" };//11211是端口号
//设置连接池
SockIOPool SPool = SockIOPool.GetInstance(SockIOPoolName);
SPool.SetServers(MemcacheServiceList);
SPool.Initialize();
//实例化
MemcachedClient MClient = new MemcachedClient();
MClient.PoolName = SockIOPoolName;
Console.WriteLine("1.创建memcache缓存Hello World");
MClient.Add("key1001", "Hello World");
Console.WriteLine("2.查询缓存信息{0}",MClient.Get("key1001"));
Console.WriteLine("3.修改memcache缓存Hello World");
MClient.Set("key1001","Hello World -修改版");
Console.WriteLine("4.查询缓存信息{0}",MClient.Get("key1001"));
//删除memcache缓存
if (MClient.KeyExists("key1001"))
{
Console.WriteLine("5.删除memcache缓存");
MClient.Delete("key1001");
}
//缓存删除后判断是否仍然存在
if (MClient.KeyExists("key1001"))
{
Console.WriteLine(MClient.Get("key1001"));
}
else
{
Console.WriteLine("6.缓存已删除");
}
//添加对象值到缓存
Student stud= new Student()
{
id ="10001",
name="张三"
};
MClient.Add("student", stud);
Student Get_stud = MClient.Get("student") as Student;
Console.WriteLine("7.缓存实体对象:{0}{1}", Get_stud.id, Get_stud.name);
//设置过期时间
MClient.Add("key1002","我已设置过期时间1分钟",DateTime.Now.AddMinutes(1));
while (true)
{
if (MClient.KeyExists("key1002"))
{
Console.WriteLine("key:key1002 Vlaue:{0},当前时间:{1}",MClient.Get("key1002"),DateTime.Now);
Thread.Sleep(20000);
}
else
{
Console.WriteLine("key:key1002 我已过期,当前时间:{0}",DateTime.Now);
Console.WriteLine("key:key1002 Vlaue:{0},当前时间:{1}", MClient.Get("key1002"), DateTime.Now);
Console.ReadKey();
break;
}
}
}
/// <summary>
/// 多个memcache操作
/// </summary>
public void OperateManyMemcacheMethod()
{
//参数
string[] MemcacheServiceList = {"10.3.90.1:11211", "10.3.90.2:11211", "10.3.90.3:11211"};
//设置连接池
SockIOPool SPool = SockIOPool.GetInstance();
SPool.SetServers(MemcacheServiceList);
SPool.Initialize();
MemcachedClient MClient = new MemcachedClient();
MClient.FlushAll();
int count = 5;
var time = Stopwatch.StartNew();
for (int i=0;i<count;i++)
{
MClient.Add(i.ToString(), "value" + i);
}
Console.WriteLine("memcached缓存创建成功.耗时:{0}",time.ElapsedTicks);
time = Stopwatch.StartNew();
for (int i=0;i<count;i++)
{
if (MClient.KeyExists(i.ToString()))
{
Console.WriteLine("key:{0}.value:{1}",i,MClient.Get(i.ToString()));
}
else
{
Console.WriteLine("-----------未能查询到数据key:{0}----------",i);
}
}
Console.WriteLine("memcached缓存数据查询完成,耗时:{0}",time.ElapsedTicks);
SPool.Shutdown();
}
}
}
附:Log4Net日志配置:
参考地址:https://www.jb51.net/article/66526.htm
1.下载log4net.dll 下载地址[http://logging.apache.org/log4net/download_log4net.cgi]
下载文件:log4net-1.2.13-bin-newkey.zip。 解压选择对应的net版本找到log4net.dll。
2.在项目中引用log4net.dll。
实例代码
准备工作完成后我们来看下实例代码 ,首先在项目中创建一个文件夹LogConfig。把有关log4net的一些配置文件和类都放在这个文件夹里面。
WEB网站为例,在项目LogConfig文件夹中创建Log4Net.config配置文件。
Log4Net.config配置文件源码:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<!--添加自定义节点:log4net type:解析类名,程序集名(log4net.dll)-->
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<!--定义输出到文件中-->
<appender name="Log4Net_INFO" type="log4net.Appender.RollingFileAppender">
<!--定义文件存放位置-->
<file value="D:/log4net/"/>
<!--是否追加到文件,默认为true,通常无需设置-->
<appendToFile value="true"/>
<RollingStyle value="Date"/>
<!--日期的格式,每天换一个文件记录,如不设置则永远只记录一天的日志,需设置-->
<DatePattern value="INFO_yyyyMMdd".log"" />
<!--日志文件名是否为静态-->
<StaticLogFileName value="false"/>
<!--多线程时采用最小锁定-->
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<!--布局(向用户显示最后经过格式化的输出信息)-->
<layout type="log4net.Layout.PatternLayout">
<!--
%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息
%n(new line):换行
%d(datetime):输出当前语句运行的时刻
%r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数
%t(thread id):当前语句所在的线程ID
%p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等
%c(class):当前日志对象的名称,例如:
%L:输出语句所在的行号
%F:输出语句所在的文件名
%-数字:表示该项的最小长度,如果不够,则用空格填充
-->
<Header value="[Header] "/>
<Footer value="[Footer] "/>
<!--正文-->
<ConversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline" />
</layout>
</appender>
<appender name="Log4Net_ERROR" type="log4net.Appender.RollingFileAppender">
<file value="D:/log4net/"/>
<appendToFile value="true"/>
<RollingStyle value="Date"/>
<DatePattern value="ERROR_yyyyMMdd".log"" />
<StaticLogFileName value="false"/>
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
<layout type="log4net.Layout.PatternLayout">
<Header value="[Header] "/>
<Footer value="[Footer] "/>
<!--正文-->
<ConversionPattern value="记录时间:%date 线程ID:[%thread] 日志级别:%-5level 出错类:%logger property:[%property{NDC}] - 错误描述:%message%newline" />
</layout>
</appender>
<root>
<level value="ERROR"/>
<appender-ref ref="Log4Net_ERROR" />
<level value="INFO"/>
<appender-ref ref="Log4Net_INFO" />
</root>
</log4net>
</configuration>
配置文件写完后我们在来写一个Helper类。同样在项目中创建一个名为LogHelper.cs的类文件
源码如下:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using log4net;
//指定log4net使用的config文件来读取配置信息
[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"LogConfig\Log4Net.config",Watch = true)]
namespace Log4.NetProject.LogConfig
{
/// <summary>
/// 日志帮助类
/// </summary>
public class LogHelper
{
private static readonly ConcurrentDictionary<Type,ILog>
_loggers = new ConcurrentDictionary<Type, ILog>();
/// <summary>
/// 1.获取记录器
/// </summary>
/// <param name="source"></param>
/// <returns></returns>
private static ILog GetLogger(Type source)
{
if (_loggers.ContainsKey(source))
{
return _loggers[source];
}
else
{
ILog logger = LogManager.GetLogger(source);
_loggers.TryAdd(source, logger);
return logger;
}
}
/*
* Log a message object
*/
/// <summary>
/// 2.调试信息
/// </summary>
public static void Debug(object source,string message)
{
Debug(source.GetType(),message);
}
/// <summary>
/// 3.调试信息
/// </summary>
/// <param name="source"></param>
/// <param name="message"></param>
/// <param name="ps"></param>
public static void Debug(object source,string message,params object[] ps)
{
Debug(source.GetType(),string.Format(message,ps));
}
/// <summary>
/// 4.调试信息
/// </summary>
/// <param name="source"></param>
/// <param name="message"></param>
public static void Debug(Type source,string message)
{
ILog logger = GetLogger(source);
if (logger.IsDebugEnabled)
{
logger.Debug(message);
}
}
/// <summary>
/// 5.关键信息
/// </summary>
public static void Info(object source, object message)
{
Info(source.GetType(),message);
}
/// <summary>
/// 6.关键信息
/// </summary>
public static void Info(Type source,object message)
{
ILog logger = GetLogger(source);
if (logger.IsInfoEnabled)
{
logger.Info(message);
}
}
/// <summary>
/// 7.警告信息
/// </summary>
public static void Warn(object source,object message)
{
Warn(source.GetType(),message);
}
/// <summary>
/// 8.警告信息
/// </summary>
/// <param name="source"></param>
/// <param name="message"></param>
public static void Warn(Type source, object message)
{
ILog logger = GetLogger(source);
if (logger.IsWarnEnabled)
{
logger.Warn(message);
}
}
/// <summary>
/// 9.错误信息
/// </summary>
public static void Error(object source, object message)
{
Error(source.GetType(), message);
}
/// <summary>
/// 10.错误信息
/// </summary>
/// <param name="source"></param>
/// <param name="message"></param>
public static void Error(Type source, object message)
{
ILog logger = GetLogger(source);
if (logger.IsErrorEnabled)
{
logger.Error(message);
}
}
/// <summary>
/// 11.失败信息
/// </summary>
public static void Fatal(object source, object message)
{
Fatal(source.GetType(), message);
}
/// <summary>
/// 12.失败信息
/// </summary>
/// <param name="source"></param>
/// <param name="message"></param>
public static void Fatal(Type source, object message)
{
ILog logger = GetLogger(source);
if (logger.IsFatalEnabled)
{
logger.Fatal(message);
}
}
/*
* Log a message object and exception
*/
/// <summary>
/// 调试信息
/// </summary>
public static void Debug(object source,object message,Exception exception)
{
Debug(source.GetType(),message,exception);
}
/// <summary>
/// 调试信息
/// </summary>
public static void Debug(Type source,object message,Exception exception)
{
GetLogger(source).Debug(message,exception);
}
/// <summary>
/// 关键信息
/// </summary>
public static void Info(object source, object message, Exception exception)
{
Info(source.GetType(), message, exception);
}
/// <summary>
/// 关键信息
/// </summary>
public static void Info(Type source, object message, Exception exception)
{
GetLogger(source).Info(message, exception);
}
/// <summary>
/// 警告信息
/// </summary>
public static void Warn(object source, object message, Exception exception)
{
Warn(source.GetType(), message, exception);
}
/// <summary>
/// 警告信息
/// </summary>
public static void Warn(Type source, object message, Exception exception)
{
GetLogger(source).Warn(message, exception);
}
/// <summary>
/// 错误信息
/// </summary>
public static void Error(object source, object message, Exception exception)
{
Error(source.GetType(), message, exception);
}
/// <summary>
/// 错误信息
/// </summary>
public static void Error(Type source, object message, Exception exception)
{
GetLogger(source).Error(message, exception);
}
/// <summary>
/// 失败信息
/// </summary>
public static void Fatal(object source, object message, Exception exception)
{
Fatal(source.GetType(), message, exception);
}
/// <summary>
/// 失败信息
/// </summary>
public static void Fatal(Type source, object message, Exception exception)
{
GetLogger(source).Fatal(message, exception);
}
}
}
配置和Helper类都有了..现在来看看调用方法。在项目中创建一个index.aspx页面
源码:
LogHelper.Debug(this,"Debug");
LogHelper.Error(this, "Error");
LogHelper.Fatal(this, "Fatal");
LogHelper.Info(this, "Info");
LogHelper.Warn(this, "Warn");
参数说明:
Log4Net.config是配置日志输出参数文件。在这个文件中可以到看很多配置节点,大体可以分为二个大类<configSections>...</configSections> 和 <log4net>...</log4net>。我们来看看这些节点都是啥意思。
1:<configSections>..</configSections>:申明自定义节点log4net解析的类名和程序集名(log4net.dll)。
2:<log4net>..</log4net>:使用log4net的配置信息都在这里设置。来重点看看都有那些设置信息,这个大节点整体也可以分为二类。
2.1:定义输出信息设置节点<appender></appender>。
2.2:定义日志的输出媒介<root></root>。
配置的总体结构就是这样,下面来看一些详细内容。
appender:决定日志输出的方式(可设置多个节点,如对INFO,ERROR等设置不同的输出方式)。
主要包括已下几种:
1 AnsiColorTerminalAppender:在ANSI 窗口终端写下高亮度的日志事件。
2 AspNetTraceAppender:能用asp.net中Trace的方式查看记录的日志。
3 BufferingForwardingAppender:在输出到子Appenders之前先缓存日志事件。
4 ConsoleAppender:将日志输出到控制台。
5 EventLogAppender:将日志写到Windows Event Log.
6 FileAppender:将日志写到文件中。
7 LocalSyslogAppender:将日志写到local syslog service (仅用于UNIX环境下).
8 MemoryAppender:将日志存到内存缓冲区。
9 NetSendAppender:将日志输出到Windows Messenger service.这些日志信息将在用户终端的对话框中显示。
10 RemoteSyslogAppender:通过UDP网络协议将日志写到Remote syslog service。
11 RemotingAppender:通过.NET Remoting将日志写到远程接收端。
12 RollingFileAppender:将日志以回滚文件的形式写到文件中。(实例代码中使用的是此类型)
13 SmtpAppender:将日志写到邮件中。
14 TraceAppender:将日志写到.NET trace 系统。
15 UdpAppender:将日志connectionless UDP datagrams的形式送到远程宿主或以UdpClient的形式广播。
从上面提供的方式中可以看出能输出文件、控制台、Windows事件日志和数据库。这个可根据实际情况选择。
代码如下:
<appender name="Log4Net_INFO" type="log4net.Appender.RollingFileAppender">
...
</appender>
这里配置的name(“Log4Net_INFO”)会在定义日志的输出媒介中使用到。name可任意设置。
在appender 节点中还会配置一些文件存放的地址,日志个数等信息。这些在实例代码中都在体现,这里不做说明。我们在来看看日志最后输出呈现的布局设置信息。
<layout type=
"log4net.Layout.PatternLayout"
>
<!--头-->
<Header value=
"[Header]"
/>
<!--脚注-->
<Footer value=
"[Footer]"
/>
<!--正文-->
<ConversionPattern value=
"%d [%t] %-5p %c [%x] - %m%n"
/>
</layout>
这里配置的信息最终是日志打印出来的样式。我们可以看到这里可以设置内容头Header和尾Footer。正文ConversionPattern。在正文中有出现有 %d [%t]这些都是啥意思了表示什么。这里有一个对照表可提供参考:
%m(message):输出的日志消息,如ILog.Debug(…)输出的一条消息
%n(new line):换行
%d(datetime):输出当前语句运行的时刻
%r(run time):输出程序从运行到执行到当前语句时消耗的毫秒数
%t(thread id):当前语句所在的线程ID
%p(priority): 日志的当前优先级别,即DEBUG、INFO、WARN…等
%c(class):当前日志对象的名称,例如:
%L:输出语句所在的行号
%F:输出语句所在的文件名
%-数字:表示该项的最小长度,如果不够,则用空格填充
配置的基本也就这些。下就是root的配置说明 。
root:
对设置输出的方式进行指定。
<root>
<!--批定DEBUG输出的文件形式记录日志-->
<level value=
"DEBUG"
/>
<appender-
ref
ref
=
"Log4Net_ERROR"
/>
<!--批定INFO输出的文件形式记录日志-->
<level value=
"INFO"
/>
<appender-
ref
ref
=
"Log4Net_INFO"
/>
</root>
比如定义级别为INFO,则INFO级别向下的级别,比如DEBUG日志将不会被记录
如果没有定义LEVEL的值,则缺省为DEBUG