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区间。