上一片讲到Memcached在Windows上的安装,和用Telnet工具进行命令操作,在稍微了解了原理之后,我也就开始尝试着用程序来对Memcached进行操作。这一篇分为两个部分,第一部分是用.net程序对Memcached进行操作,第二部分是结合mvc实现一个分布式的缓存系统。

一、.net程序对Memcached进行操作

  想要用.net操作Memcached,首先我们的去下载.NET客户端类库:https://sourceforge.net/projects/memcacheddotnet,下载完成之后,会发现里面有一些Demo,而需要引用的程序集就只有ICSharpCode.SharpZipLib.dll,Memcached.ClientLibrary.dll,log4net.dll(可有可无)。

  

  

  上图就是创建了一个控制台应用程序,将这三个程序集引入项目。之后,将Memcached服务打开。再之后,就是代码。  

  

            string[] serverlist = { "127.0.0.1:11211" };
SockIOPool sock = SockIOPool.GetInstance();   
sock.SetServers(serverlist);//添加服务器列表 
sock.InitConnections = ;//设置连接池初始数目
sock.MinConnections = ;//设置最小连接数目
sock.MaxConnections = ;//设置最大连接数目
sock.SocketTimeout = ;//设置套接字超时读取      
sock.MaintenanceSleep = ; //设置维护线程运行的睡眠时间。如果设置为0,那么维护线程将不会启动;
sock.Failover = true; //获取或设置池的故障标志。          
sock.MaxBusy = * ; //socket单次任务的最大时间(单位ms),超过这个时间socket会被强行中断,当前任务失败
sock.Initialize(); MemcachedClient mc = new MemcachedClient();
//清除所有的缓存数据
mc.FlushAll(); //增加
mc.Add("k","hello");
//增加一个键k1,值是hello1,有效时间是30s
mc.Add("k1", "hello1", DateTime.Now.AddSeconds()); // 将k的值重新设置为123 ,用set时,假如键存在,就直接修改,键不存在,就直接创建,再赋值
mc.Set("k","");
//将k的值重置为456 , 用Replace时,假如键存在,就直接修改,键不存在,报错
mc.Replace("k", ""); //删除
mc.Delete("k");

  到这里,我们用程序操作Memcached已经成功,我们程序运行完成之后,可以用telnet链接,看看数据是否加载进去了。这个比较简单,下面看个复杂点的。

二、Memcache+cookie实现模拟session

  1.session的使用原理

  以前在开发系统中,像用户这些基本信息,是直接保存在session中的,原理就是如下图所示,用户第一次访问时,服务器创建session,并把sessionid写回浏览器的cookie中,之后,浏览器每次访问服务器时,就把这个sessionid一同和其他数据发送到服务器端,这样就解决了Http协议是无状态链接这个问题了。简单原理就是这样,更加详细的session介绍详见http://www.cnblogs.com/lyzg/p/6067766.html(图也是人家的*-*)。

  

  2.Memcache+cookie代替session

  总的来说,session也不是完美的,会有易丢失,耗资源,单台服务器时还好,一遇到集群,就有点尴尬了,所以现在就模拟一下这个情况。这个例子的整体结构是这样子,搭建两个web服务器,同样也搭建两个Memcached服务器,好吧,双集群。

  1-6这个过程是,当用户从web1站点登陆,先去查询Memcached集群里是否有用户信息,这个肯定没有,之后就去数据库查,查到之后,就把用户的信息给存到Memcached中,具体存到哪个,这个先不做谈论。

  7-10过程,用户通过web2站点 访问数据,先去Memcached集群里查是否有信息(这个如何查的也先不做谈论),查到后,就直接把信息返回。

  接下来,我们就新建项目,添加引用,项目的结构如图所示,一个mvc4的框架,数据库链接用的是dapper。项目用了过滤器,写在BaseController里面,并且在Global.asax文件里要进行注册,其中UserLoginController没有继承BaseController,HomeController继承了BaseController。

  

  重要的代码有两段,一段就是登陆时候成功后,用guid生成随机数,将这个随机数作为seeionid写到浏览器的cookie中,同时把该用户的信息,sessionid这些信息存到Memcached中。

   string sql = "select * from UserInfo where UName=@UName and UPwd=@UPwd";
using (var conn = SqlHelper.Connection)
{
var loginUser1 = conn.QueryFirstOrDefault<UserInfo>(sql, new { UName = user.UName, UPwd = user.UPwd });
var loginUser = SqlMapper.QueryFirstOrDefault<UserInfo>(conn,sql, new { UName = user.UName, UPwd = user.UPwd });
if (loginUser == null)
{
return Content("用户名密码错误!");
}
else
{
Guid sessionId = Guid.NewGuid();//申请了一个模拟的GUID:SessionId //把sessionid写到客户端浏览器里面去了(一定要把sessionid写到客户端,这样用户在访问其他web资源的时候,
// 就会把cookie中的信息传给服务器,然后通过sessionid的key到Memcached中去取对应的值)
Response.Cookies["sessionId"].Value = sessionId.ToString(); //再把用户的信息插入到Memcached中
MemcacheHelper.Set(sessionId.ToString(), loginUser, DateTime.Now.AddMinutes());
return Content("ok");
}
}

  而另一段比较重要的代码就写在过滤器里,根据浏览器发过来的sessionid来去memcache中查询数据,查到的话,表示校验成功,否则跳转回登陆界面。

 protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext); //从cookie中获取咱们的 登录的sessionId
string sessionId = Request["sessionId"];
//如果sessionid为空值,则跳转到登录页面
if (string.IsNullOrEmpty(sessionId))
{
//return RedirectToAction("Login", "Logon");
Response.Redirect("/UserLogin/Index");
return;
} object obj = MemcacheHelper.Get(sessionId);
UserInfo user = obj as UserInfo;
if (user == null)
{
//用户长时间不操作,。超时。
Response.Redirect("/UserLogin/Index");
} LoginUser = user;
//实现session的滑动机制
MemcacheHelper.Set(sessionId, user, DateTime.Now.AddMinutes());
}

关于memcached集群的配置很简单,写在MemcacheHelper中,只需要将Memcache的服务地址写进去就行,以逗号分开,之后再设置一下权重就好了。

   //通过客户端来进行memcached的集群配置,在插入数据的时候,使用一致性哈希算法,将对应的value值存入Memcached
String[] serverlist = { "127.0.0.1:11211" , "127.0.0.1:11212" }; // 初始化Memcached的服务池
SockIOPool pool = SockIOPool.GetInstance("test");
//设置服务器列表
pool.SetServers(serverlist);
//各服务器之间负载均衡的设置比例
pool.SetWeights(new int[] { });
pool.Initialize();
//创建一个Memcached的客户端对象
mc = new MemcachedClient();
mc.PoolName = "test";
//是否启用压缩数据:如果启用了压缩,数据压缩长于门槛的数据将被储存在压缩的形式
mc.EnableCompression = false;

  之后,将网站发布到iis上的不同的端口号上就行了。要是想有调试效果, 直接将项目复制两份,其中一个端口号改下,启动就好了。

最后发现,当登陆一个网站成功后,我们再去访问另一个网站(不要换浏览器,cookie),发现也能直接访问了。

  这样一个关于memcached的分布式缓存系统就完成了,再写的过程,又是知识加深的过程,书常读常新,加油

Memcache+cookie实现模拟session的更多相关文章

  1. Cookie &amp;&amp; Session &amp;&amp; Token

    Cookies Cookie的由来: HTTP 本身是一个无状态的 request/response 协议. server接收一个来自client的request, 处理完以后返回一个response ...

  2. cookie编码乱码问题与cookie禁用后session操作

    Cookie传输的值只能是ASCII码,该编码表相对老旧不含有很多符号与文字 特别是中文,所以在cookie传值过程中需要先转成相应的ASCII编码再解析 如下 URLEncoder.encode(& ...

  3. cookie窃取和session劫持

    Updates 2014-08-17 感谢@搞前端的crosser的提醒,加入了HTTP Response Splitting的内容. 此篇文章的Presentation戳这里. 一.cookie的基 ...

  4. cookie机制和session机制的原理和区别[转]

    一.cookie机制和session机制的区别 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. 同时我们也看到,由于在服务器端保持状态的 ...

  5. cookie机制和session机制的区别(面试题)

    一.cookie机制和session机制的区别 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. 同时我们也看到,由于才服务器端保持状态的 ...

  6. PHP cookie禁用时session 方案

    在PHP中使用过SESSION的朋友可能会碰到这么一个问题,SESSION变量不能跨页传递.这令我苦恼了好些日子,最终通过查资料思考并解决了这个问题.我认为,出现这个问题的原因有以下几点: 1.客户端 ...

  7. session和cookie介绍以及session简单应用

    介绍http协议与TCP协议:        http协议:是短连接,关闭浏览器的时候断开与服务器的连接         TCP协议:是长连接,连接一直存在         http协议是在TCP协议 ...

  8. Cookie禁用 获取session

    转自:http://blog.csdn.net/u010433704/article/details/40950599 Cookie与 Session,一般认为是两个独立的东西,Session采用的是 ...

  9. 关于PHP中浏览器禁止Cookie后,Session能使用吗?

    sessionid是存储在cookie中的,解决方案如下: Session URL重写,保证在客户端禁用或不支持COOKIE时,仍然可以使用Session session机制.session机制是一种 ...

随机推荐

  1. android studio 2.32躺坑记

    按说这是没啥记录意义的.不过作为一个偶尔用一下ADT开发安卓程序的跨界老码农,遇到一个尴尬事,现在手机已经用上安卓6了,而电脑里的ADT里SDK还是18,19.越来越多的项目是android stud ...

  2. JavaScript设计模式_01_单例模式

    最近项目不太忙,难得有时间看看书,平时挺喜欢js这门语言.也看过很多高级教程,觉得自己还是比较热衷于js的设计模式.这一次重温一下<JavaScript设计模式与开发实践>,开篇为单例模式 ...

  3. Spring+SpringMVC+MyBatis深入学习及搭建(十一)——SpringMVC架构

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6985816.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十)--My ...

  4. 循环执行sql语句

    DECLARE --声明变量 SQL_ALLTABLES LONG; SQL_INSERT LONG; TYPE THE_CURSOR_TYPE IS REF CURSOR; --定义引用游标的数据类 ...

  5. 移动webAPP前端开发技巧汇总

    1. viewport:webapp视图 也就是可视区域.对于桌面浏览器,我们都很清楚viewport是什么,就是除去了所有工具栏.状态栏.滚动条等等之后用于看网页的区域,这是真正有效的区域.由于移动 ...

  6. AospExtended K3 Note最新官方版 Android7.1.2 极速 省电 流畅 Galaxy XIAOMI Moto Lenovo Coolpad 均支持

    AospExtended 最新官方版 Android7.1.2 极速 省电 流畅 Galaxy  XIAOMI Moto  Lenovo  Coolpad  均支持 之前用过1629开发版等,体验了很 ...

  7. 【Android Developers Training】 2. 运行你的应用

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  8. 5.Smart使用内置函数或者自定义函数

    1.使用内置函数 例如使用date函数 {"Y-m-d"|date:$time}格式{第一个参数|方法:第二个参数:第三个参数}即可转换成 2016-07-19  2.使用resi ...

  9. laravel怎么创建一个简单的blog

    主要功能实现:点击标题跳转 第一步:创建路由: Route::get('/articles','ArticlesController@index'); Route::get('/articles/{i ...

  10. 虚拟机VMware网络类型&&SSH远程连接Linux

    前言: Linux专题是16年11月开始写,说来惭愧,已经5个月没学Linux,至今感觉连入门还没达到.暑假实习有投运维开发岗位,无奈对Linux不熟悉,校招简历也被刷了.so, 我打算先花1个月内的 ...