Memcache_分布式缓存
一、 Memcache简介
1. 什么要用到Memcache以及该能解决什么问题
- 高并发访问数据库的痛楚:死锁!
- 磁盘IO之痛
- 多客户端共同缓存
- NET+Memory>>IO
- 读写性能完美 1S读取可以1W次,写10万次
- 超简单集群搭建Cluster
- 开源open Source
- 没有提供主从赋值功能,也没有提供容灾等功能,所以所有的diamante基本都只是考虑性能最佳(Redis)
- 学习成本低,入门简单
二、 Memcache基本原理
- Socket 服务器端 底层
- 数据:键值对存储
- 内存处理的算法:
本质就是一个大的哈希表。key最大长度是255个字符。
内存模型:Memcache预先将可支配的内存空间进行分区(Slab),每个分区里再分成多个块(Chunk)大小1MB,但同一个分区里:块的长度(bytes)是固定的。
插入数据:查找适合自己长度的块,然后插入,会有内存浪费。
LRU,闲置>过期 >最少访问
惰性删除:它并没有提供监控数据过期的机制,而是惰性的,当查询到某个key数据时,如果过期那么直接抛弃。
集群搭建原理:
Memcache服务器端并没有提供集群功能,但是通过客户端的驱动程序实现了集群配置。
客户端实现集群的原理:首先客户端配置多台集群机器的ip和端口的列表。然后客户端驱动程序在写入之前,首先对key做哈希处理得到哈希值后对总的机器的个数进行取余然后就选择余数对应的机器。
三、 Memcache安装
- 下载Memcache:http://code.jellycan.com/Memcache/
- 将服务程序拷贝到一个磁盘上的目录
- 安装服务:
- 首先进入cmd命令行,输入命令cd: D:\资料\自学 Memcached\memcache 其实就是进入文件存放的路径中
- →Memcached.exe -d install 打开服务监控窗口可以查看服务是否启动。
-
- 启动服务:cmd→Memcached.exe -d start(restart重启,stop关闭服务)
- 检查服务是否启动:安装一个telnet 客户端与服务端,连接到Memcache控制台:telnet ServerIP 11211 输入命令:stats检查当前服务状态。
- stats状态统计对应图
-
- 卸载服务:先定位到程序所在的目录,在cmd执行Memcached.exe -d stop(停止服务) Memcached.exe -d uninstall(先关闭服务)
- 遇到问题:win8下安装服务。无法启动此程序,因为计算机中丢失 MSVCR71.dll。尝试重新安装该程序以解决此问题。下载dll地址:http://www.dll-files.com/dllindex/dll-files.shtml?msvcr71
四、 MemcacheHelper封装
1. 将Commons.dll,ICSharpCode.SharpZipLib.dll,log4net.dll,Memcached.ClientLibrary.dll 等放到bin目录
2. 引用Memcached.ClientLibrary.dll,log4net.dll
3. 代码
using Memcached.ClientLibrary; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Memcached { class Program { static void Main(string[] args) { //指定ip地址和端口号 string[] serverlist = { "127.0.0.131:11211", "10.0.0.132:11211" }; //初始化池 SockIOPool pool = SockIOPool.GetInstance(); pool.SetServers(serverlist); pool.InitConnections = 3; //连接次数 pool.MinConnections = 3; //最小连接次数 pool.MaxConnections = 5; //最大连接次数 pool.SocketConnectTimeout = 1000; pool.SocketTimeout = 3000; pool.MaintenanceSleep = 30; pool.Failover = true; pool.Nagle = false; pool.Initialize(); // 获得客户端实例 MemcachedClient mc = new MemcachedClient(); mc.EnableCompression = false; Console.WriteLine("------------测 试-----------"); mc.Set("test", "my value"); // set指向服务端写数据,存储数据到缓存服务器,这里将字符串"my value"缓存,key 是"test" if (mc.KeyExists("test")) //测试缓存存在key为test的项目 { Console.WriteLine("test is Exists"); Console.WriteLine(mc.Get("test").ToString()); //在缓存中获取key为test的项目 } else { Console.WriteLine("test not Exists"); } Console.ReadLine(); mc.Delete("test"); //移除缓存中key为test的项目 if (mc.KeyExists("test")) { Console.WriteLine("test is Exists"); Console.WriteLine(mc.Get("test").ToString()); } else { Console.WriteLine("test not Exists"); } Console.ReadLine(); SockIOPool.GetInstance().Shutdown(); //关闭池, 关闭sockets } } }
结果:
4. 封装在common类库文件夹中,注意,需要引用Memcached.ClientLibrary.dll,log4net.dll
具体封装代码:
using Memcached.ClientLibrary; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Common { public class MemcacheHelper { private static readonly MemcachedClient mc = null; static MemcacheHelper() { //最好放在配置文件中 string[] serverlist = { "127.0.0.1:11211", "10.0.0.132:11211" }; //初始化池 SockIOPool pool = SockIOPool.GetInstance(); pool.SetServers(serverlist); pool.InitConnections = 3; pool.MinConnections = 3; pool.MaxConnections = 5; pool.SocketConnectTimeout = 1000; pool.SocketTimeout = 3000; pool.MaintenanceSleep = 30; pool.Failover = true; pool.Nagle = false; pool.Initialize(); // 获得客户端实例 mc = new MemcachedClient(); mc.EnableCompression = false; } /// <summary> /// 存储数据 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public static bool Set(string key,object value) { return mc.Set(key, value); } /// <summary> /// 重载,可以设置过期时间 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="time"></param> /// <returns></returns> public static bool Set(string key, object value,DateTime time) { return mc.Set(key, value,time); } /// <summary> /// 获取数据 /// </summary> /// <param name="key"></param> /// <returns></returns> public static object Get(string key) { return mc.Get(key); } /// <summary> /// 删除 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool Delete(string key) { if (mc.KeyExists(key)) { return mc.Delete(key); } return false; } } }