日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

分布式中Redis实现Session终结篇

發布時間:2025/7/14 数据库 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 分布式中Redis实现Session终结篇 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  上一篇使用Redis實現Session共享方式雖然可行,但是實際操作起來卻很麻煩,現有代碼已經是這個樣子了,總不可能全部換掉吧!好吧,這是個很實際的問題,那么能不能實現無侵入式的分布式Session共享方案呢?mode="InProc"這是web.config里面使用iis進程保存Session的配置,不知你注意過沒,mode除了InProc,SQLServer,StateServer這幾個常用的,還有一個Custom。這里我要使用的是網友提供給的一種方自定義Session,需要繼承System.Web.SessionState.SessionStateStoreProviderBase實現自己的SessionStateStoreProvide,下面講解如何實現自定義的RedisSessionStateStore。

閱讀目錄

  • SesstionStateProvider
  • 實現自己的RedisSessionStateStore
  • 總結
回到頂部

SessionStateStoreProviderBase

  SessionStateStoreProviderBase是asp.net提供的定義數據存儲區的會話狀態提供程序所需的成員。像常用InProcSessionStateStore(mode="InProc"),SqlSessionStateStore(mode="SQLServer"),都是繼承SessionStateStoreProviderBase實現的存儲。我們來看看msdn對其成員的定義

成員說明

InitializeRequest?方法

執行會話狀態存儲提供程序必需的所有初始化操作。

EndRequest?方法

執行會話狀態存儲提供程序必需的所有清理操作。

Dispose?方法

釋放會話狀態存儲提供程序不再使用的所有資源。

GetItemExclusive?方法

從會話數據存儲區中檢索會話的值和信息,并在請求持續期間鎖定數據存儲區中的會話項數據。GetItemExclusive?方法設置幾個輸出參數值,這些參數值將數據存儲區中當前會話狀態項的狀態通知給執行調用的?SessionStateModule

如果數據存儲區中未找到任何會話項數據,則GetItemExclusive?方法將?locked?輸出參數設置為false,并返回?null。這將導致?SessionStateModule調用?CreateNewStoreData?方法來為請求創建一個新的SessionStateStoreData?對象。

如果在數據存儲區中找到會話項數據但該數據已鎖定,則GetItemExclusive?方法將?locked?輸出參數設置為true,將?lockAge?輸出參數設置為當前日期和時間與該項鎖定日期和時間的差,將?lockId?輸出參數設置為從數據存儲區中檢索的鎖定標識符,并返回?null。這將導致SessionStateModule?隔半秒后再次調用GetItemExclusive?方法,以嘗試檢索會話項信息和獲取對數據的鎖定。如果?lockAge?輸出參數的設置值超過ExecutionTimeout?值,SessionStateModule?將調用ReleaseItemExclusive?方法以清除對會話項數據的鎖定,然后再次調用?GetItemExclusive?方法。

如果?regenerateExpiredSessionId?屬性設置為?true,則?actionFlags?參數用于其?Cookieless?屬性為?true?的會話。actionFlags?值設置為?InitializeItem?(1) 則指示會話數據存儲區中的項是需要初始化的新會話。通過調用CreateUninitializedItem?方法可以創建會話數據存儲區中未初始化的項。如果會話數據存儲區中的項已經初始化,則?actionFlags?參數設置為零。

如果提供程序支持無 Cookie 會話,請將?actionFlags?輸出參數設置為當前項從會話數據存儲區中返回的值。如果被請求的會話存儲項的?actionFlags?參數值等于InitializeItem?枚舉值 (1),則?GetItemExclusive?方法在設置?actionFlags?out?參數之后應將數據存儲區中的值設置為零。

GetItem?方法

除了不嘗試鎖定數據存儲區中的會話項以外,此方法與GetItemExclusive?方法執行的操作相同。GetItem?方法在?EnableSessionState?屬性設置為?ReadOnly?時調用。

SetAndReleaseItemExclusive?方法

采用當前請求的?HttpContext?實例、當前請求的SessionID?值、包含要存儲的當前會話值的SessionStateStoreData?對象、當前請求的鎖定標識符以及指示要存儲的數據是屬于新會話還是現有會話的值作為輸入。

如果?newItem?參數為?true,則SetAndReleaseItemExclusive?方法使用提供的值將一個新項插入到數據存儲區中。否則,數據存儲區中的現有項使用提供的值進行更新,并釋放對數據的任何鎖定。請注意,只有與提供的?SessionID?值和鎖定標識符值匹配的當前應用程序的會話數據才會更新。

調用?SetAndReleaseItemExclusive?方法后,SessionStateModule?調用?ResetItemTimeout?方法來更新會話項數據的過期日期和時間。

ReleaseItemExclusive?方法

采用當前請求的?HttpContext?實例、當前請求的SessionID?值以及當前請求的鎖定標識符作為輸入,并釋放對會話數據存儲區中的項的鎖定。在調用?GetItem?或GetItemExclusive?方法,并且數據存儲區指定被請求項已鎖定,但鎖定時間已超過?ExecutionTimeout?值時會調用此方法。此方法清除鎖定,釋放該被請求項以供其他請求使用。

RemoveItem?方法

此方法在?Abandon?方法被調用時調用。

CreateUninitializedItem?方法

采用當前請求的?HttpContext?實例、當前請求的SessionID?值以及當前請求的鎖定標識符作為輸入,并向會話數據存儲區添加一個?actionFlags?值為InitializeItem?的未初始化項。

如果?regenerateExpiredSessionId?屬性設置為?true,則?CreateUninitializedItem?方法用于無 Cookie 會話,這將導致遇到過期會話 ID 時,SessionStateModule?會生成一個新的?SessionID值。

生成新的?SessionID?值的過程需要瀏覽器重定向到包含新生成的會話 ID 的 URL。在包含過期的會話 ID 的初始請求期間,會調用?CreateUninitializedItem?方法。SessionStateModule?獲取一個新的?SessionID?值來替換過期的會話 ID 之后,它會調用CreateUninitializedItem?方法以將一個未初始化項添加到會話狀態數據存儲區中。然后,瀏覽器重定向到包含新生成的?SessionID?值的 URL。如果會話數據存儲區中存在未初始化項,則可以確保包含新生成的?SessionID?值的重定向請求被視為新的會話,而不會被誤認為是對過期會話的請求。

會話數據存儲區中未初始化的項與新生成的?SessionID值關聯,并且僅包含默認值,其中包括到期日期和時間以及與?GetItem?和?GetItemExclusive?方法的actionFlags?參數相對應的值。會話狀態存儲區中的未初始化項應包含一個與?InitializeItem?枚舉值 (1) 相等的actionFlags?值。此值由?GetItem?和GetItemExclusive?方法傳遞給SessionStateModule,并針對?SessionStateModule指定當前會話是新會話。然后,SessionStateModule將初始化該新會話,并引發?Session_OnStart?事件。

CreateNewStoreData?方法

采用當前請求的?HttpContext?實例和當前會話的Timeout?值作為輸入,并返回帶有空ISessionStateItemCollection?對象的新的SessionStateStoreData?對象、一個HttpStaticObjectsCollection?集合和指定的?Timeout值。使用?GetSessionStaticObjects?方法可以檢索 ASP.NET 應用程序的?HttpStaticObjectsCollection?實例。

上面的定義有點長,其實很多都在說明一點那就是原生了Session是單線程的方式實現的,當多個進行讀的時候會加鎖后面的會等待。我們下面實現的去掉了這些鎖,加快并發讀寫。

回到頂部

實現自己的RedisSessionStateStore

? ? 繼承SessionStateStoreProviderBase實現自己的RedisSessionStateStore也很簡單,只需繼承SessionStateStoreProviderBase重寫CreateNewStoreData,CreateUninitializedItem,GetItem等幾個方法即可,下面貼出代碼,參考InProcSessionStateStore實現。

/// <summary>/// 使用Cookie實現SessionStateStoreProviderBase/// 注意:它只適合保存簡單的基元類型數據。/// </summary>public class RedisSessionStateStore : SessionStateStoreProviderBase{public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout){return CreateLegitStoreData(context, null, null, timeout);}internal static SessionStateStoreData CreateLegitStoreData(HttpContext context, ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout){if (sessionItems == null)sessionItems = new SessionStateItemCollection();if (staticObjects == null && context != null)staticObjects = SessionStateUtility.GetSessionStaticObjects(context);return new SessionStateStoreData(sessionItems, staticObjects, timeout);}public override void CreateUninitializedItem(HttpContext context, string id, int timeout){RedisSessionState state = new RedisSessionState(null, null, timeout);RedisBase.Item_Set<string>(id, state.ToJson(), timeout);}private SessionStateStoreData DoGet(HttpContext context, string id, bool exclusive, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags){locked = false;lockId = null;lockAge = TimeSpan.Zero;actionFlags = SessionStateActions.None;RedisSessionState state = RedisSessionState.FromJson(RedisBase.Item_Get<string>(id));if (state == null){return null;}RedisBase.Item_SetExpire(id, state._timeout);return CreateLegitStoreData(context, state._sessionItems, state._staticObjects, state._timeout);}public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags){return this.DoGet(context, id, false, out locked, out lockAge, out lockId, out actionFlags);}public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actionFlags){return this.DoGet(context, id, true, out locked, out lockAge, out lockId, out actionFlags);}public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem){ISessionStateItemCollection sessionItems = null;HttpStaticObjectsCollection staticObjects = null;if (item.Items.Count > 0)sessionItems = item.Items;if (!item.StaticObjects.NeverAccessed)staticObjects = item.StaticObjects;RedisSessionState state2 = new RedisSessionState(sessionItems, staticObjects, item.Timeout);RedisBase.Item_Set<string>(id, state2.ToJson(), item.Timeout);}#region "未實現方法"public override void Dispose(){}public override void EndRequest(HttpContext context){}public override void InitializeRequest(HttpContext context){}public override void ReleaseItemExclusive(HttpContext context, string id, object lockId){}public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item){RedisBase.Item_Remove(id);}public override void ResetItemTimeout(HttpContext context, string id){}public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback){return true;}#endregion}internal sealed class SessionStateItem{public Dictionary<string, SaveValue> Dict;public int Timeout;}internal sealed class SaveValue{public object Value { get; set; }public Type Type { get; set; }}internal sealed class RedisSessionState{internal ISessionStateItemCollection _sessionItems;internal HttpStaticObjectsCollection _staticObjects;internal int _timeout;internal RedisSessionState(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout){this.Copy(sessionItems, staticObjects, timeout);}internal void Copy(ISessionStateItemCollection sessionItems, HttpStaticObjectsCollection staticObjects, int timeout){this._sessionItems = sessionItems;this._staticObjects = staticObjects;this._timeout = timeout;}public string ToJson(){// 這里忽略_staticObjects這個成員。if (_sessionItems == null || _sessionItems.Count == 0){return null;}Dictionary<string, SaveValue> dict = new Dictionary<string, SaveValue>(_sessionItems.Count);NameObjectCollectionBase.KeysCollection keys = _sessionItems.Keys;string key;object objectValue = string.Empty;Type type = null;
      //2016-09-04解決存入值沒有類型導致讀取值是jobject問題  
for (int i = 0; i < keys.Count; i++){key = keys[i];objectValue = _sessionItems[key];if (objectValue != null){type = objectValue.GetType();}else{type = typeof(object);}dict.Add(key, new SaveValue { Value = objectValue, Type = type });}SessionStateItem item = new SessionStateItem { Dict = dict, Timeout = this._timeout };return JsonConvert.SerializeObject(item);}public static RedisSessionState FromJson(string json){if (string.IsNullOrEmpty(json)){return null;}try{SessionStateItem item = JsonConvert.DeserializeObject<SessionStateItem>(json);SessionStateItemCollection collections = new SessionStateItemCollection();SaveValue objectValue = null;     //2016-09-04解決讀取出來的值 沒有類型的問題JsonSerializer serializer = new JsonSerializer();StringReader sr = null;JsonTextReader tReader = null;foreach (KeyValuePair<string, SaveValue> kvp in item.Dict){objectValue = kvp.Value as SaveValue;if (objectValue.Value == null){collections[kvp.Key] = null;}else{if (!IsValueType(objectValue.Type)){sr = new StringReader(objectValue.Value.ToString());tReader = new JsonTextReader(sr);collections[kvp.Key] = serializer.Deserialize(tReader, objectValue.Type);}else{collections[kvp.Key] = objectValue.Value;}}}return new RedisSessionState(collections, null, item.Timeout);}catch{return null;}}/// <summary>/// 判斷是否為值類型/// </summary>/// <param name="type">Type</param>/// <returns></returns>public static bool IsValueType(Type type){if (type.IsValueType){return true;}//基礎數據類型if (type == typeof(string) || type == typeof(char)|| type == typeof(ushort) || type == typeof(short) || type == typeof(uint) || type == typeof(int)|| type == typeof(ulong) || type == typeof(long) || type == typeof(double) || type == typeof(decimal)|| type == typeof(bool)|| type == typeof(byte)){return true;}//可為null的基礎數據類型if (type.IsGenericType && !type.IsGenericTypeDefinition){Type genericType = type.GetGenericTypeDefinition();if (Object.ReferenceEquals(genericType, typeof(Nullable<>))){var actualType = type.GetGenericArguments()[0];return IsValueType(actualType);}}return false;}}

?

使用也很簡單,修改web.config,如下圖 然后可以保持原先代碼不變,像Session["UserCode"]="admin"方式進行使用,但是現在的Session已經具備了分布式的特征,支持跨域。這里得說一下該方式的缺點,在GetItem和SetAndReleaseItemExclusive時需要對鍵值對進行反序列化和序列化操作,對于保存數據量大的情況反而性能相對于系統提供的方式大打折扣,所以使用的時候需要考慮自己的實際場景。 回到頂部

總結  

  ? 本來分布式Session共享到上篇就完結了,但是由于方案的可行性差,還有更好的方案,所以花了點時間參考了前面MSND中的說明,和ASP.net源碼中InProcSessionStateStore的實現,解決GetItemExclusive等方法的并發鎖定問題,最終實現了Redis的存儲方式,更加靈活方便。這里要感謝大家提的意見,讓我又學會了一個知識點!

? ? ? 資源下載地址:redis_demo

  svn下載地址:http://code.taobao.org/svn/ResidSessionDemo/

  本文參考:

  sessionstatestoreproviderbase定義:https://msdn.microsoft.com/zh-cn/library/system.web.sessionstate.sessionstatestoreproviderbase(VS.80).aspx

  sessionstatestoreproviderbase成員:https://msdn.microsoft.com/zh-cn/library/ms178587(v=vs.80).aspx

  

如果,您認為閱讀這篇博客讓您有些收獲,不妨點擊一下右下角的【推薦】按鈕。
如果,您希望更容易地發現我的新博客,不妨點擊一下綠色通道的【關注我】。

如果,想給予我更多的鼓勵,求打

因為,我的寫作熱情也離不開您的肯定支持。

感謝您的閱讀,如果您對我的博客所講述的內容有興趣,請繼續關注我的后續博客,我是焰尾迭 。

轉載于:https://www.cnblogs.com/yanweidie/p/4763556.html

總結

以上是生活随笔為你收集整理的分布式中Redis实现Session终结篇的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美一区二区三区爽爽爽 | 国内毛片毛片毛片毛片 | av激情四射 | 国产aaa级片 | 欧美xxxx69 | 伊人影院网 | 极品国产在线 | a级片在线观看视频 | 国产日产精品一区二区 | 97久久国产精品 | 日韩九九九 | 亚洲国产精品久久久久婷婷老年 | 亚洲国产精品视频一区二区 | 天堂视频在线免费观看 | 欧美巨鞭大战丰满少妇 | 69精品 | 久一国产 | 亚洲午夜久久久久 | 亚洲午夜伦理 | 美少妇av | 人成在线 | 午夜爱爱影院 | 好吊一区二区三区视频 | 琪琪秋霞午夜被窝电影网 | 巨茎人妖videos另类 | 日本少妇激三级做爰在线 | 少妇又紧又深又湿又爽视频 | 91精品视频国产 | 日韩中文字幕免费在线观看 | 久草免费新视频 | 久久国产91 | 久久久久久久综合 | 久久888 | 中文在线8资源库 | 亚洲精品中文字幕成人片 | 中文字幕女同女同女同 | 懂色一区二区三区 | 国产中文在线观看 | 亚洲同性gay激情无套 | 亚洲系列中文字幕 | 日日艹夜夜艹 | 成年人在线观看av | 131mm少妇做爰视频 | 欧美三级欧美成人高清 | 97人人干 | 中文字幕人成人乱码亚洲电影 | 国产精品一区二区在线观看 | 欧美日韩国产免费 | 奇米四色影视 | 国产av剧情一区二区三区 | 久久禁| 国产福利小视频在线观看 | 亚洲一级免费视频 | 欧美色图校园春色 | 日产亚洲一区二区三区 | 欧美激情3p | 色婷婷国产精品 | 日韩乱码人妻无码系列中文字幕 | 青青草在线免费视频 | 超碰最新在线 | 中出在线 | 日本a级大片 | 综合狠狠开心 | 护士的小嫩嫩好紧好爽 | 国产成人久久精品麻豆二区 | 日本xxxx高潮少妇 | 五级黄高潮片90分钟视频 | 毛片久久久久久久 | 极品久久久久 | 午夜在线观看影院 | 在线免费视频一区 | n0659极腔濑亚美莉在线播放播放 | 久久国产精品国产精品 | 无遮挡边吃摸边吃奶边做 | 女教师三上悠亚ssni-152 | 亚洲午夜免费视频 | 国产午夜精品久久久久 | 国产精品一区二区在线观看 | 久久久全国免费视频 | 天天射寡妇 | 成人在线不卡 | av免费国产 | 第四色激情 | 国产三级三级三级三级三级 | 美女精品在线 | 久久天天综合 | 国产视频欧美 | 中文字幕淫 | 成人福利一区 | 国产一级二级三级在线 | 久久精品国产99精品国产亚洲性色 | 97在线免费公开视频 | 久久综合日本 | 后进极品白嫩翘臀在线视频 | 日本国产精品视频 | 成人免费毛片色戒 | 亚洲一区三区 | 日韩中文免费 | 在线中文字幕av |