实现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 Mvc分布式Session Redis群集的更多相关文章
- Redis群集实现Asp.net Mvc分布式Session
Session的缺点 众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失. 如果你的网站使用了session,当网站并发过大时可能引起溢出. 配置Redis ...
- [2014-02-23]Asp.net Mvc分布式Session存储方案
要玩集群的时候,怎么处理会话状态Session? InProc模式的sessionState是不能用了,因为这是在web服务器本机进程里的,会造成各节点数据不一致.除非在分流的时候用ip hash策略 ...
- Asp.net Mvc 自定义Session (二)
在 Asp.net Mvc 自定义Session (一)中我们把数据缓存工具类写好了,今天在我们在这篇把 剩下的自定义Session写完 首先还请大家跟着我的思路一步步的来实现,既然我们要自定义Ses ...
- 在ASP.NET MVC中使用Redis
一.Redis基本认知 1.含义: REmote DIctionary Server(Redis) | 是一个key-value存储系统 2.特性: 2.1 持久化:可以将内存中的数据保存在磁盘中,重 ...
- 转载ASP.NET MVC中Session的处理机制
本文章转载自 http://www.cnblogs.com/darrenji/p/3951065.html ASP.NET MVC中的Session以及处理方式 最近在ASP.NET MVC项目中 ...
- spring boot:使用redis cluster集群作为分布式session(redis 6.0.5/spring boot 2.3.1)
一,为什么要使用分布式session? HpptSession默认使用内存来管理Session,如果将应用横向扩展将会出现Session共享问题, 所以我们在创建web集群时,把session保存到r ...
- ASP.NET MVC之Session State性能问题(七)
前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Session State特性,它主要用来当在同一浏览器发出多个请求时来存储数 ...
- Asp.net Mvc 自定义Session (一),
大家都知道用系统默认的session 会存在这样的问题 如果用户过多的话 session 会自动消亡,而且不能支持分布式和集群. 这系列博客主要讲解 怎样 解决用户过多的session自动消亡,和分 ...
- ASP.NET MVC Controller Session问题
发现问题 最近在项目中遇到这样一个问题,一直没办法重现,所以几天都没有解决. 测试那边给出的问题是这样的:每天早上来的时候,第一次通过单点登录到系统的时候,总会跳转回登录界面,再次登录就好了.当时给我 ...
随机推荐
- hdu1500 (排序+单调队列优化 )
从n根筷子里面, 选择k+8个集合的筷子,每个集合三根筷子, A<=B<=C, 费用是(A-B)^2, 问最小的费用是多少. 将n根筷子排序之后,可以知道A和B的下标一定是连续的. 比如有 ...
- 关于安装linux时要怎么分区的考虑的參考方式?
对于使用最小化安装的centos7文件夹列表,注意链接方式的文件夹会在统计占用空间时不会算入的; watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlkaX ...
- springMVC整合JAXB
一.背景 由于项目中要用到将Java对象转为xml返回给调用者.选择使用JAXB,由于它是JDK自带的.不须要引入其它Jar包 它提供了高速而简便的方法将xml和对象互转的方法. 二.重要Class和 ...
- 很多人都在埋怨没有遇到好的团队,但好的团队不可能凭空出现,一流的团队不能仅靠团队成员努力,作为Leader,要有可行的规划,并坚定地执行、时势地调整(转)
<西游记>中的唐僧团队历经千难万险,终于求得真经,目标明确.分工合理为这支队伍最终走向成功奠定了基础.唐僧从一开始,就为这个团队设定了西天取经的目标,虽然经历各种挫折与磨难,但目标从未动摇 ...
- oracle一个用户密码管理多达同意三次企图登录
假设一个用户登录连续失败三次.两日,锁定用户,两天后再次登录的用户的能力. 创建profile文件: 更新账户: 三次登录失败后用户就会被锁定: 用户锁住之后要怎么给他解锁: 解锁之后就能够正常登录了 ...
- hibernate 批量处理数据
批量处理数据是指处理大量数据的一个单独的事务. 在应用层批处理操作, 主要有以下方式: 通过 Session 通过 HQL 通过 StatelessSession 通过 JDBC API(仅仅要会用这 ...
- 疯狂Java学习笔记(84)----------大约 Java 对象序列化,你不知道 5 事
几年前,.当一个软件团队一起用 Java 书面申请.我认识比一般程序猿多知道一点关于 Java 对象序列化的知识所带来的优点. 关于本系列 您认为自己懂 Java 编程?其实,大多数程序猿对于 Jav ...
- 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 ...
- DB2 “The transaction log for the database is full” 存在的问题及解决方案
DB2在执行一个大的insert/update操作的时候报"The transaction log for the database is full.. "错误,查了一下文档是DB ...
- Source Insight 光标变粗设置NotePad++光标设置
为了更好的查看文档和代码,避免半天都找不到光标的情况,故做此说明 Source Insight 光标变粗 菜单中 Options --->Preferences --->Typing -- ...