前面我們寫過C#在redis中存儲常用的5種數據類型demo,沒看過的可以點擊電梯直達:https://www.cnblogs.com/xiongze520/p/10267804.html
我們上一篇說到Windows7系統中使用nginx部署服務器集群:https://www.cnblogs.com/xiongze520/p/10308720.html
部署完成后我們對於session的共享沒有完成,之前小編想做一個session服務器做共享,然后看到評論AjuPrince和三當家的方法,我決定使用第三方緩存(redis)
解決session共享問題。通過查詢資料整理如下設計:
- Session的實現原理
- Session共享實現
- Redis存儲session的需要考慮問題
- demo演示
Session的實現原理:
- 服務端首先查找對應的cookie的值(sessionid)。
- 根據sessionid,從服務器端session存儲中獲取對應id的session數據,進行返回。
- 如果找不到sessionid,服務器端就創建session,生成sessionid對應的cookie,寫入到響應頭中。
Session共享實現:
傳統的session由服務器端生成並存儲,當應用進行分布式集群部署的時候,如何保證不同服務器上session信息能夠共享呢?
兩種實現方式:
- session集中存儲(redis,memcached,hbase等)。
- 不同服務器上session數據進行復制,兩種方式的優缺點,大家應該一目了然。
基於session集中存儲的實現方案:
- 新增Filter,攔截請求,包裝HttpServletRequest
- 改寫getSession方法,從session存儲中獲取session數據,返回自定義的HttpSession實現
- 在生成新Session后,寫入sessionid到cookie中
Redis存儲session的需要考慮問題:
- session數據如何在Redis中存儲?
- session屬性變更何時觸發存儲?
實現:
考慮到session中數據類似map的結構,采用redis中hash存儲session數據比較合適,如果使用單個value存儲session數據,不加鎖的情況下,就會存在session覆蓋的問題,因此使用hash存儲session,每次只保存本次變更session屬性的數據,避免了鎖處理,性能更好。
如果每改一個session的屬性就觸發存儲,在變更較多session屬性時會觸發多次redis寫操作,對性能也會有影響,我們是在每次請求處理完后,做一次session的寫入,並且之寫入變更過的屬性。
如果本次沒有做session的更改, 是不會做redis寫入的,僅當沒有變更的session超過一個時間閥值(不變更session刷新過期時間的閥值),就會觸發session保存,以便session能夠延長有效期。
demo演示:
我們還是使用上傳的demo進行稍加修改:
不用說,我們首先啟動redis,不知道的可以點擊電梯直達:https://www.cnblogs.com/xiongze520/p/10267804.html
然后代碼如下:
using ServiceStack.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace RedisApplication { class Program { static void Main(string[] args) { //建立Redis客戶端類,構造函數(安裝Redis服務器的服務器ip,端口號) RedisClient client = new RedisClient("192.168.0.43", 6379); //鏈接Redis服務器 client.FlushAll(); //命令用於清空整個Redis服務器的數據(刪除所有數據庫的所有密鑰)。 //-----------------將數據存入Redis----------------- //SetEntryInHash(hashid,key,value) hashid是唯一標識符 client.SetEntryInHash("HashID", "Name", "張三"); client.SetEntryInHash("HashID", "Age", "24"); client.SetEntryInHash("HashID", "Sex", "男"); client.SetEntryInHash("HashID", "Address", "上海市XX號XX室"); client.SetEntryInHash("HashID2", "Name", "張三"); client.SetEntryInHash("HashID2", "Age", "24"); client.SetEntryInHash("HashID2", "Sex", "男"); client.SetEntryInHash("HashID2", "Address", "上海市XX號XX室"); //-----------------讀取存入的數據----------------- List<string> HaskKey = client.GetHashKeys("HashID"); foreach (string key in HaskKey) { Console.WriteLine("HashID--Key:{0}", key); } List<string> HaskKey2 = client.GetHashKeys("HashID2"); foreach (string key in HaskKey2) { Console.WriteLine("HashID2--Key:{0}", key); } //-----------------刪除對象----------------- //client.RemoveEntryFromHash("HashID", "Name"); } } }
我們獲取指定的key,運行效果圖如下:
這樣就完成redis存儲和session共享的問題了,避免iis的session不共享和覆蓋問題。
有不同的解決方案可以在評論區套路套路。