当前位置: 移动技术网 > IT编程>开发语言>.net > 几分钟搞定redis存储session共享——设计实现

几分钟搞定redis存储session共享——设计实现

2019年01月30日  | 移动技术网IT编程  | 我要评论

前面我们写过c#在redis中存储常用的5种数据类型demo,没看过的可以点击

我们上一篇说到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,不知道的可以点击

然后代码如下:

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

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

 

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网