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, , 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 = -;
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());
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 >= )
{
DateTimeOffset? absExpr;
TimeSpan? sldExpr;
MapMetadata(results, out absExpr, out sldExpr);
Refresh(key, absExpr, sldExpr);
}
if (results.Length >= && results[].HasValue)
{
return new MemoryStream(results[], writable: false);
}
return null;
}
private void MapMetadata(RedisValue[] results, out DateTimeOffset? absoluteExpiration, out TimeSpan? slidingExpiration)
{
absoluteExpiration = null;
slidingExpiration = null;
var absoluteExpirationTicks = (long?)results[];
if (absoluteExpirationTicks.HasValue && absoluteExpirationTicks.Value != NotPresent)
{
absoluteExpiration = new DateTimeOffset(absoluteExpirationTicks.Value, TimeSpan.Zero);
}
var slidingExpirationTicks = (long?)results[];
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

Redis群集实现Asp.net Mvc分布式Session的更多相关文章

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

    Redis群集实现Asp.net Mvc分布式Session Session的缺点 众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失. 如果你的网站使用了 ...

  2. [2014-02-23]Asp.net Mvc分布式Session存储方案

    要玩集群的时候,怎么处理会话状态Session? InProc模式的sessionState是不能用了,因为这是在web服务器本机进程里的,会造成各节点数据不一致.除非在分流的时候用ip hash策略 ...

  3. Asp.net Mvc 自定义Session (二)

    在 Asp.net Mvc 自定义Session (一)中我们把数据缓存工具类写好了,今天在我们在这篇把 剩下的自定义Session写完 首先还请大家跟着我的思路一步步的来实现,既然我们要自定义Ses ...

  4. 转载ASP.NET MVC中Session的处理机制

    本文章转载自 http://www.cnblogs.com/darrenji/p/3951065.html ASP.NET MVC中的Session以及处理方式   最近在ASP.NET MVC项目中 ...

  5. ASP.NET MVC之Session State性能问题(七)

    前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Session State特性,它主要用来当在同一浏览器发出多个请求时来存储数 ...

  6. Spring Boot(十一)Redis集成从Docker安装到分布式Session共享

    一.简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API,Redis也是技术领域使用最为广泛的存储中间件,它是 ...

  7. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  8. Asp.net Mvc 自定义Session (一),

    大家都知道用系统默认的session 会存在这样的问题 如果用户过多的话 session 会自动消亡,而且不能支持分布式和集群. 这系列博客主要讲解  怎样 解决用户过多的session自动消亡,和分 ...

  9. ASP.NET MVC Controller Session问题

    发现问题 最近在项目中遇到这样一个问题,一直没办法重现,所以几天都没有解决. 测试那边给出的问题是这样的:每天早上来的时候,第一次通过单点登录到系统的时候,总会跳转回登录界面,再次登录就好了.当时给我 ...

随机推荐

  1. ThinkPHP 自动验证与自动填充无效可能的原因(转)

    自动验证与自动填充是在使用ThinkPHP时经常用到的功能,但偶尔会遇到自动验证与自动填充无效的情况,本文就ThinkPHP 自动验证与自动填充无效可能的原因做一些分析. create() Think ...

  2. ios推送

    1. ios 在杀掉app后,只能接受到系统通知,JPUSH自定义消息不能接受到.系统通知经过实验只能接收到50左右个汉字. 2. 实现方案: 推送的时候,JPUSH推送一个消息,App客户端获取到数 ...

  3. 各种设备的CSS3 MediaQuery整理及爽歪歪写法

    链接:http://dwz.cn/1gZQ06 ------------------------------------------------------ 备注:内容未测试过,转载的,留着备用. - ...

  4. Oracle忽略hint的几种情形

    1.hint有语法错误.拼写错误 2.hint无效.比如索引不存在.非等值查询使用hash hint等 3.多个hint之间自相矛盾 4.hint受到了查询转换的影响 5.hint受到了数据库保留字的 ...

  5. Struts2 用 s:if test 判断属性和字符串相等时 注意双引号和单引号的使用

    字符串N一定要用“”双引号包含,从test的包含则用单引号 ‘ ’,如果相反,则不能正确判断该属性是否与该字符串相等. 正确:<s:if test='activityBean.searchFor ...

  6. Swift实战-QQ在线音乐(AppleWatch版)

    1.打开项目QQMusic,然后点菜单:“File-New-Target”添加appleWatch扩展项 2.选择Swift语言,把Include Notification Scene前的勾去掉 (项 ...

  7. PostgreSQL Replication之第十二章 与Postgres-XC一起工作(4)

    12.4 性能优化 Postgres-XC不是一个奇特的PostgreSQL版本,而是一个真正的分布式系统.这意味这,您不能只存储数据,希望事情超出服务器之外的快速,高效.如果您想优化速度,思考数据是 ...

  8. Notice: Undefined offset 的解决方法

    Notice: Undefined offset: 1 in D:\wwwroot\wr\askseo\404.php on line 5 Notice: Undefined offset: 2 in ...

  9. 转:python webdriver API 之下载文件

    webdriver 允许我们设置默认的文件下载路径.也就是说文件会自动下载并且存在设置的那个目录中.要想下载文件,首选要先确定你所要下载的文件的类型.要识别自动文件的下载类型可以使用 curl ,如图 ...

  10. .NET: 防止多个应用程序同时开

    用到了Mutex这个类,直接看代码~ using System; using System.Collections.Generic; using System.Linq; using System.W ...