Memcached高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度。Memcached能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。

Memcached的特点
Memcached的缓存是一种分布式的,可以让不同主机上的多个用户同时访问, 因此解决了共享内存只能单机应用的局限,更不会出现使用数据库做类似事情的时候,磁盘开销和阻塞的发生。

memcache的优点:

1.解决了高并发访问数据库造成的死锁

2.实现了多客户端的共享缓存

3.读写性快,1s:读取可以1w次,写:10w

4.超简单集群搭建Cluster

5.开源代码

6.学习成本低、入门容易、丰富的成功案例

缺点:

没有提供主从复制功能,也没有提供容灾等功能,数据存在缓存中(例如服务器重启就会丢失数据),所有的代码基本只是考虑性能最佳。

Memcache 基础原理

底层通讯:Socket

数据:键值对存储,key最大255个字符,item最大1MB,当然key/item最好都别太大,最长过期时间是30天

内存处理的算法:

本质就是一个大的哈希表。key最大长度是255个字符。

内存模型:Memcache预先将可支配的内存空间进行分区(Slab),每个分区里再分成多个块(Chunk)大小1MB,但同一个分区里:块的长度(bytes)是固定的。

插入数据:查找适合自己长度的块,然后插入,会有内存浪费。

LRU,闲置>过期 >最少访问

惰性删除:它并没有提供监控数据过期的机制,而是惰性的,当查询到某个key数据时,如果过期那么直接抛弃。

集群搭建原理:

Memcache服务器端并没有提供集群功能,但是通过客户端的驱动程序实现了集群配置。 客户端实现集群的原理:首先客户端配置多台集群机器的ip和端口的列表。然后客户端驱动程序在写入之前,首先对key做哈希处理得到哈希值后对总的机器的个数进行取余然后就选择余数对应的机器。

Windows下使用Memcache

下载Memcache

安装服务:以管理员的身份打开cmd进入memcache所在文件夹,输入安装命令:Memcached.exe -d install

打开服务会看到memcached已安装

打开服务监控窗口可以查看服务是否启动。 启动服务:cmd→Memcached.exe -d start(restart重启,stop关闭服务)

检查服务是否启动:

1.开启telnet

2.在控制台输入命令:telnet 192.168.1.22 11211(ip地址  端口号:默认为11211)

通过 memcached.exe -h 可以查看其帮助

3.在控制台输入命令检查当前服务状态:stats

卸载服务:Memcached.exe -d uninstall(先关闭服务)

遇到问题:win8下安装服务。无法启动此程序,因为计算机中丢失 MSVCR71.dll。尝试重新安装该程序以解决此问题。下载dll地址:http://www.dll-files.com/dllindex/dll-files.shtml?msvcr71

二   .NET memcached client library
   下载文件:https://sourceforge.net/projects/memcacheddotnet/

里面有.net1.1  和 .net2.0的两种版本  还有一个不错的例子。

三  应用

1 将Commons.dll,ICSharpCode.SharpZipLib.dll,log4net.dll,Memcached.ClientLibrary.dll 放到lib目录,如果项目中已存在log4net.dll则不需要再引用
  2 项目右击添加引用
  3 代码

using Memcached.ClientLibrary;
using System; namespace CZBK.ItcastOA.MemcaheDemo
{
class Program
{
static void Main(string[] args)
{
//ip地址:端口号
string[] serverlist = { "192.168.1.95:11211", "10.0.0.132:11211" }; //初始化池
SockIOPool pool = SockIOPool.GetInstance();
pool.SetServers(serverlist); pool.InitConnections = ;
pool.MinConnections = ;
pool.MaxConnections = ; pool.SocketConnectTimeout = ;
pool.SocketTimeout = ; pool.MaintenanceSleep = ;
pool.Failover = true; pool.Nagle = false;
pool.Initialize(); // 获得客户端实例
MemcachedClient mc = new MemcachedClient();
mc.EnableCompression = false; Console.WriteLine("------------测 试-----------");
mc.Set("test", "my value"); //存储数据到缓存服务器,这里将字符串"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
}
}
}

 新建同一过滤器类BaseController,在控制器中把继承的Controller换成BaseController

BaseController类过滤器代码

using CZBK.ItcastOA.Common;
using CZBK.ItcastOA.Model;
using System;
using System.Web.Mvc; namespace CZBK.ItcastOA.WebApp.Controllers
{
public class BaseController : Controller
{
/// <summary>
/// 记录登陆用户
/// </summary>
public UserInfo LoginUser { get; set; }
/// <summary>
/// 执行控制器前执行该方法
/// </summary>
/// <param name="filterContext"></param>
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
base.OnActionExecuting(filterContext);
bool isExt = false;
//if (Session["userInfo"]==null)
if(Request["sessionId"]!=null)
{
//接收从cookie中传过来的Memcache的key
string sessionId = Request.Cookies["sessionId"].Value;
//根据key从Memcache中获取用户的信息
object obj = MemcacheHelper.Get(sessionId);
if (obj!=null)
{
UserInfo userInfo = SerializerHelper.DeserializeToObject<UserInfo>(obj.ToString());
LoginUser = userInfo;
isExt = true;
//模拟滑动过期时间
MemcacheHelper.Set(sessionId,obj.ToString(),DateTime.Now.AddMinutes());
} }
if (!isExt)
{
//此跳转会执行完index的方法返回结果才去跳转到登录页面,所以不能用这种方法跳转
//filterContext.HttpContext.Response.Redirect("/Login/Index");
//此方法直接跳转到登录页面,后面的代码不会执行
filterContext.Result = Redirect("/Login/Index");
}
}
}
}

登录页面代码

using CZBK.ItcastOA.Common;
using CZBK.ItcastOA.IBLL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; namespace CZBK.ItcastOA.WebApp.Controllers
{
public class LoginController : Controller
{
IUserInfoService UserInfoService { get; set; }
// GET: Login
public ActionResult Index()
{
//登录时判断Cookie的信息
CheckCookieInfo();
return View();
} #region 获取验证码
public ActionResult GetCodeImage()
{
ValidateCode vlidatecode = new ValidateCode();
//产生验证码
string code = vlidatecode.CreateValidateCode();
//存到session中验证
Session["validatecode"] = code;
//将验证码画到画布上,返回文件
byte[] buffer = vlidatecode.CreateValidateGraphic(code);
//返回文件
return File(buffer, "image/jpeg");
}
#endregion #region 用户登录
public ActionResult UserLogin()
{
//获取验证码验证是否正确
//验证码为空
string validatecode = Session["validatecode"] != null ? Session["validatecode"].ToString() : string.Empty;
if (string.IsNullOrEmpty(validatecode))
{
return Content("no:验证码错误!");
} //验证码不为空
//清空session
Session["validatecode"] = null;
//获取前台输入的code
string txtcode = Request["vCode"].ToString();
//比较验证码忽略大小写
if (!validatecode.Equals(txtcode, StringComparison.InvariantCultureIgnoreCase))
{
return Content("no:验证码错误!");
} //验证用户名和密码
string userName = Request["LoginCode"];
string userPwd = Request["LoginPwd"];
var userInfo = UserInfoService.LoadEntities(a => a.UName == userName && a.UPwd == userPwd).FirstOrDefault();
if (userInfo != null)
{
//记住登录账号
//Session["userInfo"] = userInfo; //用memcache存储用户信息
//作为Memcache的key
string sessionId = Guid.NewGuid().ToString();
//使用Memcache代替Session解决数据在不同Web服务器之间共享的问题。
MemcacheHelper.Set(sessionId, SerializerHelper.SerializeToString(userInfo), DateTime.Now.AddMinutes());
//将Memcache的key以cookie的形式返回到浏览器端的内存中,当用户再次请求其它的页面请求报文中会以Cookie将该值再次发送服务端。
Response.Cookies["sessionId"].Value = sessionId; //记住登录账号
if (!string.IsNullOrEmpty(Request["checkMe"]))
{
HttpCookie cookie1 = new HttpCookie("cp1", userInfo.UName);
//HttpCookie cookie2 = new HttpCookie("cp2", WebCommon.GetMd5String(userInfo.UPwd));
HttpCookie cookie2 = new HttpCookie("cp2", userInfo.UPwd);
cookie1.Expires = DateTime.Now.AddDays();
cookie2.Expires = DateTime.Now.AddDays();
Response.Cookies.Add(cookie1);
Response.Cookies.Add(cookie2);
}
return Content("ok:登录成功!");
}
return Content("no:登录失败!");
}
#endregion #region 登录时判断Cookie的信息
private void CheckCookieInfo()
{
if (Request.Cookies["cp1"] != null && Request.Cookies["cp2"] != null)
{
string userName = Request.Cookies["cp1"].Value;
string userPwd = Request.Cookies["cp2"].Value;
//判断Cookie中存储的用户名和密码是否正确
var userInfo = UserInfoService.LoadEntities(a => a.UName == userName && a.UPwd == userPwd).FirstOrDefault();
if (userInfo != null)
{
//再次记录到Memcache中,30分钟过期
string sessionId = Guid.NewGuid().ToString();
MemcacheHelper.Set(sessionId, SerializerHelper.SerializeToString(userInfo), DateTime.Now.AddMinutes());
Response.Cookies["sessionId"].Value = sessionId;
Response.Redirect("/home/Index");
}
//Response.Redirect表示重定向页面,如果执行Response.Redirect代码则下两句代码不执行
//存在cookies但是错误则设置过期
Response.Cookies["cp1"].Expires = DateTime.Now.AddDays(-);
Response.Cookies["cp2"].Expires = DateTime.Now.AddDays(-);
}
}
#endregion #region 退出登录
public ActionResult Logout()
{
if (Request.Cookies["sessionId"] != null)
{
string key = Request.Cookies["sessionId"].Value;
Common.MemcacheHelper.Delete(key);
Response.Cookies["cp1"].Expires = DateTime.Now.AddDays(-);
Response.Cookies["cp2"].Expires = DateTime.Now.AddDays(-);
}
return Redirect("/Login/Index");
}
#endregion
}
}

关于用户登录状态存session,cookie还是数据库或者memcache的优劣

memcached参考链接:

http://www.cnblogs.com/zjneter/archive/2007/07/19/822780.html

http://www.cnblogs.com/xulb597/archive/2012/11/21/2780506.html

Memcache+Cookie解决分布式系统共享登录状态的更多相关文章

  1. Memcache+Cookie解决分布式系统共享登录状态------------------------------Why Memcached?

    每个用户请求向IIS发送一个请求,但IIS服务器的请求数有限,cpu支持的线程数有限,如果一秒钟向这台服务器发送10000次,那么则一般就会有问题,考虑集群, 请求数据分流,几台服务器共同对应一个公共 ...

  2. Lab: Brute-forcing a stay-logged-in cookie:点击保持登录状态返回的Cookie里面破解账号密码靶场复盘

    靶场内容: 此实验室允许用户在关闭浏览器会话后仍保持登录状态.用于提供此功能的 cookie 容易受到暴力破解. 为了解决实验室问题,暴力破解 Carlos 的 cookie 以访问他的"我 ...

  3. 【wpf WebBrowser 清空网站的Cookie&Session 清空用户登录状态】

    最近做项目遇到了一个说小不小,说大不大的问题,那就是在WebBrowser中清空网站上用户的登陆状态, 一开始心想,那不就清空cookies就行啦,那么简单的事情,百度一下 …… …… 是的,正如你们 ...

  4. session、cookie 记住登录状态的实现

    Cookie的机制 Cookie是浏览器(User Agent)访问一些网站后,这些网站存放在客户端的一组数据,用于使网站等跟踪用户,实现用户自定义功能. Cookie的Domain和Path属性标识 ...

  5. 使用robotframework做接口测试三——保持登录状态

    调用登录接口登录了,其他的接口怎么保持登录状态呢?  首先来看一看,web端或者说客户端是怎么样用cookie/token等保持登录状态的.一般来说,cookie都会在登录接口由服务端返回,而且会是在 ...

  6. JMeter 怎么保存登录状态

    在Recording Controller中添加一个HTTP Cookie Manager Recording Controller右键-->add-->config element--& ...

  7. uni-app 保持登录状态 (Vuex)

    在小程序中,保持登录状态是很常见的需求,今天就把写一写使用uni-app框架的保持登录状态功能是怎样实现的. 一.场景需求 1.场景:初始打开---登陆---关闭,再次打开---(已登录)上次关闭前的 ...

  8. session、cookie与“记住我的登录状态”的功能的实现

    Cookie的机制 Cookie是浏览器(User Agent)访问一些网站后,这些网站存放在客户端的一组数据,用于使网站等跟踪用户,实现用户自定义功能. Cookie的Domain和Path属性标识 ...

  9. Postman+Postman interceptor的安装和使用-解决把chrome浏览器登录状态同步到postman进行有依赖的接口测试 Postman 使用方法详解

    Postman+Postman interceptor的安装和使用-解决把chrome浏览器登录状态同步到postman进行有依赖的接口测试   问题引入:做接口测试时,有依赖关系的接口往往不好测试( ...

随机推荐

  1. axios和ajax,fetch的区别

    1,传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回 ...

  2. javascript实现复选框单选多选!

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  3. 离不开的微服务架构,脱不开的RPC细节(值得收藏)!!!

    服务化有什么好处? 服务化的一个好处就是,不限定服务的提供方使用什么技术选型,能够实现大公司跨团队的技术解耦,如下图所示: 服务A:欧洲团队维护,技术背景是Java 服务B:美洲团队维护,用C++实现 ...

  4. 使用Wamp搭建Php本地开发环境,HBuilder调试

    初涉Php,此处做点笔记,希望下次不要能够轻松应对,至少不要在入同一个坑 本文摘要: wamp和HBuilder和Mysql5.7的安装包 Wamp的使用,包括80端口,443端口的占用问题 HBui ...

  5. Scala 语法(一)

    (1)基本语法 变量 val var(可变变量): 数据类型 Byte,Char,Int,Short,Long,String(字符),Float,Double,Boolean(true,flase). ...

  6. 2.3 摄像头驱动_vivi驱动程序分析

    学习目标:熟悉vivi的调用过程,分析vivi程序源码的ioctl函数: 一.vivi虚拟视频驱动测试方法 当我们接上usb摄像头设备时,系统会自动给我们安装对应的usb设备驱动程序.如果下次直接测试 ...

  7. 《C++ Primer》第II部分:C++标准库

    <C++ Primer>第II部分:C++标准库 前言 把<C++ Primer>读薄系列笔记.本篇为第II部分C++标准库,包含全书第8-12章重难点: IO库 顺序容器 范 ...

  8. NB-IOT连接移动onenet平台流程

    1. 先创建账号,然后创建产品 2. 创建设备,用AT+CGSN和AT+CIMI查询NB-IOT的IMEI和IMSI填写上去. 3. 创建好的设备.

  9. 【费元星原创】一键安装Hadoo2.7.6 集群完全分布式脚本-完美解决

    有Bug 欢迎反馈,我不烦:feiyuanxing@gmail.com 1 #!/bin/bash #@author:feiyuanxing [既然笨到家,就要努力到家] #@date:2017-01 ...

  10. [转帖]localhost与127.0.0.1的区别

    localhost与127.0.0.1的区别 https://www.cnblogs.com/hqbhonker/p/3449975.html 前段时间用PG的时候总有问题 当时没有考虑 localh ...