您的位置:首页 > 数据库 > Redis

Redis中的StackExchange.redis在C#中的应用

2017-09-15 15:02 423 查看
Redis,基于这种Key-Value的内存数据库很适合来做分布式Session。本示例将基于StackExchange.Redis.dll进行实现,序列化使用的是Newtonsoft.json.dll。

为了避免APP等客户端重复登录导致同一个用户出现重复的Session,将以ServerID(可以是数据库主键)为服务端令牌,并生成一个新的GUID作为其客户端令牌,客户端令牌将返回给客户端。

两个令牌都将存储在Redis中,形成2个键值对,在服务端令牌中保存了其对应的客户端令牌ID。当同一用户再次登录时,将首先检查是否有基于其ServerID的服务端令牌存在,如果存在,则直接取其值(客户端令牌)返回给客户端,以此避免重复的Session浪费。



Web.config:

[csharp] view
plain copy

 print?

<!--Redis数据库编号(范围:0~15)-->  

<add key="SessionRedisDBIndex" value="0"/>  

<!--主Redis连接串-->  

<add key="SessionRedisMaster" value="pass:192.168.1.236:6379"/>  

<!--Session有效时长,单位:分钟-->  

<add key="SessionTimeOut" value="120"/>  

Session基类:

[csharp] view
plain copy

 print?

public abstract class BaseSession  

    {  

        DateTime mExpiresTime = DateTime.Now;  

  

        [JsonConverter(typeof(TimestampConverter))]  

        public DateTime ExpiresTime  

        {  

            get { return mExpiresTime; }  

        }  

  

        /// <summary>  

        /// 设置Session过期时间  

        /// </summary>  

        /// <param name="aExpiresTime"></param>  

        internal void SetExpiresTime(DateTime aExpiresTime)  

        {  

            mExpiresTime = aExpiresTime;  

        }  

  

        [JsonIgnore]  

        /// <summary>  

        /// 获取服务端ID  

        /// </summary>  

        public abstract string ServerID { get; }  

    }  

[csharp] view
plain copy

 print?

public static class SessionService  

   {  

       /// <summary>  

       /// Session有效时长,默认120分钟  

       /// </summary>  

       static int TimeOutMinutes=120;  

  

       /// <summary>  

       /// Redis缓存访问对象  

       /// </summary>  

       static ConnectionMultiplexer mRedisSession;  

  

       /// <summary>  

       /// Session管理  

       /// </summary>  

       static SessionService()  

       {  

           try  

           {  

               TimeOutMinutes = int.Parse(ConfigurationManager.AppSettings["SessionTimeOut"]);  

               string[] redisMaster = ConfigurationManager.AppSettings["SessionRedisMaster"].Split(':');  

               ConfigurationOptions fRedisConfig = new ConfigurationOptions()  

               {  

                   Password = redisMaster[0],  

                   EndPoints ={ { redisMaster[1], int.Parse(redisMaster[2]) } },  

                   KeepAlive = 180,  

                   DefaultDatabase = int.Parse(ConfigurationManager.AppSettings["SessionRedisDBIndex"])  

               };  

               mRedisSession = ConnectionMultiplexer.Connect(fRedisConfig);  

           }  

           catch (Exception ex)  

           {  

               Lib.LocalLog.Append("Session Error(SessionService):" + ex.Message, "", "SessionError", "SessionError");  

               throw ex;  

           }  

       }  

  

       /// <summary>  

       /// 添加Session  

       /// </summary>  

       /// <typeparam name="T">Session对象类型</typeparam>  

       /// <param name="aSession">要存为Session的对象</param>  

       /// <param name="aPrefix">前缀</param>  

       /// <returns>令牌</returns>  

       public static string Add<T>(T aSession,string aPrefix="") where T:BaseSession  

       {  

           try  

           {  

               IDatabase client = mRedisSession.GetDatabase();  

               aSession.SetExpiresTime(DateTime.Now.AddMinutes(TimeOutMinutes));  

               string fExistToken = client.StringGet(aSession.ServerID);//获取服务端唯一码当前对应的客户端令牌  

               if (fExistToken != null)  

               {//存在客户端令牌  

                   //更新客户端令牌  

                   if (client.StringSet(fExistToken,  

                       JsonConvert.SerializeObject(aSession),   

                       aSession.ExpiresTime.Subtract(DateTime.Now)))  

                   {  

                       return fExistToken;  

                   }  

               }  

               else  

               {  

                   string token = aPrefix + Guid.NewGuid().ToString("N");  

                   if(client.StringSet(token,  

                       JsonConvert.SerializeObject(aSession),  

                       aSession.ExpiresTime.Subtract(DateTime.Now)) &&//添加Session  

                      client.StringSet(aSession.ServerID,  

                       token,  

                       aSession.ExpiresTime.AddSeconds(-5).Subtract(DateTime.Now)))//绑定服务端唯一码与客户端令牌(将比Session早5秒失效)  

                   {  

                       return token;  

                   }  

               }  

           }  

           catch (Exception ex)  

           {  

               Lib.LocalLog.Append("Session Error(Add<T>):" + ex.Message, "", "SessionError", "SessionError");  

           }  

           return null;  

       }  

  

       /// <summary>  

       /// 获取Session  

       /// </summary>  

       /// <typeparam name="T">Session对象类型</typeparam>  

       /// <param name="aToken">令牌</param>  

       /// <returns>令牌对应的Session对象</returns>  

       public static T Get<T>(string aToken) where T : BaseSession  

       {  

           try  

           {  

               IDatabase client = mRedisSession.GetDatabase();  

               T fEntity = null;  

               string fSessionValue = client.StringGet(aToken);  

               if (!string.IsNullOrEmpty(fSessionValue))  

               {  

                   fEntity = JsonConvert.DeserializeObject<T>(fSessionValue);  

                   CheckExpireTime<T>(aToken, fEntity, client);  

               }  

               return fEntity;  

           }  

           catch (Exception ex)  

           {  

               Lib.LocalLog.Append("Session Error(Get<T>):" + ex.Message, "", "SessionError", "SessionError");  

           }  

           return default(T);  

       }  

  

       /// <summary>  

       /// 获取Session 字符串值  

       /// </summary>  

       /// <param name="aToken">令牌</param>  

       /// <returns>令牌对应的Session 字符串值</returns>  

       public static string GetValue<T>(string aToken) where T : BaseSession  

       {  

           try  

           {  

               IDatabase client = mRedisSession.GetDatabase();  

               string fSessionValue = client.StringGet(aToken);  

               if (fSessionValue != null)  

               {  

                   CheckExpireTime<T>(aToken, JsonConvert.DeserializeObject<T>(fSessionValue), client);  

               }  

               return fSessionValue;  

           }  

           catch (Exception ex)  

           {  

               Lib.LocalLog.Append("Session Error(GetValue<T>):" + ex.Message, "", "SessionError", "SessionError");  

           }  

           return null;  

       }  

  

       /// <summary>  

       /// 删除Session  

       /// </summary>  

       /// <param name="aToken">令牌</param>  

       public static void Remove<T>(string aToken) where T : BaseSession  

       {  

           try  

           {  

               IDatabase client = mRedisSession.GetDatabase();  

               T fEntity = null;  

               string fSessionValue = client.StringGet(aToken);  

               if (!string.IsNullOrEmpty(fSessionValue))  

               {  

                   fEntity = JsonConvert.DeserializeObject<T>(fSessionValue);  

                   client.KeyDelete(fEntity.ServerID);  

                   client.KeyDelete(aToken);  

               }  

           }  

           catch (Exception ex)  

           {  

               Lib.LocalLog.Append("Session Error(Remove):" + ex.Message, "", "SessionError", "SessionError");  

           }  

       }  

  

       /// <summary>  

       /// 令牌有效时间检查  

       /// </summary>  

       /// <typeparam name="T"></typeparam>  

       /// <param name="aToken">令牌</param>  

       /// <param name="aSession"></param>  

       static void CheckExpireTime<T>(string aToken, T aSession, IDatabase client) where T : BaseSession  

       {  

           if (aSession.ExpiresTime.Subtract(DateTime.Now).TotalMinutes < 10)  

           {//离Session过期时间小于10分钟,延长Session有效期  

               try  

               {  

                   aSession.SetExpiresTime(DateTime.Now.AddMinutes(TimeOutMinutes));  

                   client.StringSet(aToken, JsonConvert.SerializeObject(aSession), aSession.ExpiresTime.Subtract(DateTime.Now));  

                   client.KeyExpire(aSession.ServerID, aSession.ExpiresTime.AddSeconds(-5).Subtract(DateTime.Now));  

               }  

               catch (Exception ex)  

               {  

                   Lib.LocalLog.Append("Session Error(6):" + ex.Message, "", "SessionError", "SessionError");  

               }  

           }  

       }  

   }  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: