C# Memcached 缓存使用方法
一、memcached是什么
MemCached是一种基于内存的key-value存储,用来存储小块的任意数据。实现原理就是,第一次从数据库获取到结果之后,同时将结果保存在内存中,从而简单对数据库的访问次数,以提高Web应用的速度。

二、memcached安装:
1、下载memcached文件 给出链接 http://download.csdn.net/download/jx_521/10022727
2、解压将对应memcached.exe 版本放入到文件夹内(F:\memcached.exe)
3、使用命令切换到memcached.exe目录下 cd F:\
4、memcached.exe -d install
5、memcached.exe -d start 启动服务
6、在服务器上开启端口 11211 (防火墙里添加入站规则,如果是本机则不需要设置)
MemCache常用的几条命令:
安装:memcache.exe -d install
卸载:memcache.exe -d unstall
启动:memcache.exe -d start
停止:memcache.exe -d stop
memcache的默认端口是11211,默认内存大小是64M,如果需要修改这二项参数使用下面这条命令:
memcache.exe -p 10000 -m 512 -d start
详细参数:
-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 显示帮助
安装完成之后服务里就可以看到

三、.net中使用Memcached(添加控制台应用程序)
1、添加Dll
Enyim.Caching.dll
MemcachedProviders.dll
log4net.dll
2、修改配置文件
<configuration> <configSections> <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" /> </configSections> <memcached> <servers> <!-- 注意这里写你自己的IP地址和端口号(memcached端口号默认11211)--> <add address="192.168.1.0" port="11211" /> </servers> <socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" /> </memcached> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> </configuration>
3、添加缓存类 MemCached.cs
public class MemCached
{
private static MemcachedClient oMemCached;
static MemCached()
{
MemcachedClientSection oServersSection = (MemcachedClientSection)ConfigurationManager.GetSection("memcached");
MemcachedClientConfiguration oMemConfig = new MemcachedClientConfiguration();
foreach (IPEndPoint server in oServersSection.Servers.ToIPEndPointCollection())
{
oMemConfig.Servers.Add(server);
}
oMemCached = new MemcachedClient(oMemConfig);
}
public static long DefaultExpireTime = TimeSpan.TicksPerHour;
public static string KeySuffix { get; set; }
public static bool Add(string strKey, object objValue)
{
return oMemCached.Store(StoreMode.Set, strKey, objValue);
}
public static bool Add(string strKey, object objValue, bool bDefaultTimeSpan)
{
//var vTimeSpan = TimeSpan.FromMilliseconds(DefaultExpireTime);
return Add(strKey, objValue, 480 * 60 * 1000);
}
public static bool Add(string strKey, object objValue, long lNumofMilliSeconds)
{
return oMemCached.Store(StoreMode.Set, strKey, objValue, DateTime.Now.AddMilliseconds(lNumofMilliSeconds));
}
public static bool Add(string strKey, object objValue, TimeSpan tspan)
{
return oMemCached.Store(StoreMode.Set, strKey, objValue, tspan);
}
public static IDictionary<string, object> Get(params string[] keys)
{
Dictionary<string, object> dictObjects = new Dictionary<string, object>();
foreach (string key in keys)
{
dictObjects.Add(key, oMemCached.Get(key));
}
return dictObjects;
}
public static T Get<T>(string strKey)
{
return oMemCached.Get<T>(strKey);
}
public static object Get(string strKey)
{
return oMemCached.Get(strKey);
}
public static T GetCache<T>(string key, Func<T> fun)
{
T value = Get<T>(key);
if (value == null)
{
value = fun.Invoke();
Add(key, value);
}
return value;
}
public static IDictionary<string, object> Get(IEnumerable<string> keys)
{
return oMemCached.Get(keys);
}
public static bool Remove(string strKey)
{
return oMemCached.Remove(strKey);
}
public static void RemoveAll()
{
oMemCached.FlushAll();
}
}4.调用
调用Get方法
static void Main(string[] args)
{
//获取缓存
object ob = MemCached.Get("hello");
if (ob == null)
{
//添加缓存
MemCached.Add("hello", getHi(1230));
ob = MemCached.Get("hello");
}
Console.WriteLine(ob);
Console.ReadKey();
}
private static string getHi(int id)
{
return "hello_" + id;
}调用GetCache方法
static void Main(string[] args)
{
string obCache = MemCached.GetCache<string>("hello", () => getHi(1230));
Console.WriteLine(obCache);
Console.ReadKey();
}
private static string getHi(int id)
{
return "hello_" + id;
}很明显使用委托之后代码很简洁,判断缓存是否存在的方法被封装起来了
四、memcached 分布式原理
memcached不相互通信,那么memcached是如何实现分布式的呢?memcached的分布式实现主要依赖客户端的实现:

memcached分布式
如上图所示,我们看下缓存的存储的一般流程:
当数据到达客户端,客户端实现的算法就会根据“键”来决定保存的memcached服务器,服务器选定后,命令他保存数据。取的时候也一样,客户端根据“键”选择服务器,使用保存时候的相同算法就能保证选中和存的时候相同的服务器。
余数计算分散法
余数计算分散法是memcached标准的memcached分布式方法,算法如下:
CRC($key)%N
该算法下,客户端首先根据key来计算CRC,然后结果对服务器数进行取模得到memcached服务器节点,对于这种方式有两个问题值得说明一下:
1.当选择到的服务器无法连接的时候,一种解决办法是将尝试的连接次数加到key后面,然后重新进行hash,这种做法也叫rehash。
2.第二个问题也是这种方法的致命的缺点,尽管余数计算分散发相当简单,数据分散也很优秀,当添加或者移除服务器的时候,缓存重组的代价相当大。
Consistent Hashing算法
Consistent Hashing算法描述如下:首先求出memcached服务器节点的哈希值,并将其分配到0~2^32的圆上,这个圆我们可以把它叫做值域,然后用同样的方法求出存储数据键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上,如果超过0~2^32仍找不到,就会保存在第一台memcached服务器上:

再抛出上面的问题,如果新添加或移除一台机器,在consistent Hashing算法下会有什么影响。上图中假设有四个节点,我们再添加一个节点叫node5:

添加了node节点之后
node5被放在了node4与node2之间,本来映射到node2和node4之间的区域都会找到node4,当有node5的时候,node5和node4之间的还是找到node4,而node5和node2之间的此时会找到node5,因此当添加一台服务器的时候受影响的仅仅是node5和node2区间。