Memcached分布式缓存快速入门

一、从单机到分布式

走向分布式第一步就是解决:多台机器共享登录信息的问题。
•例如:现在有三台机器组成了一个Web的应用集群,其中一台机器用户登录,然后其他另外两台机器共享登录状态?
•解决1:AspNet 进程外的Session。
•解决2:用数据库存储当前登录状态。
•解决3:Memcache (性能最好,类似的:Redis,NoSql)

 

二、为什么要使用Memcached?

•高并发访问数据库的痛楚:死锁!
•磁盘IO之痛:
•多客户端共享缓存
•Net + Memory  >> IO   
•读写性能完美  1s:读取可以1w次。 写:10w
•超简单集群搭建 Cluster
•开源 Open Source
•没有提供主从赋值功能,也没提供容灾等功能,单纯解决性能问题。(Redis有容灾功能,将内存数据备份到磁盘上)
•学习成本非常低,入门非常容易
•丰富的成功的案例
 
三、Memcached基础原理:
•位置:放在服务器端,通过Socket方式进行通信。
•数据:键值对存储
•内存处理的算法:
•本质就是一个大的哈希表。key最大长度是255个字符。
•内存模型:Memcache预先将可支配的内存空间进行分区(Slab),每个分区里再分成多个块(Chunk)大小1MB,但同一个分区里:块的长度(bytes)是固定的。
•插入数据:查找适合自己长度的块,然后插入,会有内存浪费。
•插入数据规则:闲置 > 过期 > 最少访问     
•惰性删除:它并没有提供监控数据过期的机制,而是惰性的,当查询到某个key数据时,如果过期那么直接抛弃。
•集群搭建原理:Memcache服务器端并没有提供集群功能,但是通过客户端的驱动程序实现了集群配置。
•客户端实现集群的原理:首先客户端配置多台集群机器的ip和端口的列表。然后客户端驱动程序在写入之前,首先对key做哈希处理得到哈希值后对总的机器的个数进行取余然后就选择余数对应的机器。

其他说明:
key最大255个字符,item内存块最大1MB,当然key/item最好都别太大,最长过期时间是30天 

Memcache预先将可支配的内存空间进行分区(Slab),每个分区里再分成多个块(Chunk),但同一个分区里:块的长度(bytes)是固定的。
将记录从Memcache删除后,已经分配的内存(即Chunk),也不会被释放,而是会重复利用,这样就彻底解决了内存碎片的问题
Memcache采用“惰性”方式来应对记录的超期问题


一致性哈希处理: http://www.cnblogs.com/lanceyan/archive/2013/05/13/3075044.html

解决多线程问题:
3. CAS的基本原理
Memcached于1.2.4版本新增CAS协议,类同于Java并发包中CAS(Compare and Set)原子操作,用来处理同一item被多个线程更改过程的并发问题.
基本原理非常简单,简而言之就是”版本号”.每个存储的数据对象都有一个版本号.在Memcached中,每个key关联有一个64bit长度的long型唯一数值,表示该key对应value的版本号.
这个数值由Memcached产生,从1开始,且同一Memcached不会重复,在两种情况下这个版本数值会加,即新增与更新,而删除item版本值不会减小.

我们可以从下面的例子来理解:
如果不采用CAS,则有如下的情景:
第一步,A取出数据对象X;
第二步,B取出数据对象X;
第三步,B修改数据对象X,并将其放入缓存;
第四步,A修改数据对象X,并将其放入缓存。
我们可以发现,第四步中会产生数据写入冲突。

如果采用CAS协议,则是如下的情景。
第一步,A取出数据对象X,并获取到CAS-ID1;
第二步,B取出数据对象X,并获取到CAS-ID2;
第三步,B修改数据对象X,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“一致”,就将修改后的带有CAS-ID2的X写入到缓存。
第四步,A修改数据对象Y,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“不一致”,则拒绝写入,返回存储失败。
View Code

 

使用场景:

缓存放频繁访问但很少变化的内容:
如:类别、禁用词(用正则匹配)、

string str = string.Join(list.ToArray()); //aa|bb|cc
Regex.IsMatch(msg,str);

 

四、Windows下使用Memcache

•下载Memcache服务程序:点击下载>>
•将服务程序拷贝到一个磁盘上的目录,如D:\Memcached
•安装服务:
cmd→ D: 回车 定位到D盘
cd D:\Memcached 回车 定位到D盘下Memcached目录
memcached.exe -d install 安装memcached服务
memcached.exe -d start   启动memcached服务  (打开服务监控窗口可以查看服务是否启动。restart重启,stop关闭服务)
 
•检查服务是否安装成功:
1.先确认已安装telnet客户端,未安装的先安装。安装教程>>
连接到Memcache控制台:telnet 服务器IP地址 11211  如:telnet 127.0.0.1 11211 (用本地测试的,如果是其他服务器则改为服务器地址。端口号11211为固定的。)
输入cmd命令检查:stats 检查当前服务状态。
出现上面信息则表示安装成功。
 
•卸载服务:Memcached.exe -d uninstall(先关闭服务)
•遇到问题:win8下安装服务。无法启动此程序,因为计算机中丢失 MSVCR71.dll。尝试重新安装该程序以解决此问题。下载dll地址:http://www.dll-files.com/dllindex/dll-files.shtml?msvcr71
 

其他说明:

将Memcache.exe安装为Windows服务:Memcache.exe -d install
启动Memcache服务:Memcache.exe -d start
启动Memcache服务(windows命令):net start "Memcache Server"
停止Memcache服务(windows命令):net stop "Memcache Server"
连接到Memcache控制台:telnet ServerIP 11211
打印当前Memcache服务器状态:stats
打印当前Memcache服务器Items(记录)的统计信息:stats items
打印当前Memcache服务器Slab(分区)及Chunk(块)的统计信息:stats slabs
打印指定Slab中的KEY列表(可用于遍历items,但效率较低,慎用!):stats cachedump SlabId Limit_num。显示结果:ITEM KeyName [ValueByteLength b; LastAccessTime s]。值得注意的是,经过测试确认:那个LastAccessTime并不是记录到期时间,而是最后一次的get时间,并且get之后,也不会自动延长expiry(到期时间)。
添加新记录:add KeyName 0 0 ValueByteLength [回车] ValueContent
删除记录 : delete KeyName
添加或更新记录 : set KeyName 0 0 ValueByteLength [回车] ValueContent
更新记录 : replace KeyName 0 0 ValueByteLength [回车] ValueContent
取值:get key
参考:http://www.cnblogs.com/lost-1987/articles/3069460.html

http://wenku.baidu.com/view/e30db586ec3a87c24028c401.html

也可以图形化监控 Memcached 的运行状态
http://livebookmark.net/journal/2008/05/21/memcachephp-stats-like-apcphp/

在 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\memcached Server 下面找到一个 ImagePath 的字符串项,正好是服务的执行路径的字符串,双击该串,在后面加入 -l 192.168.1.135 -m 45 -p 12345 (访问ip为:192.168.1.135 使用45M内存,12345为端口),再启动服务。
View Code

 

五、应用

1.下载.NET版memcached客户端API组件 放到自建的Lib文件夹

2.添加这些dll引用(Commons.dll,ICSharpCode.SharpZipLib.dll,log4net.dll)

3.封装MemcacheHelper代码如下:

public class MemcacheHelper
    {
        private static readonly MemcachedClient mc = new MemcachedClient();
static MemcacheHelper() //静态构造函数只会执行一次  { string[] serverlist = { "127.0.0.1:11211","10.0.0.132:11211" };//Memcache服务器IP地址和端口号,这里用本地机子进行测试。(可存放多个服务器信息,无效的服务器会自动被忽略。具体往哪台服务器存,会根据内部哈希算法自动去选择,不用我们去考虑。) //初始化池 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(); //获得客户端实例(可以认为是telnet或socket客户端) MemcachedClient mc = new MemcachedClient(); mc.EnableCompression = false; } /// <summary> /// 向Memcache存储数据 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public static void Set(string key, object value) { mc.Set(key, value); } public static void Set(string key, object value, DateTime time) { mc.Set(key, value, time);//绝对过期时间  } /// <summary> /// 获取Memcache中的数据 /// </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; } }

调用:

MemcacheHelper.Set("test","myValue");

如果存储复杂类型数据则需要进行序列号处理:

MemcacheHelper.Set(sessionId,SerializerHelper.SerializerToString(userInfo));

序列化处理:(添加dll引用:Newtonsoft.Json) 点击下载FrameWork4.5版本>>

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CZBK.HeiMaOA.Common
{
    public class SerializerHelper
    {
        public static string SerializerToString(object obj)
        {
            return JsonConvert.SerializeObject(obj);
        }
    }
}

 

 

六、源码下载:

点击下载>>

点击下载数据库文件>>

测试:

 

posted @ 2015-12-23 15:32  IT浪潮之巅  阅读(787)  评论(1编辑  收藏  举报
   友情链接: 淘宝优惠券