1、什么是Redis
Redis是一个开源的使用
ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
2.与其他用户状态保存方案比较
一般开发中用户状态使用session或者cookie,两种方式各种利弊。
Session:在InProc模式下容易丢失,并且引起并发问题。如果使用SQLServer或者SQLServer模式又消耗了性能
Cookie则容易将一些用户信息暴露,加解密同样也消耗了性能。
Redis采用这样的方案解决了几个问题,
1.Redis存取速度快。
2.用户数据不容易丢失。
3.用户多的情况下容易支持集群。
4.能够查看在线用户。
5.能够实现用户一处登录。(通过代码实现,后续介绍)
封装以后
这里我利用了MVC3中的ActionFilter,拦截用户的所有请求
在Global.asax中要注册一下
5.调用方式
调用方法
2.与其他用户状态保存方案比较
一般开发中用户状态使用session或者cookie,两种方式各种利弊。
Session:在InProc模式下容易丢失,并且引起并发问题。如果使用SQLServer或者SQLServer模式又消耗了性能
Cookie则容易将一些用户信息暴露,加解密同样也消耗了性能。
Redis采用这样的方案解决了几个问题,
1.Redis存取速度快。
2.用户数据不容易丢失。
3.用户多的情况下容易支持集群。
4.能够查看在线用户。
5.能够实现用户一处登录。(通过代码实现,后续介绍)
6.支持持久化。(当然可能没什么用)
2.实现思路
初始化配置
初始化配置 {
一个调用的例子其他的具体看源码
2.实现思路
1.我们知道session其实是在cookie中保存了一个sessionid,用户每次访问都将sessionid发给服务器,服务器通过ID查找用户对应的状态数据。3.Redis调用接口在这里我的处理方式也是在cookie中定义一个sessionid, 程序需要取得用户状态时将sessionid做为key在Redis中查找。2.同时session支持用户在一定时间不访问将session回收。借用Redis中Keys支持过期时间的特性支持这个功能,但是在续期方面需要程序 自行拦截请求调用这个方法(demo有例子)下面开始代码说明
首先引用ServiceStack相关DLL。
在web.config添加配置,这个配置用来设置Redis调用地址每台服务用【,】隔开。主机写在第一位
普通浏览
复制代码
-
1 <appSettings>
-
2
-
3 <!--每台Redis之间用,分割.第一个必须为主机-->
-
4 <add key= "SessionRedis" value= "127.0.0.1:6384,127.0.0.1:6384"/>
-
5
-
6 </appSettings>
初始化配置 {
|
一个调用的例子其他的具体看源码
-
/// <summary>
-
/// 写入
-
/// </summary>
-
/// <typeparam name="F"></typeparam>
-
/// <param name="doWrite"></param>
-
/// <returns></returns>
-
public F TryRedisWrite<F> (Func<IRedisClient, F> doWrite )
-
{
-
PooledRedisClientManager prcm = new Managers ( ).GetClientManagers ( ) ;
-
IRedisClient client = null ;
-
try
-
{
-
using (client = prcm.GetClient ( ) )
-
{
-
return doWrite (client ) ;
-
}
-
}
-
catch (RedisException )
-
{
-
throw new Exception ( "Redis写入异常.Host:" + client.Host + ",Port:" + client.Port ) ;
-
}
-
finally
-
{
-
if (client != null )
-
{
-
client.Dispose ( ) ;
-
}
-
}
-
}
-
//一个调用的例子其他的具体看源码
-
/// <summary>
-
/// 以Key/Value的形式存储对象到缓存中
-
/// </summary>
-
/// <typeparam name="T">对象类别</typeparam>
-
/// <param name="value">要写入的集合</param>
-
public void KSet (Dictionary< string, T> value )
-
{
-
Func<IRedisClient, bool> fun = (IRedisClient client ) =>
-
{
-
} ;
-
-
TryRedisWrite (fun ) ;
-
}
按上面说的给cookie写一个sessionid
-
/// <summary></font></font></p> /// 用户状态管理
-
/// </summary>
-
public class Session
-
{
-
/// <summary>
-
/// 初始化
-
/// </summary>
-
/// <param name="_context"></param>
-
public Session (HttpContextBase _context )
-
{
-
var context = _context ;
-
var cookie = context.Request.Cookies.Get (SessionName ) ;
-
if (cookie == null || string.IsNullOrEmpty (cookie.Value ) )
-
{
-
SessionId = NewGuid ( ) ;
-
context.Response.Cookies.Add ( new HttpCookie (SessionName, SessionId ) ) ;
-
context.Request.Cookies.Add ( new HttpCookie (SessionName, SessionId ) ) ;
-
}
-
else
-
{
-
SessionId = cookie.Value ;
-
}
-
}
-
-
}
-
/// <summary>
-
/// 获取当前用户信息
-
/// </summary>
-
/// <typeparam name="T"></typeparam>
-
/// <returns></returns>
-
public object Get<T> ( ) where T: class, new ( )
-
{
-
return new RedisClient<T> ( ).KGet (SessionId ) ;
-
}
-
-
/// <summary>
-
/// 用户是否在线
-
/// </summary>
-
/// <returns></returns>
-
public bool IsLogin ( )
-
{
-
return new RedisClient< object> ( ).KIsExist (SessionId ) ;
-
}
-
-
/// <summary>
-
/// 登录
-
/// </summary>
-
/// <typeparam name="T"></typeparam>
-
/// <param name="obj"></param>
-
public void Login<T> (T obj ) where T : class, new ( )
-
{
-
new RedisClient<T> ( ).KSet (SessionId, obj, new TimeSpan ( 0, Managers.TimeOut, 0 ) ) ;
-
}
默认用户没访问超过30分钟注销用户的登录状态,所以用户每次访问都要将用户的注销时间推迟30分钟
这需要调用Redis的续期方法
普通浏览
复制代码
-
/// <summary></font></font></p> /// 延期
-
/// </summary>
-
/// <param name="key"></param>
-
/// <param name="expiresTime"></param>
-
public void KSetEntryIn ( string key, TimeSpan expiresTime )
-
{
-
Func<IRedisClient, bool> fun = (IRedisClient client ) =>
-
{
-
client.ExpireEntryIn (key, expiresTime ) ;
-
return false ;
-
} ;
-
-
TryRedisWrite (fun ) ;
-
}
普通浏览
复制代码
-
/// <summary>
-
/// 续期
-
/// </summary>
-
public void Postpone ( )
-
{
-
new RedisClient< object> ( ).KSetEntryIn (SessionId, new TimeSpan ( 0, Managers.TimeOut, 0 ) ) ;
-
}
普通浏览
复制代码
-
namespace Test
-
{
-
public class SessionFilterAttribute : ActionFilterAttribute
-
{
-
/// <summary>
-
/// 每次请求都续期
-
/// </summary>
-
/// <param name="filterContext"></param>
-
public override void OnActionExecuting (ActionExecutingContext filterContext )
-
{
-
new Session (filterContext.HttpContext ).Postpone ( ) ;
-
}
-
}
-
}
普通浏览
复制代码
-
public static void RegisterGlobalFilters (GlobalFilterCollection filters )
-
{
-
filters.Add ( new SessionFilterAttribute ( ) ) ;
-
}
-
-
protected void Application_Start ( )
-
{
-
RegisterGlobalFilters (GlobalFilters.Filters ) ;
-
}
为了方便调用借用4.0中的新特性,把Controller添加一个扩展属性
普通浏览
复制代码
-
public static class ExtSessions</font></font></p>{ public static Session SessionExt ( this Controller controller )
-
{
-
return new Session (controller.HttpContext ) ;
-
}
-
}
普通浏览
复制代码
-
public class HomeController : Controller
-
{
-
public ActionResult Index ( )
-
{
-
this.SessionExt ( ).IsLogin ( ) ;
-
return View ( ) ;
-
}
-
}
7.后续SessionManager包含 获取用户列表数量,注销某个用户,根据用户ID获取用户信息,在线用户对象列表,在线用户SessionId列表等方法