幾分鍾搞定redis存儲session共享——設計實現


前面我們寫過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的實現原理:

  1. 服務端首先查找對應的cookie的值(sessionid)。
  2. 根據sessionid,從服務器端session存儲中獲取對應id的session數據,進行返回。
  3. 如果找不到sessionid,服務器端就創建session,生成sessionid對應的cookie,寫入到響應頭中。

 Session共享實現:

傳統的session由服務器端生成並存儲,當應用進行分布式集群部署的時候,如何保證不同服務器上session信息能夠共享呢?

兩種實現方式:

  1. session集中存儲(redis,memcached,hbase等)。
  2. 不同服務器上session數據進行復制,兩種方式的優缺點,大家應該一目了然。

基於session集中存儲的實現方案:

  • 新增Filter,攔截請求,包裝HttpServletRequest
  • 改寫getSession方法,從session存儲中獲取session數據,返回自定義的HttpSession實現
  • 在生成新Session后,寫入sessionid到cookie中

Redis存儲session的需要考慮問題:

  1. session數據如何在Redis中存儲?
  2. 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不共享和覆蓋問題。

再次感謝AjuPrince三當家的思路。

有不同的解決方案可以在評論區套路套路。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM