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

前面咱們寫過C#在redis中存儲經常使用的5種數據類型demo,沒看過的能夠點擊電梯直達:https://www.cnblogs.com/xiongze520/p/10267804.htmlhtml

咱們上一篇說到Windows7系統中使用nginx部署服務器集羣:https://www.cnblogs.com/xiongze520/p/10308720.htmlnginx

部署完成後咱們對於session的共享沒有完成,以前小編想作一個session服務器作共享,而後看到評論AjuPrince三當家的方法,我決定使用第三方緩存(redis)redis

解決session共享問題。經過查詢資料整理以下設計:數據庫


  • Session的實現原理
  • Session共享實現
  • Redis存儲session的須要考慮問題
  • demo演示

 Session的實現原理:緩存

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

 Session共享實現:服務器

傳統的session由服務器端生成並存儲,當應用進行分佈式集羣部署的時候,如何保證不一樣服務器上session信息可以共享呢?cookie

兩種實現方式:session

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

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

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

Redis存儲session的須要考慮問題:memcached

  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三當家的思路。

有不一樣的解決方案能夠在評論區套路套路。

相關文章
相關標籤/搜索