zoukankan      html  css  js  c++  java
  • 几分钟搞定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三当家的思路。

    有不同的解决方案可以在评论区套路套路。

    欢迎关注订阅我的微信公众平台【熊泽有话说】,更多好玩易学知识等你来取
    作者:熊泽-学习中的苦与乐
    公众号:熊泽有话说
    出处:https://www.cnblogs.com/xiongze520/p/10333233.html
    创作不易,任何人或团体、机构全部转载或者部分转载、摘录,请在文章明显位置注明作者和原文链接。  

     

  • 相关阅读:
    python基础 2
    python基础 1
    进程
    进程作业
    上海python14期第二次阶段性考试
    面向对向之元类
    面向对向
    笔试题
    模块(2)
    模块作业
  • 原文地址:https://www.cnblogs.com/xiongze520/p/10333233.html
Copyright © 2011-2022 走看看