缓存工厂之Redis缓存
这几天没有按照计划分享技术博文,主要是去医院了,这里一想到在医院经历的种种,我真的有话要说;医院里的医务人员曾经被吹捧为美丽+和蔼+可亲的天使,在经受5天左右相互接触后不得不让感慨;遇见的有些人员在挂号队伍犹如长龙的时候坐在收费窗口玩手机,理由是自己是换班的差几分钟才上班呢;遇见态度极其恶劣的主任医师,做咨询几个问题声音马上提高并言语中携带讽刺话语;还有其他几个遇见哈哈这里就不多说了,可能是某些医务人员觉得多您个不少,我有的是客源,所以个别是这种态度吧,还是市医院真不知道怎么混进去的。
以上是个人的看法,下面来正式分享今天的文章吧:
。搭建Redis服务端,并用客户端连接
。封装缓存父类,定义Get,Set等常用方法
。定义RedisCache缓存类,执行Redis的Get,Set方法
。构造出缓存工厂调用方法
下面一步一个脚印的来分享:
。搭建Redis服务端,并用客户端连接
首先,咋们去这个地址下载安装文件https://github.com/dmajkic/redis/downloads,我这里的版本是:redis-2.4.5-win32-win64里面有32位和64位的执行文件,我这里服务器是64位的下面给出截图和用到部分程序的说明:
现在,咋们直接可以用鼠标双击redis-server.exe这个应用程序,这样就打开了redis服务窗体(您也可以下载一个windows服务承载器,把redis服务运行在windows的服务中,就不用担心每次关闭redis服务黑色窗体后无法访问redis了),运行起来是这样:
有红色框的信息就表示成功了,这里redis服务监听的端口默认是6379,要修改端口或者更多的配置信息请找到redis.conf配置文件,具体配置信息介绍可以来这里http://www.shouce.ren/api/view/a/6231
再来,打开客户端连接服务端,咋们退到64bit文件夹的目录中,鼠标移到64bit文件夹上并且安装Shift键,同时点击鼠标的右键,选中"在此处打开命令窗口"这样快速进入到了该文件夹的cmd命令窗口中(当然不同的操作系统不同,这里演示的是windows的操作;还有其他进入的方式这里不做介绍,因为个人感觉这是最快的);然后,在命令窗口中录入redis-cli.exe -h localhost -p 6379回车来访问服务端,效果图:
再来看下服务端窗体截图:
没错这样客户端就连接上服务端了,可以简单在客户端执行下set,get命令:
如果是客户端要访问远程的redis服务端,只需要把localhost换成可访问的ip就行了如果还需要密码等更多配置请去上面的那个地址链接;
。封装缓存父类,定义Get,Set等常用方法
先来,上父类的代码:
public class BaseCache : IDisposable
{
protected string def_ip = string.Empty;
protected int def_port = ;
protected string def_password = string.Empty; public BaseCache()
{ } public virtual void InitCache(string ip = "", int port = , string password = "")
{ } public virtual bool SetCache<T>(string key, T t, int timeOutMinute = ) where T : class,new()
{ return false;
} public virtual T GetCache<T>(string key) where T : class,new()
{ return default(T);
} public virtual bool Remove(string key)
{ return false;
} public virtual bool FlushAll()
{ return false;
} public virtual bool Any(string key)
{ return false;
} public virtual void Dispose(bool isfalse)
{ if (isfalse)
{ }
} //手动释放
public void Dispose()
{ this.Dispose(true);
//不自动释放
GC.SuppressFinalize(this);
}
}
这里定义的方法没有太多的注释,更多的意思我想看方法名称就明白了,这个父类主要实现了IDisposable,实现的Dispose()中主要用来释放资源并且自定义了一个 public virtual void Dispose(bool isfalse)方法,这里面有一句是GC.SuppressFinalize(this);按照官网介绍的意思是阻塞自动释放资源,其他的没有什么了,继续看下面的
。定义RedisCache缓存类,执行Redis的Get,Set方法
首先,咋们分别定义类RedisCache,MemcachedCache(这里暂未实现对memcache缓存的操作),并且继承BaseCache,重写Set,Get方法如下代码:
/// <summary>
/// Redis缓存
/// </summary>
public class RedisCache : BaseCache
{
public RedisClient redis = null; public RedisCache()
{ //这里去读取默认配置文件数据
def_ip = "172.0.0.1";
def_port = ;
def_password = "";
} #region Redis缓存 public override void InitCache(string ip = "", int port = , string password = "")
{ if (redis == null)
{
ip = string.IsNullOrEmpty(ip) ? def_ip : ip;
port = port == ? def_port : port;
password = string.IsNullOrEmpty(password) ? def_password : password; redis = new RedisClient(ip, port, password);
}
} public override bool SetCache<T>(string key, T t, int timeOutMinute = )
{ var isfalse = false; try
{
if (string.IsNullOrEmpty(key)) { return isfalse; } InitCache();
isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute));
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override T GetCache<T>(string key)
{
var t = default(T);
try
{
if (string.IsNullOrEmpty(key)) { return t; } InitCache();
t = redis.Get<T>(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return t;
} public override bool Remove(string key)
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; } InitCache();
isfalse = redis.Remove(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override void Dispose(bool isfalse)
{ if (isfalse && redis != null)
{ redis.Dispose();
redis = null;
}
} #endregion
} /// <summary>
/// Memcached缓存
/// </summary>
public class MemcachedCache : BaseCache
{ }
这里,用到的RedisClient类是来自nuget包引用的,这里nuget包是:
然后,来看下重写的InitCache方法,这里面有一些ip,port(端口),password(密码)参数,这里直接写入在cs文件中没有从配置文件读取,大家可以扩展下;这些参数通过RedisClient构造函数传递给底层Socket访问需要的信息,下面简单展示下RedisClient几个的构造函数:
public RedisClient();
public RedisClient(RedisEndpoint config);
public RedisClient(string host);
public RedisClient(Uri uri);
public RedisClient(string host, int port);
public RedisClient(string host, int port, string password = null, long db = );
至于Get,Set方法最终都是使用RedisClient对象访问的,个人觉得需要注意的是Set方法里面的过期时间参数,目前还没有试验这种情况的效果:
?通过这几种方法设置过期时间后,快到过期时间的时候如果此时有使用这个缓存key那么过期时间是否会往后自动增加过期时间有效期,这里暂时没有试验(这里是由于前面项目中的.net core框架中的memecache缓存都有这种设置,想来redis应该也有吧)
这里,需要重写下public override void Dispose(bool isfalse)方法,因为调用完RedisClient后需要释放,我们通过Dispose统一来手动释放,而不是直接在调用的时候使用using()
。构造出缓存工厂调用方法
接下来,咋们需要定义一个缓存工厂,因为上面刚才定义了一个RedisCache和MemcachedCache明显这里会有多个不同缓存的方法调用,所用咋们来定义个工厂模式来调用对应的缓存;这里的工厂模式没有使用直接显示创建new RedisCache(),new MemcachedCache()对象的方法,而是使用了反射的原理,创建对应的缓存对象;
先来,定义个枚举,枚举里面的声明的名字要和咋们缓存类的名称相同,代码如下:
public enum CacheType
{
RedisCache, MemcachedCache
}
再来,定义个工厂来CacheRepository(缓存工厂),并且定义方法Current如下代码:
public static BaseCache Current(CacheType cacheType = CacheType.RedisCache)
{
var nspace = typeof(BaseCache);
var fullName = nspace.FullName;
var nowspace = fullName.Substring(, fullName.LastIndexOf('.') + ); return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache;
}
*:通过传递枚举参数,来确定反射CreateInstance()方法需要用到的typeName参数,从而来定义需要访问的那个缓存对象,这里要注意的是加上了一个命名空间nowspace,因为缓存类可能和工厂类不是同一个命名空间,但是通常会和缓存基类是同命名空间所以在方法最开始的时候截取获取了缓存类需要的命名空间(这里看自身项目来定吧);
*:Assembly.GetExecutingAssembly()这个是用来获取当前应用程序集的路径,这里就避免了咋们使用Assembly.Load()方法还需要传递程序集的路径地址了
好了满上上面要求后,咋们可以在测试页面调用代码如:CacheRepository.Current(CacheType.RedisCache).SetCache<MoFlightSearchResponse>(keyData, value);就如此简单,咋们使用redis-cli.exe客户端来看下缓存起来的数据:
怎么样,您们的是什么效果呢,下面给出整体代码(最后更新时间:2016-09-29):
#region CacheRepository 缓存工厂(默认存储Session中) /// <summary>
/// 缓存枚举
/// </summary>
public enum CacheType
{
BaseCache, RedisCache, MemcachedCache
} /// <summary>
/// 缓存工厂(默认存储Session中)
/// </summary>
public class CacheRepository
{ /// <summary>
/// 缓存工厂(默认存储Session中, CacheKey = "SeesionKey")
/// </summary>
/// <param name="cacheType">缓存类型</param>
/// <returns></returns>
public static BaseCache Current(CacheType cacheType = CacheType.RedisCache)
{
var nspace = typeof(BaseCache);
var fullName = nspace.FullName;
var nowspace = fullName.Substring(, fullName.LastIndexOf('.') + ); return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache;
}
} /// <summary>
/// 缓存基类(默认存储Session中)
/// </summary>
public class BaseCache : IDisposable
{
protected string def_ip = string.Empty;
protected int def_port = ;
protected string def_password = string.Empty;
protected string CacheKey = "SeesionKey"; public BaseCache()
{ } /// <summary>
/// 获取自定义SessionId值
/// </summary>
/// <param name="key">key:使用唯一的登陆账号</param>
/// <returns>hash值的SessionId</returns>
public virtual string GetSessionId(string key)
{
return Md5Extend.GetSidMd5Hash(key);
} public virtual void InitCache(bool isReadAndWriter = true, string ip = "", int port = , string password = "")
{ } public virtual bool SetCache<T>(string key, T t, int timeOutMinute = , bool isSerilize = false) where T : class,new()
{
var isfalse = false; try
{
key = key ?? CacheKey;
if (t == null) { return isfalse; } var session_json = JsonConvert.SerializeObject(t);
HttpContext.Current.Session.Timeout = timeOutMinute;
HttpContext.Current.Session.Add(key, session_json);
isfalse = true;
}
catch (Exception ex)
{ throw new Exception(ex.Message);
}
return isfalse;
} public virtual T GetCache<T>(string key = null, bool isSerilize = false) where T : class,new()
{
var t = default(T); try
{ key = key ?? CacheKey;
var session = HttpContext.Current.Session[key];
if (session == null) { return t; } t = JsonConvert.DeserializeObject<T>(session.ToString());
}
catch (Exception ex)
{ throw new Exception(ex.Message);
}
return t;
} public virtual bool Remove(string key = null)
{
var isfalse = false; try
{
key = key ?? CacheKey;
HttpContext.Current.Session.Remove(key);
isfalse = true;
}
catch (Exception ex)
{ throw new Exception(ex.Message);
}
return isfalse;
} /// <summary>
/// 增加缓存时间
/// </summary>
/// <returns></returns>
public virtual bool AddExpire(string key, int nTimeMinute = )
{
return true;
} public virtual bool FlushAll()
{ return false;
} public virtual bool Any(string key)
{ return false;
} public virtual bool SetHashCache<T>(string hashId, string key, T t, int nTimeMinute = ) where T : class,new()
{ return false;
} public virtual List<string> GetHashKeys(string hashId)
{ return null;
} public virtual List<string> GetHashValues(string hashId)
{ return null;
} public virtual T GetHashValue<T>(string hashId, string key) where T : class,new()
{
var t = default(T);
return t;
} public virtual bool RemoveHashByKey(string hashId, string key)
{ return false;
} public virtual void Dispose(bool isfalse)
{ if (isfalse)
{ }
} //手动释放
public void Dispose()
{ this.Dispose(true);
//不自动释放
GC.SuppressFinalize(this);
}
} /// <summary>
/// Redis缓存
/// </summary>
public class RedisCache : BaseCache
{
public IRedisClient redis = null; public RedisCache()
{ //这里去读取默认配置文件数据
def_ip = "127.0.0.1";
def_port = ;
def_password = "";
} #region Redis缓存 public static object _lockCache = new object();
public override void InitCache(bool isReadAndWriter = true, string ip = "", int port = , string password = "")
{ if (redis == null)
{
ip = string.IsNullOrEmpty(ip) ? def_ip : ip;
port = port == ? def_port : port;
password = string.IsNullOrEmpty(password) ? def_password : password; //单个redis服务
//redis = new RedisClient(ip, port, password); //集群服务 如果密码,格式如:pwd@ip:port
var readAndWritePorts = new List<string> { "shenniubuxing3@127.0.0.1:6379" };
var onlyReadPorts = new List<string> {
"shenniubuxing3@127.0.0.1:6378",
"shenniubuxing3@127.0.0.1:6377"
}; var redisPool = new PooledRedisClientManager(
readAndWritePorts,
onlyReadPorts,
new RedisClientManagerConfig
{
AutoStart = true,
//最大读取链接
MaxReadPoolSize = ,
//最大写入链接
MaxWritePoolSize =
})
{
//每个链接超时时间
ConnectTimeout = ,
//连接池超时时间
PoolTimeout =
}; lock (_lockCache)
{
redis = isReadAndWriter ? redisPool.GetClient() : redisPool.GetReadOnlyClient();
}
}
} public override bool AddExpire(string key, int nTimeMinute = )
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; } InitCache();
//isfalse = redis.ExpireEntryIn(key, TimeSpan.FromMinutes(nTimeMinute));
isfalse = redis.ExpireEntryAt(key, DateTime.Now.AddMinutes(nTimeMinute));
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override bool SetCache<T>(string key, T t, int timeOutMinute = , bool isSerilize = false)
{ var isfalse = false; try
{
if (string.IsNullOrEmpty(key)) { return isfalse; } InitCache();
if (isSerilize)
{
var data = JsonConvert.SerializeObject(t);
var bb = System.Text.Encoding.UTF8.GetBytes(data);
isfalse = redis.Set<byte[]>(key, bb, TimeSpan.FromMinutes(timeOutMinute));
}
else { isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute)); }
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override T GetCache<T>(string key, bool isSerilize = false)
{
var t = default(T);
try
{
if (string.IsNullOrEmpty(key)) { return t; } InitCache(false);
if (isSerilize)
{ var bb = redis.Get<byte[]>(key);
if (bb.Length <= ) { return t; }
var data = System.Text.Encoding.UTF8.GetString(bb);
t = JsonConvert.DeserializeObject<T>(data);
}
else { t = redis.Get<T>(key); }
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return t;
} public override bool Remove(string key)
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; } InitCache();
isfalse = redis.Remove(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override bool SetHashCache<T>(string hashId, string key, T t, int nTimeMinute = )
{ var isfalse = false; try
{
if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(key) || t == null) { return isfalse; } InitCache(); var result = JsonConvert.SerializeObject(t);
if (string.IsNullOrEmpty(result)) { return isfalse; }
isfalse = redis.SetEntryInHash(hashId, key, result);
if (isfalse) { AddExpire(key, nTimeMinute); }
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override List<string> GetHashKeys(string hashId)
{
var hashKeys = new List<string>();
try
{
if (string.IsNullOrEmpty(hashId)) { return hashKeys; } InitCache();
hashKeys = redis.GetHashKeys(hashId); }
catch (Exception ex)
{
}
finally { this.Dispose(); }
return hashKeys;
} public override List<string> GetHashValues(string hashId)
{
var hashValues = new List<string>();
try
{
if (string.IsNullOrEmpty(hashId)) { return hashValues; } InitCache();
hashValues = redis.GetHashValues(hashId);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return hashValues;
} public override T GetHashValue<T>(string hashId, string key)
{
var t = default(T);
try
{
if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(key)) { return t; } InitCache();
var result = redis.GetValueFromHash(hashId, key);
if (string.IsNullOrEmpty(result)) { return t; } t = JsonConvert.DeserializeObject<T>(result);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return t;
} public override bool RemoveHashByKey(string hashId, string key)
{
var isfalse = false; try
{
if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(key)) { return isfalse; } InitCache();
isfalse = redis.RemoveEntryFromHash(hashId, key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
} public override void Dispose(bool isfalse)
{ if (isfalse && redis != null)
{ redis.Dispose();
redis = null;
}
} #endregion
} /// <summary>
/// Memcached缓存
/// </summary>
public class MemcachedCache : BaseCache
{ } #endregion
这次分享的Redis缓存从搭建到使用希望给您们有帮助,还请多多支持点赞,谢谢。
.2016-08-30号修改最新版本代码
缓存工厂之Redis缓存的更多相关文章
- Laravel之路——file缓存修改为redis缓存
1.Session: 修改.evn文件: SESSION_DRIVER:redis (如果还不行的话,修改config/session.php的driver) 2.缓存修改为redis 注意:使用 L ...
- 缓存策略:redis缓存之springCache
最近通过同学,突然知道服务器的缓存有很多猫腻,这里通过网上查询其他人的资料,进行记录: 缓存策略 比较简单的缓存策略: 1.失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放 ...
- 缓存机制总结(JVM内置缓存机制,MyBatis和Hibernate缓存机制,Redis缓存)
一.JVM内置缓存(值存放在JVM缓存中) 我们可以先了解一下Cookie,Session,和Cache Cookie:当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cooki ...
- Windows Azure Redis 缓存服务
8月20日,Windows Azure (中国版)开始提供Redis缓存服务,比较国际版的Microsoft Azure晚了差不多一年的时间.说实话,微软真不应该将这个重要的功能delay这么长时间, ...
- 本地缓存,Redis缓存,数据库DB查询(结合代码分析)
问题背景 为什么要使用缓存?本地缓存/Redis缓存/数据库查询优先级? 一.为什么要使用缓存 原因:CPU的速度远远高于磁盘IO的速度问题:很多信息存在数据库当中的,每次查询数据库就是一次IO操作所 ...
- SpringBoot集成Redis分布式锁以及Redis缓存
https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...
- Redis 缓存失效机制
Redis缓存失效的故事要从EXPIRE这个命令说起,EXPIRE允许用户为某个key指定超时时间,当超过这个时间之后key对应的值会被清除,这篇文章主要在分析Redis源码的基础上站在Redis设计 ...
- TP5中用redis缓存
在config.php配置文件下找到缓存设置,将原来的文件缓存修改为redis缓存,也可以改为多种类型的缓存: // +---------------------------------------- ...
- redis缓存使用详解
mysql数据库是存在磁盘中的,操作是对于磁盘操作,这样访问量和并发很大时,运行速率就取决于磁盘的容量,带宽的大小和读取的方式,也就是 sql 语句,次数和效率也会影响读取效率.当访问量和并发很大的时 ...
随机推荐
- 微信企业号 获取AccessToken
目录 1. AccessToken介绍 2. 示例代码 1. AccessToken介绍 1.1 什么是AccessToken AccessToken即访问凭证,业务服务器每次主动调用企业号接口时需要 ...
- 编写高质量代码:改善Java程序的151个建议(第5章:数组和集合___建议75~78)
建议75:集合中的元素必须做到compareTo和equals同步 实现了Comparable接口的元素就可以排序,compareTo方法是Comparable接口要求必须实现的,它与equals方法 ...
- ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core
背景: 1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了. 2:.NET Core 有新的Memory Cache提供, ...
- Partition:分区切换(Switch)
在SQL Server中,对超级大表做数据归档,使用select和delete命令是十分耗费CPU时间和Disk空间的,SQL Server必须记录相应数量的事务日志,而使用switch操作归档分区表 ...
- 06.SQLServer性能优化之---数据库级日记监控
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 之前说了一下数据库怎么发邮件:http://www.cnblogs.com/duniti ...
- css3中perspective
perspective 属性定义 3D 元素距视图的距离,以像素计.该属性允许改变 3D 元素查看 3D 元素的视图.当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本 ...
- Base64编码
Base64编码 写在前面 今天在做一个Android app时遇到了一个问题:Android端采用ASE对称加密的数据在JavaWeb(jre1.8.0_7)后台解密时,居然解密失败了!经过测试后发 ...
- [C#] 简单的 Helper 封装 -- CookieHelper
using System; using System.Web; namespace ConsoleApplication5 { /// <summary> /// Cookie 助手 // ...
- 设置line-height:1.5和line-height:150%或者line-height:150px的区别
直接正题: 看一下line-height可能的值: 其实可以分为两类: (1)不带单位的(如line-height:1.5),这种是推荐使用的: (2)带单位的(如line-heigth:30px/1 ...
- angular2之前端篇—1(node服务器分支)
上一篇.net core和angular2之前端篇-1 使用的是dotnet模板.之所以用它,因为想用他写webapi,但是写道下一篇的时候遇到点问题,所以先写个分支测试一下.这次是用Node作为服务 ...