StackExchange.Redis学习笔记(一) 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服务启动成功
StackExchange.Redis学习笔记(一) Redis的使用初探的更多相关文章
- Redis学习笔记(4) Redis事务、生存时间及排序
1. Redis事务 Redis中的事务(transaction)是一组命令的集合,一个事务中的命令要么都执行,要么都不执行.事务的原理是先将属于一个事务的命令发送给Redis,然后再让Redis依次 ...
- Redis学习笔记(1) Redis介绍及基础
1. Redis的特性 (1) 存储结构 Redis(Remote Dictionary Server,远程字典服务器)是以字典结构存储数据,并允许其他应用通过TCP协议读写字典中的内容.Redis支 ...
- redis学习笔记之redis简介
redis简介 Redis是一个开源的,高性能的,基于键值对的缓存与存储系统,通过设置各种键值数据类型来适应不同场景下的缓存与存储需求.同事redis的诸多高层级功能使其可以胜任消息队列,任务队列等不 ...
- Redis学习笔记之Redis单机,伪集群,Sentinel主从复制的安装和配置
0x00 Redis简介 Redis是一款开源的.高性能的键-值存储(key-value store).它常被称作是一款数据结构服务器(data structure server). Redis的键值 ...
- StackExchange.Redis学习笔记(二) Redis查询 五种数据类型的应用
ConnectionMultiplexer ConnectionMultiplexer 是StackExchange.Redis的核心对象,用这个类的实例来进行Redis的一系列操作,对于一个整个应用 ...
- redis学习笔记(三)——redis的命令大全总结
总结了一些redis五种存储类型的常用命令以及一些通用操作命令,不是很全,是在学习的时候将学到的做了个汇总,使用的时候可以查一下. 笔记写在表格里面了,不好粘贴.......后面的直接截图了..... ...
- Redis学习笔记(3) Redis基础类型及命令之二
1. 集合类型 集合类型与列表类型有很多相似之处,但二者的区别在于:前者具有唯一性,但不具有有序性:后者具有有序性,但不具有唯一性.集合类型的常用操作是向集合中加入或删除元素.判断某个元素是否存在等, ...
- Redis学习笔记(2) Redis基础类型及命令之一
1. 基础命令 (1) 获取符合规则的键名列表 格式为:KEYS pattern 其中pattern表示支持通配符 # 建立一个名为bar的键 > SET bar OK # 获取Redis所有键 ...
- Redis学习笔记之Redis基本数据结构
Redis基础数据结构 Redis有5种基本数据结构:String(字符串).list(列表).set(集合).hash(哈希).zset(有序集合) 字符串string 字符串类型是Redis的va ...
随机推荐
- mybatis问题: There is no getter for property named 'equipmentId' in 'class java.lang.String'
本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...
- golang json 处理的一些例子代码
json 处理的例子代码, 解析结果看后面注释. package main import "encoding/json" import "fmt" impo ...
- HDU 2680(最短路)(多个起始点)
这道题也是死命TLE.. http://acm.hdu.edu.cn/showproblem.php?pid=2680 /* 使用pair代替结构 */ #include <iostream&g ...
- 移动端HTML5实现文件上传
PC端上传文件多半用插件,引入flash都没关系,但是移动端要是还用各种冗余的插件估计得被喷死,项目里面需要做图片上传的功能,既然H5已经有相关的接口且兼容性良好,当然优先考虑用H5来实现. 用的技术 ...
- 拆系数FFT(任意模数FFT)
拆系数FFT 对于任意模数 \(mod\) 设\(m=\sqrt {mod}\) 把多项式\(A(x)\)和\(B(x)\)的系数都拆成\(a\times m+b\)的形式,时\(a, b\)都小于\ ...
- PHP new StdClass() 创建空对象
PHP可以用 $object = new StdClass(); 创建一个没有成员方法和属性的空对象.很多时候,程序员们会将一些参数配置项之类的信息放在数组中使用,但是数组操作起来并不是很方便,很多时 ...
- 命令行下运行 java someClass.class出现 “错误:找不到或无法加载主类someClass ” 的解决方案
假设在C:\Java\code\目录下建立了如下 Test.java文件: package code; public class Test { public static void main(Stri ...
- Centos 7配置docker-阿里云镜像加速
阿里云加速网址:https://cr.console.aliyun.com/cn-hangzhou/mirrors(自行注册账密码) sudo mkdir -p /etc/docker sudo vi ...
- byr面经两则
人人,金山西山居,腾讯互娱,微信,网易游戏offer及面经 首先感谢师兄在两年前发的贴([天道酬勤] 腾讯.百度.网易游戏.华为Offer及笔经面经 ),这篇文章对我帮助很大. 我写这篇文章一是为了感 ...
- MVC项目后台管理,各页面判断登陆问题。
public class BaseController : Controller { protected string hostUrl = ""; /// <summary& ...