Redis的使用初探
Redis
- Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。
- 与其它键值数据存储相比,Redis有一组相对丰富的数据类型。
- Redis可以将数据复制到任意数量的从机中
Redis的安装
官网只提供了linux的安装包,我win10 的系统,在github上下载的windows安装包 3.0.504最新稳定版的
github地址:https://github.com/MicrosoftArchive/redis/releases
官网下载地址:https://redis.io/download
将压缩包解压到文件夹后,双击“redis-server.exe”即可启动redis服务,也可以在环境变量中配置之后,用redis-server 命令来开启服务,以下是服务启动成功界面

Redis的使用
C#可选用ServiceStack.Redis或者StackExchange.Redis等客户端程序操作redis,由于ServiceStack.Redis已经收费了,我这里用的是StackExchange.Redis,通过Nuget安装到项目中

接下来我们创建一个操作redis的帮助类:
public static class StackExchangeRedisHelper
{
private static readonly string Coonstr = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString;//
private static object _locker = new Object();
private static ConnectionMultiplexer _instance = null;
/// <summary>
/// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
/// </summary>
public static ConnectionMultiplexer Instance
{
get
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null || !_instance.IsConnected)
{
_instance = ConnectionMultiplexer.Connect(Coonstr);
}
}
}
//注册如下事件
_instance.ConnectionFailed += MuxerConnectionFailed;
_instance.ConnectionRestored += MuxerConnectionRestored;
_instance.ErrorMessage += MuxerErrorMessage;
_instance.ConfigurationChanged += MuxerConfigurationChanged;
_instance.HashSlotMoved += MuxerHashSlotMoved;
_instance.InternalError += MuxerInternalError;
return _instance;
}
} static StackExchangeRedisHelper()
{
} /// <summary>
///
/// </summary>
/// <returns></returns>
public static IDatabase GetDatabase()
{
return Instance.GetDatabase();
} /// <summary>
/// 这里的 MergeKey 用来拼接 Key 的前缀,具体不同的业务模块使用不同的前缀。
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private static string MergeKey(string key)
{
return BaseSystemInfo.SystemCode + key;
}
/// <summary>
/// 根据key获取缓存对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static T Get<T>(string key)
{
key = MergeKey(key);
return Deserialize<T>(GetDatabase().StringGet(key));
}
/// <summary>
/// 根据key获取缓存对象
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static object Get(string key)
{
key = MergeKey(key);
return Deserialize<object>(GetDatabase().StringGet(key));
} /// <summary>
/// 设置缓存
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public static void Set(string key, object value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags flags = CommandFlags.None)
{
key = MergeKey(key);
GetDatabase().StringSet(key, Serialize(value), expiry, when, flags);
} /// <summary>
/// 判断在缓存中是否存在该key的缓存数据
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool Exists(string key)
{
key = MergeKey(key);
return GetDatabase().KeyExists(key); //可直接调用
} /// <summary>
/// 移除指定key的缓存
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static bool Remove(string key)
{
key = MergeKey(key);
return GetDatabase().KeyDelete(key);
} /// <summary>
/// 异步设置
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public static async Task SetAsync(string key, object value)
{
key = MergeKey(key);
await GetDatabase().StringSetAsync(key, Serialize(value));
} /// <summary>
/// 根据key获取缓存对象
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static async Task<object> GetAsync(string key)
{
key = MergeKey(key);
object value = await GetDatabase().StringGetAsync(key);
return value;
} /// <summary>
/// 实现递增
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public static long Increment(string key)
{
key = MergeKey(key);
//三种命令模式
//Sync,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。
//Async,异步模式直接走的是Task模型。
//Fire - and - Forget,就是发送命令,然后完全不关心最终什么时候完成命令操作。
//即发即弃:通过配置 CommandFlags 来实现即发即弃功能,在该实例中该方法会立即返回,如果是string则返回null 如果是int则返回0.这个操作将会继续在后台运行,一个典型的用法页面计数器的实现:
return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
} /// <summary>
/// 实现递减
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static long Decrement(string key, string value)
{
key = MergeKey(key);
return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget);
} /// <summary>
/// 序列化对象
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
static byte[] Serialize(object o)
{
if (o == null)
{
return null;
}
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, o);
byte[] objectDataAsStream = memoryStream.ToArray();
return objectDataAsStream;
}
} /// <summary>
/// 反序列化对象
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="stream"></param>
/// <returns></returns>
static T Deserialize<T>(byte[] stream)
{
if (stream == null)
{
return default(T);
}
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream(stream))
{
T result = (T)binaryFormatter.Deserialize(memoryStream);
return result;
}
}
/// <summary>
/// 配置更改时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
{
LogHelper.WriteInfoLog("Configuration changed: " + e.EndPoint);
}
/// <summary>
/// 发生错误时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
{
LogHelper.WriteInfoLog("ErrorMessage: " + e.Message);
}
/// <summary>
/// 重新建立连接之前的错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
{
LogHelper.WriteInfoLog("ConnectionRestored: " + e.EndPoint);
}
/// <summary>
/// 连接失败 , 如果重新连接成功你将不会收到这个通知
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
LogHelper.WriteInfoLog("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
}
/// <summary>
/// 更改集群
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
{
LogHelper.WriteInfoLog("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
}
/// <summary>
/// redis类库错误
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
{
LogHelper.WriteInfoLog("InternalError:Message" + e.Exception.Message);
} //场景不一样,选择的模式便会不一样,大家可以按照自己系统架构情况合理选择长连接还是Lazy。
//建立连接后,通过调用ConnectionMultiplexer.GetDatabase 方法返回对 Redis Cache 数据库的引用。从 GetDatabase 方法返回的对象是一个轻量级直通对象,不需要进行存储。 /// <summary>
/// 使用的是Lazy,在真正需要连接时创建连接。
/// 延迟加载技术
/// 微软azure中的配置 连接模板
/// </summary>
//private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
//{
// //var options = ConfigurationOptions.Parse(constr);
// ////options.ClientName = GetAppName(); // only known at runtime
// //options.AllowAdmin = true;
// //return ConnectionMultiplexer.Connect(options);
// ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr);
// muxer.ConnectionFailed += MuxerConnectionFailed;
// muxer.ConnectionRestored += MuxerConnectionRestored;
// muxer.ErrorMessage += MuxerErrorMessage;
// muxer.ConfigurationChanged += MuxerConfigurationChanged;
// muxer.HashSlotMoved += MuxerHashSlotMoved;
// muxer.InternalError += MuxerInternalError;
// return muxer;
//}); #region 当作消息代理中间件使用 一般使用更专业的消息队列来处理这种业务场景
/// <summary>
/// 当作消息代理中间件使用
/// 消息组建中,重要的概念便是生产者,消费者,消息中间件。
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public static long Publish(string channel, string message)
{
ISubscriber sub = Instance.GetSubscriber();
//return sub.Publish("messages", "hello");
return sub.Publish(channel, message);
} /// <summary>
/// 在消费者端得到该消息并输出
/// </summary>
/// <param name="channelFrom"></param>
/// <returns></returns>
public static void Subscribe(string channelFrom)
{
ISubscriber sub = Instance.GetSubscriber();
sub.Subscribe(channelFrom, (channel, message) =>
{
Console.WriteLine((string)message);
});
}
#endregion /// <summary>
/// GetServer方法会接收一个EndPoint类或者一个唯一标识一台服务器的键值对
/// 有时候需要为单个服务器指定特定的命令
/// 使用IServer可以使用所有的shell命令,比如:
/// DateTime lastSave = server.LastSave();
/// ClientInfo[] clients = server.ClientList();
/// 如果报错在连接字符串后加 ,allowAdmin=true;
/// </summary>
/// <returns></returns>
public static IServer GetServer(string host, int port)
{
IServer server = Instance.GetServer(host, port);
return server;
} /// <summary>
/// 获取全部终结点
/// </summary>
/// <returns></returns>
public static EndPoint[] GetEndPoints()
{
EndPoint[] endpoints = Instance.GetEndPoints();
return endpoints;
} } internal class BaseSystemInfo
{
internal static readonly string SystemCode="000A";
}
测试代码
static void Main(string[] args)
{
RedisTest();
}
public static void RedisTest()
{
Console.WriteLine("Redis写入缓存:Name:张三丰");
StackExchangeRedisHelper.Set("Name", "张三丰", new TimeSpan(, , , , ));
Console.WriteLine("Redis获取缓存:Name:" + StackExchangeRedisHelper.Get("Name").ToString());
Thread.Sleep();
Console.WriteLine("一秒后Redis获取缓存:Name:" + StackExchangeRedisHelper.Get("Name")??"");
Console.ReadKey();
}

也可以通过Execute来直接运行redis命令

Redis加入Windows服务
由于关闭控制台redis就自动关闭了,所以把redis加入windows服务更好一些
切换到redis目录下运行命令:redis-server --service-install redis.windows-service.conf --loglevel verbose


移除服务:--service-uninstal
开启服务:redis-server --service-start
关闭服务:redis-server --service-stop
在开启Redis服务时遇到一些坑,
redis.windows-service.conf中配置:
1. logfile "Logs/redis_log.txt"需要有对应的目录
2.将bind 127.0.0.1注释去掉
3.依然有问题,后参考一篇文章 http://blog.csdn.net/fengzhihen2007/article/details/52211048

直到出现successfully started服务启动成功
Redis的使用初探的更多相关文章
- StackExchange.Redis学习笔记(一) Redis的使用初探
Redis Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化. 与其它键值数据存储相比,Redis有一组相对丰富的数据类型. Redis可以将数据复制到任意数量的从机中 Redis的安装 官 ...
- redis源码学习之工作流程初探
目录 背景 环境准备 下载redis源码 下载Visual Studio Visual Studio打开redis源码 启动过程分析 调用关系图 事件循环分析 工作模型 代码分析 动画演示 网络模块 ...
- .NET中使用Redis
Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http://redis.io/. 最近 ...
- 转:.NET中使用Redis (一)
原文来自于:http://blog.jobbole.com/83821/ 原文出处: 寒江独钓 欢迎分享原创到伯乐头条 Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Gi ...
- 全面剖析Redis Cluster原理和应用 (转)
1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最核心的目标有三个: 性能:这是Redis赖以生 ...
- 全面剖析Redis Cluster原理和应用
全面剖析Redis Cluster原理和应用 1.Redis Cluster总览 1.1 设计原则和初衷 在官方文档Cluster Spec中,作者详细介绍了Redis集群为什么要设计成现在的样子.最 ...
- 【每日更新】【Redis学习】
5. Redis订阅和发布模式和Redis事务 -------------------Redis事务------------------- 1.概念: redis中的事务是一组命令的集合.事务 ...
- .NET中使用Redis 转发
.NET中使用Redis Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http: ...
- .NET中使用Redis:http://www.cnblogs.com/yangecnu/p/Introduct-Redis-in-DotNET.html
.NET中使用Redis Redis是一个用的比较广泛的Key/Value的内存数据库,新浪微博.Github.StackOverflow 等大型应用中都用其作为缓存,Redis的官网为http: ...
随机推荐
- js中判断对象数据类型的方法
对js中不同数据的布尔值类型总结:false:空字符串:null:undefined:0:NaN.true:除了上面的false的情况其他都为true: 如下: var o = { 'name':'l ...
- 初识Hibernate之理解持久化类
上一篇文章我们简单介绍了Hibernate相关的一些最基本的文件及其作用,并在最后完整的搭建了Hibernate的运行环境,成功的完成了与数据库的映射.但是至于其中的一些更加细节的地方并没有 ...
- P1013
问题 D: P1013 时间限制: 1 Sec 内存限制: 128 MB提交: 33 解决: 21[提交][状态][讨论版] 题目描述 " 找啊找啊找GF,找到一个好GF,吃顿饭啊拉拉手 ...
- EnCase missed some usb activities in the evidence files
My friend is a developer and her colleague May was suspected of stealing the source code of an impor ...
- Island Perimeter
You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represen ...
- KM算法的应用
HDU2255 模板 难度x HDU2282 思维 难度XXx HDU3722 模板 难度X HDU3395 模版 HDU1533 最小值模型 难度x HDU2853 HDU3 ...
- windows 本地构建hadoop-spark运行环境(hadoop-2.6, spark2.0)
下载hadoop http://hadoop.apache.org/releases.html --> http://mirrors.tuna.tsinghua.edu.cn/apache/ha ...
- MyBatis开发中解决返回字段不全的问题
场景重现: mybatis 在查询的时候,可以返回Map,但是一旦这个字段为空(null)的时候,map里就没有了.我用的是mysql数据库,除了在查询语句上做ifnull判断给它默认值外,有没的别的 ...
- Session详解及集群共享
Session的介绍 维基百科:会话(session)是一种持久网络协议,在用户(或用户代理)端和服务器端之间创建关联,从而起到交换数据包的作用机制,session在网络协议(例如telnet或FTP ...
- C# 使用itextsharp 读取pdf中文字坐标
程序调用: using iTextSharp.text.pdf; using System; using System.Collections.Generic; using System.Linq ...