Redis 安装 & 配置

本测试环境将在 CentOS 7 x64 上安装最新版本的 Redis。

1. 运行以下命令安装 Redis

$ wget http://download.redis.io/releases/redis-3.2.6.tar.gz
$ tar xzf redis-3.2.6.tar.gz
$ cd redis-3.2.6
$ make install

如果 CentOS 上提示 wget 命令未找到,则先安装 net-tools。

yum install net-tools

2. Redis 配置文件

1)开启守护程序

修改 daemonize 节点为 yes。

2)运行外部IP访问

配置 bind 节点为 0.0.0.0

本次示例只使用 Redis 的缓存 所以配置暂时只修改这两处即可。

3. 设置 Redis 开机自动启动

1)在 Redis 的源码包中找到 utils 目录

2) 将 redis_init_script 文件复制到 /etc/init.d 目录下并重命名为 redisd

cp redis_init_script /etc/init.d/redisd

3) 打开 redisd 修改部分配置。

 #!/bin/sh
# chkconfig: 2345 90 10
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem. REDISPORT=6379
EXEC=/usr/local/bin/redis-server
CLIEXEC=/usr/local/bin/redis-cli PIDFILE=/var/run/redis_${REDISPORT}.pid
CONF="/etc/redis/redis_${REDISPORT}.conf"

其中第二行 # chkconfig: 2345 90 10 需要另行添加。

- REDISPORT Redis 运行端口号;

- EXEC Redis 服务器命令文件路径(根据实际情况修改);

- CLIEXEC Redis 客户端命令文件路径(亦根据实际情况修改);

- CONF Redis 配置文件。

4)设置开机启动 & 启动、停止服务

#设置为开机自启动服务器
chkconfig redisd on
#打开服务
service redisd start
#关闭服务
service redisd stop

主:如果外部机器还访问不到 Redis 服务器,请将 6379 端口号加防火墙例外即可。

代码实现:

Common 包 接口定义 & 分布式缓存实例获取和配置

- IDistributedCache 接口
 using System;

 namespace Wlitsoft.Framework.Common.Core
{
/// <summary>
/// 分布式缓存接口。
/// </summary>
public interface IDistributedCache
{
/// <summary>
/// 获取缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <returns>获取到的缓存。</returns>
T Get<T>(string key); /// <summary>
/// 设置缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="value">要缓存的对象。</param>
void Set<T>(string key, T value); /// <summary>
/// 设置缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="value">要缓存的对象。</param>
/// <param name="expiredTime">过期时间。</param>
void Set<T>(string key, T value, TimeSpan expiredTime); /// <summary>
/// 判断指定键值的缓存是否存在。
/// </summary>
/// <param name="key">缓存键值。</param>
/// <returns>一个布尔值,表示缓存是否存在。</returns>
bool Exists(string key); /// <summary>
/// 移除指定键值的缓存。
/// </summary>
/// <param name="key">缓存键值。</param>
bool Remove(string key); /// <summary>
/// 获取 Hash 表中的缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">要获取的 hash 字段。</param>
/// <returns>获取到的缓存。</returns>
T GetHash<T>(string key, string hashField); /// <summary>
/// 设置 缓存到 Hash 表。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">要设置的 hash 字段。</param>
/// <param name="hashValue">要设置的 hash 值。</param>
void SetHash<T>(string key, string hashField, T hashValue); /// <summary>
/// 判断指定键值的 Hash 缓存是否存在。
/// </summary>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">hash 字段。</param>
/// <returns>一个布尔值,表示缓存是否存在。</returns>
bool ExistsHash(string key, string hashField); /// <summary>
/// 删除 hash 表中的指定字段的缓存。
/// </summary>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">hash 字段。</param>
/// <returns>一个布尔值,表示缓存是否删除成功。</returns>
bool DeleteHash(string key, string hashField);
}
}

- App 类

 /// <summary>
/// 获取分布式缓存。
/// </summary>
public static IDistributedCache DistributedCache { get; internal set; }

- AppBuilder 类

 namespace Wlitsoft.Framework.Common
{
/// <summary>
/// 应用 构造。
/// </summary>
public class AppBuilder
{
#region 添加序列化者 /// <summary>
/// 添加序列化者。
/// </summary>
/// <param name="type">序列化类型。</param>
/// <param name="serializer">序列化者接口。</param>
public void AddSerializer(SerializeType type, ISerializer serializer)
{
#region 参数校验 if (serializer == null)
throw new ObjectNullException(nameof(serializer)); #endregion App.SerializerService.SetSerializer(type, serializer);
} #endregion #region 添加日志记录者 /// <summary>
/// 添加日志记录者。
/// </summary>
/// <param name="name">日志记录者名称。</param>
/// <param name="logger">日志接口。</param>
public void AddLogger(string name, ILog logger)
{
#region 参数校验 if (string.IsNullOrEmpty(name))
throw new StringNullOrEmptyException(nameof(name)); if (logger == null)
throw new ObjectNullException(nameof(logger)); #endregion App.LoggerService.SetLogger(name, logger);
} #endregion #region 设置分布式缓存 /// <summary>
/// 设置分布式缓存。
/// </summary>
/// <param name="cache">分布式缓存实例。</param>
/// <returns></returns>
public AppBuilder SetDistributedCache(IDistributedCache cache)
{
#region 参数校验 if (cache == null)
throw new ObjectNullException(nameof(cache)); #endregion App.DistributedCache = cache;
return this;
} #endregion
}
}

分布式缓存 Redis 实现

- RedisCache 类

 using System;
using System.Linq;
using System.Threading;
using StackExchange.Redis;
using Wlitsoft.Framework.Common.Core;
using Wlitsoft.Framework.Common.Extension;
using Wlitsoft.Framework.Common.Exception; namespace Wlitsoft.Framework.Caching.Redis
{
/// <summary>
/// Redis 缓存。
/// </summary>
public class RedisCache : IDistributedCache
{
#region 私有属性 //redis 连接实例。
private volatile ConnectionMultiplexer _connection; //redis 缓存数据库实例。
private IDatabase _database; //连接实例锁。
private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(, ); //Redis 配置。
internal static RedisCacheConfiguration RedisCacheConfiguration; #endregion #region IDistributedCache 成员 /// <summary>
/// 获取缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <returns>获取到的缓存。</returns>
public T Get<T>(string key)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); #endregion this.Connect();
string result = this._database.StringGet(key);
if (string.IsNullOrEmpty(result))
return default(T);
return result.ToJsonObject<T>();
} /// <summary>
/// 设置缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="value">要缓存的对象。</param>
public void Set<T>(string key, T value)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); if (value == null)
throw new ObjectNullException(nameof(value)); #endregion this.Connect();
this._database.StringSet(key, value.ToJsonString());
} /// <summary>
/// 设置缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="value">要缓存的对象。</param>
/// <param name="expiredTime">过期时间。</param>
public void Set<T>(string key, T value, TimeSpan expiredTime)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); if (value == null)
throw new ObjectNullException(nameof(value)); #endregion this.Connect();
this._database.StringSet(key, value.ToJsonString(), expiredTime);
} /// <summary>
/// 判断指定键值的缓存是否存在。
/// </summary>
/// <param name="key">缓存键值。</param>
/// <returns>一个布尔值,表示缓存是否存在。</returns>
public bool Exists(string key)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); #endregion this.Connect();
return this._database.KeyExists(key);
} /// <summary>
/// 移除指定键值的缓存。
/// </summary>
/// <param name="key">缓存键值。</param>
public bool Remove(string key)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); #endregion this.Connect();
return this._database.KeyDelete(key);
} /// <summary>
/// 获取 Hash 表中的缓存。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">要获取的 hash 字段。</param>
/// <returns>获取到的缓存。</returns>
public T GetHash<T>(string key, string hashField)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); if (string.IsNullOrEmpty(hashField))
throw new StringNullOrEmptyException(nameof(hashField)); #endregion this.Connect();
string value = this._database.HashGet(key, hashField);
if (string.IsNullOrEmpty(value))
return default(T);
return value.ToJsonObject<T>();
} /// <summary>
/// 设置 缓存到 Hash 表。
/// </summary>
/// <typeparam name="T">缓存类型。</typeparam>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">要设置的 hash 字段。</param>
/// <param name="hashValue">要设置的 hash 值。</param>
public void SetHash<T>(string key, string hashField, T hashValue)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); if (string.IsNullOrEmpty(hashField))
throw new StringNullOrEmptyException(nameof(hashField)); if (hashValue == null)
throw new ObjectNullException(nameof(hashValue)); #endregion this.Connect();
this._database.HashSet(key, hashField, hashValue.ToJsonString());
} /// <summary>
/// 判断指定键值的 Hash 缓存是否存在。
/// </summary>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">hash 字段。</param>
/// <returns>一个布尔值,表示缓存是否存在。</returns>
public bool ExistsHash(string key, string hashField)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); if (string.IsNullOrEmpty(hashField))
throw new StringNullOrEmptyException(nameof(hashField)); #endregion this.Connect();
return this._database.HashExists(key, hashField);
} /// <summary>
/// 删除 hash 表中的指定字段的缓存。
/// </summary>
/// <param name="key">缓存键值。</param>
/// <param name="hashField">hash 字段。</param>
/// <returns>一个布尔值,表示缓存是否删除成功。</returns>
public bool DeleteHash(string key, string hashField)
{
#region 参数校验 if (string.IsNullOrEmpty(key))
throw new StringNullOrEmptyException(nameof(key)); if (string.IsNullOrEmpty(hashField))
throw new StringNullOrEmptyException(nameof(hashField)); #endregion this.Connect();
return this._database.HashDelete(key, hashField);
} #endregion #region 私有方法 /// <summary>
/// 连接。
/// </summary>
private void Connect()
{
if (this._connection != null)
return; this._connectionLock.Wait();
try
{
if (this._connection == null)
{
this._connection = ConnectionMultiplexer.Connect(this.GetConfigurationOptions());
this._database = this._connection.GetDatabase();
}
}
finally
{
this._connectionLock.Release();
}
} private ConfigurationOptions GetConfigurationOptions()
{
#region 校验 if (RedisCacheConfiguration == null)
throw new ObjectNullException(nameof(RedisCacheConfiguration)); if (!RedisCacheConfiguration.HostAndPoints.Any())
throw new Exception("RedisCahce 的 HostAndPoints 不能为空"); #endregion ConfigurationOptions options = new ConfigurationOptions(); foreach (string item in RedisCacheConfiguration.HostAndPoints)
options.EndPoints.Add(item); options.ConnectRetry = RedisCacheConfiguration.ConnectRetry;
options.ConnectTimeout = RedisCacheConfiguration.ConnectTimeout; return options;
} #endregion #region 析构函数 /// <summary>
/// 析构 <see cref="RedisCache"/> 类型的对象。
/// </summary>
~RedisCache()
{
_connection?.Close();
} #endregion
}
}

一个技术汪的开源梦 —— 公共组件缓存之分布式缓存 Redis 实现篇的更多相关文章

  1. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之 Http 请求客户端

    一个技术汪的开源梦 —— 目录 想必大家在项目开发的时候应该都在程序中调用过自己内部的接口或者使用过第三方提供的接口,咱今天不讨论 REST ,最常用的请求应该就是 GET 和 POST 了,那下面开 ...

  2. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之序列化

    一个技术汪的开源梦 —— 目录 想必大家在项目中都接触过 JSON 或者 XML 吧,为了将对象在网络上传输或者将其持久化必须将其序列化为一个字符串然后进行后续操作.常见的就是将其序列化成 JSON ...

  3. 一个技术汪的开源梦 —— 基于 .Net Core 的公共组件之目录结构

    一个技术汪的开源梦 —— 目录 这篇文章是开源公共组件的开篇那就先说说项目的 Github 目录结构和 .Net Core 的项目结构. 1. GitHub 目录结构和相关文件 - src 源码项目目 ...

  4. 一个技术汪的开源梦 —— 基于 .Net Core 的组件 Nuget 包制作 & 发布

    一个技术汪的开源梦 —— 目录 微软的 ASP.Net Core 强化了 Nuget 的使用,所有的 .Net Core 组件均有 Nuget 管理,所以有必要探讨一下 .Net Core 组件制作 ...

  5. 一个技术汪的开源梦 —— 微信开发工具包(WeixinSDK)

    由于春节的关系 WeixinSDK 这个开源项目的进展比预期推迟了大约一个月的时间,值得高兴的是到目前为止该项目的重要模块已经开发完毕.  - 关于项目 该项目的背景是现在微信公众号.微信服务号乃至微 ...

  6. Net Core 的公共组件之 Http 请求客户端

    Net Core 的公共组件之 Http 请求客户端 想必大家在项目开发的时候应该都在程序中调用过自己内部的接口或者使用过第三方提供的接口,咱今天不讨论 REST ,最常用的请求应该就是 GET 和 ...

  7. 【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)

    一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...

  8. 表单配置项写法,表单写成JSON数组套对象,一行是一个数组单位,一列是一个对象单位,然后再写一个公共组件读取这个配置,循环加载slot,外层载入slot的自定义部分,比如input select等,这种写法就是把组件嵌套改为配置方式

    表单配置项写法,表单写成JSON数组套对象,一行是一个数组单位,一列是一个对象单位,然后再写一个公共组件读取这个配置,循环加载slot,外层载入slot的自定义部分,比如input select等,这 ...

  9. 利用vue-cropper做的关于图片裁剪、压缩、上传、预览等做的一个公共组件

    公共组件: <template> <div> <div class="upload-box"> <div class="imag ...

随机推荐

  1. 03.SQLServer性能优化之---存储优化系列

    汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 概  述:http://www.cnblogs.com/dunitian/p/60413 ...

  2. 踩石行动:ViewPager无限轮播的坑

    2016-6-19 前言 View轮播效果在app中很常见,一想到左右滑动的效果就很容易想到使用ViewPager来实现.对于像我们常说的banner这样的效果,具备无限滑动的功能是可以用ViewPa ...

  3. 冒泡,setinterval,背景图的div绑定事件,匿名函数问题

    1.会冒泡到兄弟元素么? $(function(){ $("#a").click(function(){alert("a")}) $("#b" ...

  4. IE8/9 JQuery.Ajax 上传文件无效

    IE8/9 JQuery.Ajax 上传文件有两个限制: 使用 JQuery.Ajax 无法上传文件(因为无法使用 FormData,FormData 是 HTML5 的一个特性,IE8/9 不支持) ...

  5. BI分析受阻?FineBI推出SPA螺旋式分析新功能!

    过去,企业级的数据分析通常会有这么几种场景,业务部门托信息部门分析数据,结果报表一出,唇枪舌剑争论你我高低,数据不准,指标不对.信息部门欠缺业务概念,业务部门不懂技术逻辑,数据分析之路,暂时搁浅. 后 ...

  6. oracle 误删数据恢复

    1.根据时间点查系统版本号scn: select timestamp_to_scn(to_timestamp('2013-01-07 11:20:00','YYYY-MM-DD HH:MI:SS')) ...

  7. mono for android学习过程系列教程(1)

    直接进入主题,关于mono for android的学习,首先配置好环境,如何配置环境,度娘谷歌一大堆,记得使用破解版. 我自己是百度“黑马四期”传智播客的视频,里面有破解版开发环境的软件. 今天直接 ...

  8. 浅谈浏览器http的缓存机制

    针对浏览器的http缓存的分析也算是老生常谈了,每隔一段时间就会冒出一篇不错的文章,其原理也是各大公司面试时几乎必考的问题. 之所以还写一篇这样的文章,是因为近期都在搞新技术,想“回归”下基础,也希望 ...

  9. 吐血大奉献,打造cnblogs最新最火辣的css3模板(IE9以下请勿入内) -- 第一版

    一直自己都想给自己的博客打造一个独一无二的皮肤,但是一直没有强劲的动力去完成这件事情.后来凭借着工作上面的需求(涉及到css3),就把自己的博客当成一个最好的试验场地.从而产生了你现在所看到的这个模板 ...

  10. Linux简单指令操作

    Linux CentOS运维中,常用的操作和命令记录下: 1.DNS设置 在Linux服务器上,当我们ping出现这个错误时:ping: unknown host,很大可能是系统的DNS没有设置或者设 ...