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, , 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的更多相关文章
- 实现Asp.net Mvc分布式Session Redis群集
Redis群集实现Asp.net Mvc分布式Session Session的缺点 众所周知Asp.net Session默认存储在IIS中,IIS的重启会导致Session丢失. 如果你的网站使用了 ...
- [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中Session的处理机制
本文章转载自 http://www.cnblogs.com/darrenji/p/3951065.html ASP.NET MVC中的Session以及处理方式 最近在ASP.NET MVC项目中 ...
- ASP.NET MVC之Session State性能问题(七)
前言 这一节翻译一篇有关Session State性能问题的文章,非一字一句翻译. 话题 不知道我们在真实环境中是否用到了Session State特性,它主要用来当在同一浏览器发出多个请求时来存储数 ...
- Spring Boot(十一)Redis集成从Docker安装到分布式Session共享
一.简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API,Redis也是技术领域使用最为广泛的存储中间件,它是 ...
- 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射
使用Code First建模自引用关系笔记 原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...
- Asp.net Mvc 自定义Session (一),
大家都知道用系统默认的session 会存在这样的问题 如果用户过多的话 session 会自动消亡,而且不能支持分布式和集群. 这系列博客主要讲解 怎样 解决用户过多的session自动消亡,和分 ...
- ASP.NET MVC Controller Session问题
发现问题 最近在项目中遇到这样一个问题,一直没办法重现,所以几天都没有解决. 测试那边给出的问题是这样的:每天早上来的时候,第一次通过单点登录到系统的时候,总会跳转回登录界面,再次登录就好了.当时给我 ...
随机推荐
- [RGeos]手簿
1.屏幕坐标以像素为单位,地图坐标通常以米为单位,CAD制图默认以毫米为单位. DPI是“dot per inch”的缩写.顾名思义,就是指在每英寸长度内的点数.通常,我们都使用dpi来作为扫描器和打 ...
- PHP Tab的Demo
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- C#线程系列讲座(4):同步与死锁
虽然线程可以在一定程度上提高程序运行的效率,但也会产生一些副作用.让我们先看看如下的代码: class Increment { private int n = 0; ...
- ssh隧道技术
大家都知道SSH是一种安全的传输协议,用在连接服务器上比较多.不过其实除了这个功能,它的隧道转发功能更是吸引人.下面是个人根据自己的需求以及在网上查找的资料配合自己的实际操作所得到的一些心得. SSH ...
- Java基础之集合框架——在文件中存储地图(TryPhoneBook2)
控制台程序. import java.io.*; public class Person implements Comparable<Person>, Serializable { // ...
- 学习OpenCV——配置CUDA环境
大家都把GPU&CUDA说的很NB狠NB,于是,下一步想通过GPU加速程序运行.这一个星期,都在配置OpenCV的CUDA环境,今天终于以失败告终,原因是实验室的机器显卡不支持CUDA...伤 ...
- java io读书笔记(3)数值类型的数据
input stream读取字节:out stream写入字节.Readers读取字符而Writers写入字符.因此,如果我们想理解input和output,我们首先就要明白 java如何处理字节,整 ...
- Java相对路径读取文件
不管你是新手还是老鸟,在程序中读取资源文件总会遇到一些找不到文件的问题,这与Java底层的实现有关,不能算bug,只要方法得当,问题还是可以解决的. 项目的文件夹结构: repathtest ├─sr ...
- 根据搜素的字符串改变label包含该字符串的文字
http://www.2cto.com/kf/201504/391811.html NSString *text =@"人生若只如初见"; //判断字符串所在的位置,并不区分大小写 ...
- [摘录]quarts:feature
Features of Quartz Runtime Environments Quartz can run embedded within another free standing applica ...