Linux下MemCached安装及c#客户端调用
一、Linux下MemCached安装和启动
如果是centos可以yum安装
# yum install libevent-devel
如果不支持yum的系统,可以这样装libevent
# cd /usr/local/src
# wget http://www.monkey.org/~provos/libevent-1.4.12-stable.tar.gz
# tar vxf libevent-1.4.12-stable.tar.gz
# cd libevent-1.4.12
# ./configure --prefix=/usr/local/libevent
# make && make install
继续安装memcached
# cd /usr/local/src
# wget http://cloud.github.com/downloads/saberma/saberma.github.com/memcached-1.4.4.tar.gz
# tar vxf memcached-1.4.4.tar.gz
# cd memcached-1.4.4
# ./configure --prefix=/usr/local/memcached
# make && make install
安装完后启动memcached并分配1024m内存
/usr/local/memcached/bin/memcached -d -m 1024 –l 10.32.33.120 -p 11211 -u root
-d选项是启动一个守护进程,
-m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB,
-u是运行Memcache的用户,我这里是root,
-l是监听的服务器IP地址,如果有多个地址的话,我这里指定了服务器的IP地址10.32.33.120,
-p是设置Memcache监听的端口,我这里设置了12000,最好是1024以上的端口,
-c选项是最大运行的并发连接数,默认是1024,我这里设置了256,按照你服务器的负载量来设定,
-P是设置保存Memcache的pid文件,我这里是保存在 /tmp/memcached.pid,
将memcached加入启动项
# vi /etc/rc.d/rc.local
在最后加入
/usr/local/memcached/bin/memcached -d -m 1024 –l 10.32.33.120 -p 11211 -u root
按Esc键,再输入
:wq
保存退出
查看是否启动memcached
获取运行状态:echo stats | nc 10.32.33.120 11211(可以查看出pid) 或使用ps -ef|grep memcached
如果要结束Memcache进程,执行:
# kill `cat /tmp/memcached.pid`
也可以
#kill –9 进程号
二、连接到 memcached
连接到 memcached:
telnet ip 端口,如telnet 10.32.33.120 11211
stats查看状态,flush_all:清楚缓存
查看memcached状态的基本命令,通过这个命令可以看到如下信息:
STAT pid 22459 进程ID
STAT uptime 1027046 服务器运行秒数
STAT time 1273043062 服务器当前unix时间戳
STAT version 1.4.4 服务器版本
STAT pointer_size 64 操作系统字大小(这台服务器是64位的)
STAT rusage_user 0.040000 进程累计用户时间
STAT rusage_system 0.260000 进程累计系统时间
STAT curr_connections 10 当前打开连接数
STAT total_connections 82 曾打开的连接总数
STAT connection_structures 13 服务器分配的连接结构数
STAT cmd_get 54 执行get命令总数
STAT cmd_set 34 执行set命令总数
STAT cmd_flush 3 指向flush_all命令总数
STAT get_hits 9 get命中次数
STAT get_misses 45 get未命中次数
STAT delete_misses 5 delete未命中次数
STAT delete_hits 1 delete命中次数
STAT incr_misses 0 incr未命中次数
STAT incr_hits 0 incr命中次数
STAT decr_misses 0 decr未命中次数
STAT decr_hits 0 decr命中次数
STAT cas_misses 0 cas未命中次数
STAT cas_hits 0 cas命中次数
STAT cas_badval 0 使用擦拭次数
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 15785 读取字节总数
STAT bytes_written 15222 写入字节总数
STAT limit_maxbytes 1048576 分配的内存数(字节)
STAT accepting_conns 1 目前接受的链接数
STAT listen_disabled_num 0
STAT threads 4 线程数
STAT conn_yields 0
STAT bytes 0 存储item字节数
STAT curr_items 0 item个数
STAT total_items 34 item总数
STAT evictions 0 为获取空间删除item的总数
三、c#调用
MemCache管理操作类,MemCachedManager.cs文件:
using System; using System.Collections; using System.Data; using System.Data.Common; using System.IO; using Memcached.ClientLibrary; namespace Plugin.Cache { /// <summary> /// MemCache管理操作类 /// </summary> public sealed class MemCachedManager { #region 静态方法和属性 private static MemcachedClient mc = null; private static SockIOPool pool = null; private static string[] serverList = null; private static MemCachedConfigInfo memCachedConfigInfo = MemCachedConfig.GetConfig(); #endregion static MemCachedManager() { CreateManager(); } private static void CreateManager() { serverList = memCachedConfigInfo.ServerList; pool = SockIOPool.GetInstance(memCachedConfigInfo.PoolName); pool.SetServers(serverList); pool.InitConnections = memCachedConfigInfo.IntConnections;//初始化链接数 pool.MinConnections = memCachedConfigInfo.MinConnections;//最少链接数 pool.MaxConnections = memCachedConfigInfo.MaxConnections;//最大连接数 pool.SocketConnectTimeout = memCachedConfigInfo.SocketConnectTimeout;//Socket链接超时时间 pool.SocketTimeout = memCachedConfigInfo.SocketTimeout;// Socket超时时间 pool.MaintenanceSleep = memCachedConfigInfo.MaintenanceSleep;//维护线程休息时间 pool.Failover = memCachedConfigInfo.FailOver; //失效转移(一种备份操作模式) pool.Nagle = memCachedConfigInfo.Nagle;//是否用nagle算法启动socket pool.HashingAlgorithm = HashingAlgorithm.NewCompatibleHash; pool.Initialize(); mc = new MemcachedClient(); mc.PoolName = memCachedConfigInfo.PoolName; mc.EnableCompression = false; } /// <summary> /// 缓存服务器地址列表 /// </summary> public static string[] ServerList { set { if (value != null) serverList = value; } get { return serverList; } } /// <summary> /// 客户端缓存操作对象 /// </summary> public static MemcachedClient CacheClient { get { if (mc == null) CreateManager(); return mc; } } public static void Dispose() { if (pool != null) pool.Shutdown(); } } }
cache操作接口类ICacheStrategy.cs(为了方便扩展其他的cache):
using System; using System.Text; namespace Plugin.Cache { /// <summary> /// 公共缓存策略接口 /// </summary> public interface ICacheStrategy { /// <summary> /// 添加指定ID的对象 /// </summary> /// <param name="objId">缓存键</param> /// <param name="o">缓存对象</param> void AddObject(string objId, object o); /// <summary> /// 移除指定ID的对象 /// </summary> /// <param name="objId">缓存键</param> void RemoveObject(string objId); /// <summary> /// 返回指定ID的对象 /// </summary> /// <param name="objId">缓存键</param> /// <returns></returns> object RetrieveObject(string objId); /// <summary> /// 到期时间,单位:秒 /// </summary> int TimeOut { set;get;} } }
MemCached.cs类
using System; using System.Web; using System.Collections; using System.Web.Caching; namespace Plugin.Cache { /// <summary> /// 默认缓存管理类,默认用memcached /// </summary> public class MemCached : ICacheStrategy { /// <summary> /// 设置到期相对时间[单位: 秒] /// </summary> public int TimeOut { set; get; } /// <summary> /// 加入当前对象到缓存中 /// </summary> /// <param name="objId">对象的键值</param> /// <param name="o">缓存的对象</param> public virtual void AddObject(string objId, object o) { if (TimeOut > 0) { MemCachedManager.CacheClient.Set(objId, o, System.DateTime.Now.AddSeconds(TimeOut)); } else { MemCachedManager.CacheClient.Set(objId, o); } } /// <summary> /// 删除缓存对象 /// </summary> /// <param name="objId">对象的关键字</param> public virtual void RemoveObject(string objId) { if (MemCachedManager.CacheClient.KeyExists(objId)) MemCachedManager.CacheClient.Delete(objId); } /// <summary> /// 返回一个指定的对象 /// </summary> /// <param name="objId">对象的关键字</param> /// <returns>对象</returns> public virtual object RetrieveObject(string objId) { return MemCachedManager.CacheClient.Get(objId); } } }
实体类MemCachedConfigInfo.cs
using Yintai.Plugin.Common; /// <summary> /// MemCached配置信息类文件 /// </summary> namespace Plugin { public class MemCachedConfigInfo { private string[] _serverList; /// <summary> /// 链接地址 /// </summary> public string[] ServerList { get { return _serverList; } set { _serverList = value; } } private string _poolName; /// <summary> /// 链接池名称 /// </summary> public string PoolName { get { return string.IsNullOrEmpty(_poolName) ? "Yintai.Plugin.Cache.MemCached" : _poolName; } set { _poolName = value; } } private int _intConnections; /// <summary> /// 初始化链接数 /// </summary> public int IntConnections { get { return _intConnections > 0 ? _intConnections : 3; } set { _intConnections = value; } } private int _minConnections; /// <summary> /// 最少链接数 /// </summary> public int MinConnections { get { return _minConnections > 0 ? _minConnections : 3; } set { _minConnections = value; } } private int _maxConnections; /// <summary> /// 最大连接数 /// </summary> public int MaxConnections { get { return _maxConnections > 0 ? _maxConnections : 5; } set { _maxConnections = value; } } private int _socketConnectTimeout; /// <summary> /// Socket链接超时时间 /// </summary> public int SocketConnectTimeout { get { return _socketConnectTimeout > 1000 ? _socketConnectTimeout : 1000; } set { _socketConnectTimeout = value; } } private int _socketTimeout; /// <summary> /// socket超时时间 /// </summary> public int SocketTimeout { get { return _socketTimeout > 1000 ? _maintenanceSleep : 3000; } set { _socketTimeout = value; } } private int _maintenanceSleep; /// <summary> /// 维护线程休息时间 /// </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算法启动socket /// </summary> public bool Nagle { get { return _nagle; } set { _nagle = value; } } } }
实现代码完了,下面就是把配置文件memcached.config反序列化成实体方法
用MemCachedConfig.cs实现配置文件的载入和读取LoadConfig是载入配置,SetConfig是保存配置,GetConfig是获取配置,其中用了了序列化和反序列化
MemCachedConfig.cs文件如下:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Linq; using System.Text; using System.Web; using Plugin.Cache; using Plugin.Common; namespace Plugin { public class MemCachedConfig { private static object _lockHelper = new object(); private static MemCachedConfigInfo config = null; public static void LoadConfig(string configfilepath) { if (config == null) { lock (_lockHelper) { if (config == null) { config = (MemCachedConfigInfo)SerializationHelper.Load(typeof(MemCachedConfigInfo), configfilepath); } } } } /// <summary> /// 获取配置 /// </summary> /// <param name="anConfig"></param> public static MemCachedConfigInfo GetConfig() { return config; } #region 私有方法 public static void SetConfig(MemCachedConfigInfo verifyImageServiceInfoList, string configfilepath) { SerializationHelper.Save(verifyImageServiceInfoList, configfilepath); } #endregion } }
SerializationHelper.cs代码如下:
using System; using System.IO; using System.Xml.Serialization; using System.Xml; using System.Collections.Generic; using System.Text; namespace Plugin.Common { /// <summary> /// SerializationHelper 的摘要说明。 /// </summary> public class SerializationHelper { private SerializationHelper() {} private static Dictionary<int, XmlSerializer> serializer_dict = new Dictionary<int, XmlSerializer>(); public static XmlSerializer GetSerializer(Type t) { int type_hash = t.GetHashCode(); if (!serializer_dict.ContainsKey(type_hash)) serializer_dict.Add(type_hash, new XmlSerializer(t)); return serializer_dict[type_hash]; } /// <summary> /// 反序列化 /// </summary> /// <param name="type">对象类型</param> /// <param name="filename">文件路径</param> /// <returns></returns> public static object Load(Type type, string filename) { FileStream fs = null; try { // open the stream... fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); XmlSerializer serializer = new XmlSerializer(type); return serializer.Deserialize(fs); } catch(Exception ex) { throw ex; } finally { if(fs != null) fs.Close(); } } /// <summary> /// 序列化 /// </summary> /// <param name="obj">对象</param> /// <param name="filename">文件路径</param> public static bool Save(object obj, string filename) { bool success = false; FileStream fs = null; // serialize it... try { fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); XmlSerializer serializer = new XmlSerializer(obj.GetType()); serializer.Serialize(fs, obj); success = true; } catch(Exception ex) { throw ex; } finally { if(fs != null) fs.Close(); } return success; } /// <summary> /// xml序列化成字符串 /// </summary> /// <param name="obj">对象</param> /// <returns>xml字符串</returns> public static string Serialize(object obj) { string returnStr = ""; XmlSerializer serializer = GetSerializer(obj.GetType()); MemoryStream ms = new MemoryStream(); XmlTextWriter xtw = null; StreamReader sr = null; try { xtw = new System.Xml.XmlTextWriter(ms, Encoding.UTF8); xtw.Formatting = System.Xml.Formatting.Indented; serializer.Serialize(xtw, obj); ms.Seek(0, SeekOrigin.Begin); sr = new StreamReader(ms); returnStr = sr.ReadToEnd(); } catch (Exception ex) { throw ex; } finally { if (xtw != null) xtw.Close(); if (sr != null) sr.Close(); ms.Close(); } return returnStr; } public static object DeSerialize(Type type, string s) { byte[] b = System.Text.Encoding.UTF8.GetBytes(s); try { XmlSerializer serializer = GetSerializer(type); return serializer.Deserialize(new MemoryStream(b)); } catch (Exception ex) { throw ex; } } } }
最后配置文件类似这样的:
<?xml version="1.0"?> <MemCachedConfigInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <ServerList> <string>10.32.33.120:11211</string> </ServerList> <PoolName>Plugin.Cache.MemCached</PoolName> <IntConnections>3</IntConnections> <MinConnections>3</MinConnections> <MaxConnections>5</MaxConnections> <SocketConnectTimeout>1000</SocketConnectTimeout> <SocketTimeout>30</SocketTimeout> <MaintenanceSleep>30</MaintenanceSleep> <FailOver>true</FailOver> <Nagle>false</Nagle> </MemCachedConfigInfo>
使用时调用方法:
MemCachedConfig.LoadConfig(Server.MapPath("/config/memcached.config"));
这个方法通过LoadConfig把配置加载进来,反序列化成MemCachedConfigInfo实体并放入私有静态变量config 中,并通过GetConfig() 获取config,然后MemCachedManager类通过private static MemCachedConfigInfo memCachedConfigInfo = MemCachedConfig.GetConfig();方法获取到配置了。