怎么使用redis实现session功能

60次阅读
没有评论

共计 4965 个字符,预计需要花费 13 分钟才能阅读完成。

自动写代码机器人,免费开通

这篇文章主要介绍怎么使用 redis 实现 session 功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

我们来简单介绍下 redis。

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

1. 与其他用户状态保存方案比较

一般开发中用户状态使用 session 或者 cookie,两种方式各种利弊。

Session: 在 InProc 模式下容易丢失,并且引起并发问题。如果使用 SQLServer 或者 SQLServer 模式又消耗了性能

Cookie 则容易将一些用户信息暴露,加解密同样也消耗了性能。

Redis 采用这样的方案解决了几个问题,

1.Redis 存取速度快。

2. 用户数据不容易丢失。

3. 用户多的情况下容易支持集群。

4. 能够查看在线用户。

5. 能够实现用户一处登录。(通过代码实现,后续介绍)

6. 支持持久化。(当然可能没什么用)

2. 实现思路

1. 我们知道 session 其实是在 cookie 中保存了一个 sessionid,用户每次访问都将 sessionid 发给服务器,服务器通过 ID 查找用户对应的状态数据。

在这里我的处理方式也是在 cookie 中定义一个 sessionid,程序需要取得用户状态时将 sessionid 做为 key 在 Redis 中查找。

2. 同时 session 支持用户在一定时间不访问将 session 回收。

借用 Redis 中 Keys 支持过期时间的特性支持这个功能,但是在续期方面需要程序自行拦截请求调用这个方法(demo 有例子)

下面开始代码说明

3.Redis 调用接口

首先引用 ServiceStack 相关 DLL。

在 web.config 添加配置,这个配置用来设置 Redis 调用地址每台服务用【,】隔开。主机写在第一位

appSettings 
  !-- 每台 Redis 之间用, 分割. 第一个必须为主机 -- 
  add key= SessionRedis  value= 127.0.0.1:6384,127.0.0.1:6384 / 
 /appSettings

初始化配置

static Managers()
 {
 string sessionRedis= ConfigurationManager.AppSettings[ SessionRedis 
 string timeOut = ConfigurationManager.AppSettings[ SessionRedisTimeOut 
 if (string.IsNullOrEmpty(sessionRedis))
 {
 throw new Exception( web.config  缺少配置 SessionRedis, 每台 Redis 之间用, 分割. 第一个必须为主机 
 }
 if (string.IsNullOrEmpty(timeOut)==false)
 { TimeOut = Convert.ToInt32(timeOut);
 }
 var host = sessionRedis.Split(char.Parse( ,));
 var writeHost = new string[] { host[0] };
 var readHosts = host.Skip(1).ToArray();
 ClientManagers = new PooledRedisClientManager(writeHost, readHosts, new RedisClientManagerConfig
 {
 MaxWritePoolSize = writeReadCount,//“写”链接池链接数
 MaxReadPoolSize = writeReadCount,//“读”链接池链接数
 AutoStart = true
 });
 }

为了控制方面写了一个委托

///  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) = 
 { client.SetAll T (value);
 return true;
 };
 TryRedisWrite(fun);
 }

4. 实现 Session

按上面说的给 cookie 写一个 sessionid

///  summary 
 ///  用户状态管理
 ///  /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));
 }

6. 续期

默认用户没访问超过 30 分钟注销用户的登录状态,所以用户每次访问都要将用户的注销时间推迟 30 分钟

这需要调用 Redis 的续期方法

///  summary 
 ///  延期
 ///  /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));
}

这里我利用了 MVC3 中的 ActionFilter,拦截用户的所有请求

namespace Test
 public class SessionFilterAttribute : ActionFilterAttribute
 {
 ///  summary 
 ///  每次请求都续期
 ///  /summary 
 ///  param name= filterContext /param 
 public override void OnActionExecuting(ActionExecutingContext filterContext)
 { new Session(filterContext.HttpContext).Postpone();
 }
 }
}

在 Global.asax 中要注册一下

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
 { filters.Add(new SessionFilterAttribute());
 }
 protected void Application_Start()
 { RegisterGlobalFilters(GlobalFilters.Filters);
 }

5. 调用方式

为了方便调用借用 4.0 中的新特性,把 Controller 添加一个扩展属性

public static class ExtSessions
{public static Session SessionExt(this Controller controller)
 { return new Session(controller.HttpContext);
 }
}

调用方法:

public class HomeController : Controller
 { public ActionResult Index()
 { this.SessionExt().IsLogin();
 return View();
 }
 }

以上是“怎么使用 redis 实现 session 功能”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!

向 AI 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计4965字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)