zoukankan      html  css  js  c++  java
  • 实现Asp.net Mvc分布式Session Redis群集

    Redis群集实现Asp.net Mvc分布式Session

    Session的缺点

    众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失。

    如果你的网站使用了session,当网站并发过大时可能引起溢出。

    配置Redis 集群


    安装Redis

    创建一个文件,进入该文件夹

    下载Redis 地址:http://download.redis.io/releases/redis-3.0.4.tar.gz

    tar -xvf redis-3.0.4.tar.gz 解压文件

    cd redis-3.0.4 进入解压的文件

    make && make install 安装

    创建三个文件夹

    把redis.conf文件分别复制到这三个文件夹

    然后分别进入这三个文件夹修改配置文件和指定不同的端口

    1.daemonize yes  (开启后台运行)

    2.port 6379 (端口)

    3.pidfile /var/run/redis-6379.pid (Redis 以守护进程的方式运行的时候,Redis 默认会把 pid 文件放在/var/run/redis.pid,你可以配置到其他地址。当运行多个 redis 服务时,需要指定不同的 pid 文件和端口)

    4.cluster-enabled yes (是否启用集群)

    5.cluster-config-file "nodes-6379.conf" (nodes 节点文件)

     

     安装ruby环境

    yum -y install zlib ruby rubygems

    gem install redis

    开启服务

    分别开启这三个实例

    查看是否开启

     创建集群

    首先,进入redis的安装包路径下:

    cd /usr/local/src/redis/redis-3.0.1/src/

    执行命令:

    ./redis-trib.rb create --replicas 0 ./redis-trib.rb create --replicas 0 192.168.1.108:6379 192.168.1.108:6380 192.168.1.108:6381

    进入redis-cli -p 6379 -c

    Cluster nodes 查看集群信息

    配置完成

    使用 StackExchange.Redis驱动连接到redis


    代码是我从Asp.net vnext Caching 程序集中copy下来的

    配置类型

    复制代码
     public class RedisCacheOptions
            {
            /// <summary>
            /// 连接配置
            /// </summary>
            public string Configuration { get; set; }
           /// <summary>
           /// 实例名字
           /// </summary>
            public string InstanceName { get; set; }
    
    
            }
    复制代码
    复制代码
      static void Main(string[] args)
                {
    
    
                string key = "myKey";
                object state = null;
                string value1 = "yyyyyyyyyyyyyy";
                byte[] value = Encoding.Default.GetBytes(value1);
                Stream valueStream;
    
                Console.WriteLine("Connecting to cache");
                var cache = new RedisCache(new RedisCacheOptions
                    {
                    InstanceName = "sessionId",
                    Configuration = "192.168.1.108:6379,192.168.1.108:6380,192.168.1.108:6381"
                    });
                Console.WriteLine("Connected");
    
                Console.WriteLine("Setting");
                valueStream = cache.Set(key, state, context =>
                {
                    context.Data.Write(value, 0, value.Length);
                });
    复制代码

    RedisCache 集体实现

    复制代码
       public class RedisCache : IDistributedCache
            {
            //Lua 脚本
            private const string SetScript = (@" 
                    redis.call('HMSET', KEYS[1], 'absexp', ARGV[1], 'sldexp', ARGV[2], 'data', ARGV[4])
                    if ARGV[3] ~= '-1' then
                      redis.call('EXPIRE', KEYS[1], ARGV[3]) 
                    end
                    return 1");
            //key
            private const string AbsoluteExpirationKey = "absexp";
            //key
            private const string SlidingExpirationKey = "sldexp";
            //key
            private const string DataKey = "data";
            private const long NotPresent = -1;
            private ConnectionMultiplexer _connection;
            private IDatabase _cache;
            private readonly RedisCacheOptions _options;
            private readonly string _instance;
            /// <summary>
            /// 初始化配置
            /// </summary>
            /// <param name="optionsAccessor"></param>
            public RedisCache(RedisCacheOptions optionsAccessor)
                {
                _options = optionsAccessor;
                _instance = optionsAccessor.InstanceName;
                }
            public void Connect()
                {
                if (_connection == null)
                    {
                    _connection = ConnectionMultiplexer.Connect(_options.Configuration);
                    _cache = _connection.GetDatabase();
                    }
                }
    
    
            /// <summary>
            /// set到Redis中
            /// </summary>
            /// <param name="key"></param>
            /// <param name="state"></param>
            /// <param name="create"></param>
            /// <returns></returns>
            public Stream Set(string key, object state, Action<ICacheContext> create)
                {
                Connect();
    
                var context = new CacheContext(key) { State = state };
                //设置绝对过期时间
                //context.SetAbsoluteExpiration(DateTimeOffset.Now.AddMilliseconds(22222));
                //设置滑动过期时间
                context.SetSlidingExpiration(TimeSpan.FromSeconds(22222));
                create(context);
                var value = context.GetBytes();
                //Lua脚本赋值
                var result = _cache.ScriptEvaluate(SetScript, new RedisKey[] { _instance + key },
                    new RedisValue[]
                    {
                        context.AbsoluteExpiration?.Ticks ?? NotPresent,
                        context.SlidingExpiration?.Ticks ?? NotPresent,
                        context.GetExpirationInSeconds() ?? NotPresent,
                        value
                    });
                return new MemoryStream(value, writable: false);
                }
    
            public bool TryGetValue(string key, out Stream value)
                {
                value = GetAndRefresh(key, getData: true);
                return value != null;
                }
    
            public void Refresh(string key)
                {
                var ignored = GetAndRefresh(key, getData: false);
                }
    
            private Stream GetAndRefresh(string key, bool getData)
                {
                Connect();
    
    
                RedisValue[] results;
                if (getData)
                    {
                    results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
                    }
                else
                    {
                    results = _cache.HashMemberGet(_instance + key, AbsoluteExpirationKey, SlidingExpirationKey);
                    }
    
                if (results.Length >= 2)
                    {
                    DateTimeOffset? absExpr;
                    TimeSpan? sldExpr;
                    MapMetadata(results, out absExpr, out sldExpr);
                    Refresh(key, absExpr, sldExpr);
                    }
                if (results.Length >= 3 && results[2].HasValue)
                    {
                    return new MemoryStream(results[2], writable: false);
                    }
                return null;
                }
            private void MapMetadata(RedisValue[] results, out DateTimeOffset? absoluteExpiration, out TimeSpan? slidingExpiration)
                {
                absoluteExpiration = null;
                slidingExpiration = null;
                var absoluteExpirationTicks = (long?)results[0];
                if (absoluteExpirationTicks.HasValue && absoluteExpirationTicks.Value != NotPresent)
                    {
                    absoluteExpiration = new DateTimeOffset(absoluteExpirationTicks.Value, TimeSpan.Zero);
                    }
                var slidingExpirationTicks = (long?)results[1];
                if (slidingExpirationTicks.HasValue && slidingExpirationTicks.Value != NotPresent)
                    {
                    slidingExpiration = new TimeSpan(slidingExpirationTicks.Value);
                    }
                }
    
            /// <summary>
            /// 刷新缓存过期时间
            /// </summary>
            /// <param name="key"></param>
            /// <param name="absExpr"></param>
            /// <param name="sldExpr"></param>
            private void Refresh(string key, DateTimeOffset? absExpr, TimeSpan? sldExpr)
                {
                TimeSpan? expr = null;
                if (sldExpr.HasValue)
                    {
                    if (absExpr.HasValue)
                        {
                        var relExpr = absExpr.Value - DateTimeOffset.Now;
                        expr = relExpr <= sldExpr.Value ? relExpr : sldExpr;
                        }
                    else
                        {
                        expr = sldExpr;
                        }
                    _cache.KeyExpire(_instance + key, expr);
                    // TODO: Error handling
                    }
                }
            /// <summary>
            /// 移除指定key
            /// </summary>
            /// <param name="key"></param>
            public void Remove(string key)
                {
                Connect();
                _cache.KeyDelete(_instance + key);
    
                }
            }
    复制代码

    运行结果

    源码:http://pan.baidu.com/s/1gdm8F9h

     
    分类: Asp.net vnext
  • 相关阅读:
    rocketmq 修改broker和namesrv默认设置的堆内存大小
    linux 向文件中添加内容 sed
    页面 请求错误总结
    将pgsql中的所有表的序列当前值设置为所需的值
    pg 强制断开连接 删库
    测试的基本概念
    Linking(3)
    Linking(1)
    Linking(2)
    Nginx Learning (5)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/4881213.html
Copyright © 2011-2022 走看看