您好,登錄后才能下訂單哦!
本篇文章為大家展示了分布式中Redis是怎樣實現Session,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
這里我要使用的是網友提供給的一種方自定義Session,需要繼承System.Web.SessionState.SessionStateStoreProviderBase實現自己的SessionStateStoreProvide,下面講解如何實現自定義的RedisSessionStateStore。
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 |
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是單線程的方式實現的,當多個進行讀的時候會加鎖后面的會等待。我們下面實現的去掉了這些鎖,加快并發讀寫。
繼承SessionStateStoreProviderBase實現自己的RedisSessionStateStore也很簡單,只需繼承SessionStateStoreProviderBase重寫CreateNewStoreData,CreateUninitializedItem,GetItem等幾個方法即可,下面貼出代碼,參考InProcSessionStateStore實現。
使用也很簡單,修改web.config
然后可以保持原先代碼不變,像Session["UserCode"]="admin"方式進行使用,但是現在的Session已經具備了分布式的特征,支持跨域。這里得說一下該方式的缺點,在GetItem和SetAndReleaseItemExclusive時需要對鍵值對進行反序列化和序列化操作,對于保存數據量大的情況反而性能相對于系統提供的方式大打折扣,所以使用的時候需要考慮自己的實際場景。
上述內容就是分布式中Redis是怎樣實現Session,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。