用redis来实现Session保存的一个简单Demo

本文探讨了在使用Redis作为Session存储时如何避免内存浪费的问题。通过分析RedisSessionStateProvider的工作原理,提出了一种优化方案,即只保留一份Data数据,利用_Internal数据关联不同浏览器的Session。提供了一个简单的Demo,包括在用户登录时写入Redis和设置Cookie,以及利用Redis的过期时间管理Session过期。
摘要由CSDN通过智能技术生成

现在很多项目都用Redis(RedisSessionStateProvider)来保存Session数据,但是最近遇到一个比较典型的情况,需要把用户数据全部load到redis里面,在加上RedisSessionStateProvider本身的数据,造成很多内存的浪费。首先我们要知道Session会针对用户的数据,比如用户在chrome登录会保存一套信息,用ie登录有保存一套信息,用FF登录还是保存一套信息,那么redis就保存了3套一样的session data数据

 

如RedisSessionStateProvider默认会生成*****_Data来保存我们的session数据,******_Internal来记录session过期,这里的*****_2qfxy3ie51m5oneffzr0jkrd****和****_isudg4h01axx3lnd3pao4zcj****其实是用一个用户在2个浏览器上的数据,我们是否可以只保留一份****——Data数据,多分_Internal数据(用与表示到***_Data数据的关联)

demo如下:

  public class BaseController : Controller
    {
        string cookieName;
        public BaseController()
        {
            cookieName = SessionStateManage.CookieName;
            
            HttpCookie cookie = System.Web.HttpContext.Current.Request.Cookies[cookieName];
            if (cookie != null)
            {
                SessionCookieValue = cookie.Value;
                if (string.IsNullOrEmpty(SessionCookieValue))
                {
                    UserSession = SessionStateManage.GetUser(SessionCookieValue);
                }
            }

        }

        public void Login(UserInfo info)
        {
            string sessionID = Guid.NewGuid().ToString();
            System.Web.HttpContext.Current.Response.Cookies.Set(new HttpCookie(cookieName, sessionID));
            SessionStateManage.SetLogin(sessionID, info);
        }
        public string SessionCookieValue { set; get; }

        public UserInfo UserSession { set; get; }
    }
 public class HomeController : BaseController
    {
        public ActionResult Index()
        {         
            if (UserSession == null)
            {
                UserSession = new UserInfo { Email = "gavin@test", Password = "123", UserID = "1", UserName = "gavin" };
                Login(UserSession);
            }
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }

从当前请求中获取cookie,如果有就加载用户信息,如果没有我们在用户登录的时候除了写Redis还需要给浏览器写上cookie

  public class UserInfo
    {
        public string UserID { set; get; }
        public string UserName { set; get; }
        public string Password { set; get; }
        public string Email { set; get; }
    }
    public class SessionStateManage
    {
        static RedisHelper Redis;
        static SessionStateManage()
        {
            CookieName = ConfigurationManager.AppSettings["cookieName"] ?? "SESSION_ID";
            ApplicationName = ConfigurationManager.AppSettings["ApplicationName"] ?? "SESSION";

            Redis = new RedisHelper(1);

            Redis.SetSysCustomKey(ApplicationName);
            string sessionTimeOutStr = ConfigurationManager.AppSettings["SessionTimeOut"] ?? "20";
            SessionTimeOut = int.Parse(sessionTimeOutStr);
        }
        #region Property

        public static string CookieName { get; private set; }

        public static string ApplicationName { get; private set; }


        public static int SessionTimeOut { get; private set; }
        #endregion

        public static void SetLogin(string cookieName, UserInfo user)
        {
            Redis.StringSet(cookieName, user.UserID);
            Redis.KeyExpire(cookieName, new TimeSpan(0, SessionTimeOut, 0));

            Redis.HashSet(user.UserID, user);
        }

        public static UserInfo GetUser(string cookinNme)
        {
            string userID = Redis.StringGet(cookinNme);
            return userID == null ? null : Redis.HashGet<UserInfo>(userID);
        }

    }

用户的session过期直接用redis里面key的过期时间。redis操作需要辅助类如下:

/// <summary>
    /// ConnectionMultiplexer对象管理帮助类
    /// </summary>
    public static class RedisConnectionHelp
    {
        //系统自定义Key前缀
        public static readonly string SysCustomKey = ConfigurationManager.AppSettings["redisKey"] ?? "";

        //"127.0.0.1:6379,allowadmin=true
        private static readonly string RedisConnectionString = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString;

        private static readonly object Locker = new object();
        private static ConnectionMultiplexer _instance;
        private static readonly ConcurrentDictionary<string, ConnectionMultiplexer> ConnectionCache = new ConcurrentDictionary<string, ConnectionMultiplexer>();

        /// <summary>
        /// 单例获取
        /// </summary>
        public static ConnectionMultiplexer Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (Locker)
                    {
                        if (_instance == null || !_instance.IsConnected)
                        {
                            _instance = GetManager();
                        }
                    }
                }
                return _instance;
            }
        }

        /// <summary>
        /// 缓存获取
        /// </summary>
        /// <param name="connectionString"></param>
        /// <returns></returns>
        public static ConnectionMultiplexer GetConnectionMultiplexer(string connectionString)
        {
            if (!ConnectionCache.ContainsKey(connectionString))
            {
                ConnectionCache[connectionString] = GetManager(connectionString);
            }
            return ConnectionCache[connectionString];
        }

        private static ConnectionMultiplexer GetManager(string connectionString = null)
        {
            connectionString = connectionString ?? RedisConnectionString;
            var connect = ConnectionMultiplexer.Connect(connectionString);

            //注册如下事件
            connect.ConnectionFailed += MuxerConnectionFailed;
            connect.ConnectionRestored += MuxerConnectionRestored;
            connect.ErrorMessage += MuxerErrorMessage;
            connect.ConfigurationChanged += MuxerConfigurationChanged;
            connect.HashSlotMoved += MuxerHashSlotMoved;
            connect.InternalError += MuxerInternalError;

            return connect;
        }

        #region 事件

        /// <summary>
        /// 配置更改时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
        {
            Console.WriteLine("Configuration changed: " + e.EndPoint);
        }

        /// <summary>
        /// 发生错误时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
        {
            Console.WriteLine("ErrorMessage: " + e.Message);
        }

        /// <summary>
        /// 重新建立连接之前的错误
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
        {
            Console.WriteLine("ConnectionRestored: " + e.EndPoint);
        }

        /// <summary>
        /// 连接失败 , 如果重新连接成功你将不会收到这个通知
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            Console.WriteLine("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
        }

        /// <summary>
        /// 更改集群
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
        {
            Console.WriteLine("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
        }

        /// <summary>
        /// redis类库错误
        /// </summary>
        /// <param name="sender"></par
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值