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

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

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

    Session的缺点 众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失. 如果你的网站使用了session,当网站并发过大时可能引起溢出. 配置Redis ...

  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中使用Redis

    一.Redis基本认知 1.含义: REmote DIctionary Server(Redis) | 是一个key-value存储系统 2.特性: 2.1 持久化:可以将内存中的数据保存在磁盘中,重 ...

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

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

  6. spring boot:使用redis cluster集群作为分布式session(redis 6.0.5/spring boot 2.3.1)

    一,为什么要使用分布式session? HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题, 所以我们在创建web集群时,把session保存到r ...

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

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

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

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

  9. ASP.NET MVC Controller Session问题

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

随机推荐

  1. hdu1500 (排序+单调队列优化 )

    从n根筷子里面, 选择k+8个集合的筷子,每个集合三根筷子, A<=B<=C, 费用是(A-B)^2, 问最小的费用是多少. 将n根筷子排序之后,可以知道A和B的下标一定是连续的. 比如有 ...

  2. 关于安装linux时要怎么分区的考虑的參考方式?

    对于使用最小化安装的centos7文件夹列表,注意链接方式的文件夹会在统计占用空间时不会算入的; watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlkaX ...

  3. springMVC整合JAXB

    一.背景 由于项目中要用到将Java对象转为xml返回给调用者.选择使用JAXB,由于它是JDK自带的.不须要引入其它Jar包 它提供了高速而简便的方法将xml和对象互转的方法. 二.重要Class和 ...

  4. 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)

    <西游记>中的唐僧团队历经千难万险,终于求得真经,目标明确.分工合理为这支队伍最终走向成功奠定了基础.唐僧从一开始,就为这个团队设定了西天取经的目标,虽然经历各种挫折与磨难,但目标从未动摇 ...

  5. oracle一个用户密码管理多达同意三次企图登录

    假设一个用户登录连续失败三次.两日,锁定用户,两天后再次登录的用户的能力. 创建profile文件: 更新账户: 三次登录失败后用户就会被锁定: 用户锁住之后要怎么给他解锁: 解锁之后就能够正常登录了 ...

  6. hibernate 批量处理数据

    批量处理数据是指处理大量数据的一个单独的事务. 在应用层批处理操作, 主要有以下方式: 通过 Session 通过 HQL 通过 StatelessSession 通过 JDBC API(仅仅要会用这 ...

  7. 疯狂Java学习笔记(84)----------大约 Java 对象序列化,你不知道 5 事

    几年前,.当一个软件团队一起用 Java 书面申请.我认识比一般程序猿多知道一点关于 Java 对象序列化的知识所带来的优点. 关于本系列 您认为自己懂 Java 编程?其实,大多数程序猿对于 Jav ...

  8. Red Gate系列之四 SQL Data Compare 10.2.0.885 Edition 数据比较同步工具 完全破解+使用教程

    原文:Red Gate系列之四 SQL Data Compare 10.2.0.885 Edition 数据比较同步工具 完全破解+使用教程 Red Gate系列之四 SQL Data Compare ...

  9. DB2 “The transaction log for the database is full” 存在的问题及解决方案

    DB2在执行一个大的insert/update操作的时候报"The transaction log for the database is full.. "错误,查了一下文档是DB ...

  10. Source Insight 光标变粗设置NotePad++光标设置

    为了更好的查看文档和代码,避免半天都找不到光标的情况,故做此说明 Source Insight 光标变粗 菜单中 Options --->Preferences --->Typing -- ...