• C#如何使用StackExchange.Redis访问Redis
  • 发布于 2个月前
  • 348 热度
    0 评论
  • 离人愁
  • 0 粉丝 27 篇博客
  •   
基本用法
StackExchange.Redis中的中心对象是名称空间中的ConnectionMultiplexer类StackExchange.Redis。这是隐藏多个服务器详细信息的对象。由于ConnectionMultiplexer功能很多,因此可以在调用方之间共享和重用它。您不应该创建ConnectionMultiplexer每个操作。它是完全线程安全的,并且可以用于此用途。在所有后续示例中,将假定您已ConnectionMultiplexer保存一个实例以供重用。但是现在,让我们创建一个。这可以使用ConnectionMultiplexer.Connect或ConnectionMultiplexer.ConnectAsync传入配置字符串或ConfigurationOptions对象来完成。配置字符串可以采用逗号分隔的一系列节点的形式,因此让我们仅通过默认端口(6379)连接到本地计算机上的实例:
using StackExchange.Redis;
...
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
// ^^^ store and re-use this!!!
需要注意的是ConnectionMultiplexer工具IDisposable,可以在不再需要处置。这是故意不显示using语句用法的原因,因为ConnectionMultiplexer要重用此对象非常少见,因此您希望简短地使用它。更复杂的情况可能涉及主/副本设置。对于此用法,只需指定组成该逻辑Redis层的所有所需节点(它将自动识别主节点):
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("server1:6379,server2:6379");
如果发现两个节点都是主节点,则可以有选择地指定一个决胜键,该键可用于解决问题,但是幸运的是这种情况很少见。
有了之后ConnectionMultiplexer,您可能需要做以下三件事:
1.访问redis数据库(请注意,在集群的情况下,单个逻辑数据库可能分布在多个节点上)
2.利用redis的发布/订阅功能
3.访问单个服务器以进行维护/监视

使用redis数据库
访问redis数据库非常简单:
IDatabase db = redis.GetDatabase();
返回的对象GetDatabase是便宜的直通对象,不需要存储。请注意,redis支持多个数据库(尽管“群集”不支持此功能);您可以在调用中指定此选项GetDatabase。此外,如果您打算使用异步API并要求Task.AsyncState具有一个值,则也可以指定以下值:
int databaseNumber = ...
object asyncState = ...
IDatabase db = redis.GetDatabase(databaseNumber, asyncState);
一旦有了IDatabase,只需使用redis API。请注意,所有方法都具有同步和异步实现。按照Microsoft的命名指南,所有异步方法都结束了...Async(...),并且是完全await可用的,等等。

最简单的操作是存储和检索值:
string value = "abcdefg";
db.StringSet("mykey", value);
...
string value = db.StringGet("mykey");
Console.WriteLine(value); // writes: "abcdefg"
请注意,String...此处的前缀表示String redis类型,尽管它们都可以存储文本数据,但它们在很大程度上与.NET String类型分开。但是,redis允许键和值都使用原始二进制数据-用法是相同的:
byte[] key = ..., value = ...;
db.StringSet(key, value);
...
byte[] value = db.StringGet(key);
的整个范围内redis的数据库命令涵盖所有redis的数据类型是可供使用。

使用redis发布订阅
Redis的另一种常见用法是作为发布/订阅消息分发工具。这也很简单,并且在连接失败的情况下,ConnectionMultiplexer它将处理重新订阅所请求频道的所有细节。
ISubscriber sub = redis.GetSubscriber();
同样,从中返回的对象GetSubscriber是便宜的直通对象,无需存储。pub / sub API没有数据库的概念,但是像以前一样,我们可以选择提供异步状态。请注意,所有订阅都是全局的:它们的作用域不限于ISubscriber实例的生存期。Redis中的发布/订阅功能使用命名为“ channels”的通道;不需要在服务器上预先定义通道(这里有趣的用法是每用户通知通道之类的东西,它是驱动Stack Overflow实时更新的一部分)。与.NET中常见的一样,订阅采用回调委托的形式,它们接受通道名称和消息:
sub.Subscribe("messages", (channel, message) => {
    Console.WriteLine((string)message);
});
注意:此处的异常由StackExchange.Redis捕获和丢弃,以防止级联失败。要处理失败,请在处理程序中使用try/catch来执行您希望的操作(有任何例外情况)。

在v2中,您可以订阅而无需直接向该Subscribe()方法提供回调,而可以使用return ChannelMessageQueue,它表示有序发布/订阅通知的消息队列。这允许使用ChannelMessageQueue.OnMessage()方法,该方法为接收消息时要执行的同步(Action<ChannelMessage>)和异步(Func<ChannelMessage, Task>)处理程序提供重载。
// Synchronous handler
sub.Subscribe("messages").OnMessage(channelMessage => {
    Console.WriteLine((string) channelMessage.Message);
});

// Asynchronous handler
sub.Subscribe("messages").OnMessage(async channelMessage => {
    await Task.Delay(1000);
    Console.WriteLine((string) channelMessage.Message);
});
您可以单独(通常是在单独的计算机上的单独过程中)发布到此频道:
sub.Publish("messages", "hello");
这将(实际上是瞬时地)写入"hello"已订阅进程的控制台。和以前一样,通道名和消息都可以是二进制的。

访问单个服务器
出于维护目的,有时有必要发出服务器特定的命令:
// 堆代码 duidaima.com
IServer server = redis.GetServer("localhost", 6379);
该GetServer方法将接受EndPoint唯一标识服务器的或名称/值对。和以前一样,从其返回的对象GetServer是便宜的直通对象,不需要存储,并且可以选择指定异步状态。请注意,可用端点集也可用:
EndPoint[] endpoints = redis.GetEndPoints();
在IServer实例中,服务器命令可用;例如:
DateTime lastSave = server.LastSave();
ClientInfo[] clients = server.ClientList();
同步和异步
StackExchange.Redis有3种主要使用机制:
同步-操作在方法返回调用者之前完成(请注意,尽管这可能会阻止调用者,但它绝对不会阻止其他线程:StackExchange.Redis中的关键思想是它积极共享并发调用者之间的连接)
异步-该操作将在以后的某个时间完成,并且立即返回Task或Task<T>,以后可以:
是.Wait()ED(阻塞当前线程,直到响应是可用的)

ContinueWith在TPL中添加了一个继续回调

被期待已久的(这是一个语言级的功能,简化了后者,同时也继续如果立即答复是已知的)
一劳永逸-您对回复真的不感兴趣,无论回复如何,乐于继续
同步用法已在上面的示例中显示。这是最简单的用法,并且不涉及TPL。
对于异步使用,主要区别在于Async方法的后缀,以及(通常)await语言功能的使用。例如:
string value = "abcdefg";
await db.StringSetAsync("mykey", value);
...
string value = await db.StringGetAsync("mykey");
Console.WriteLine(value); // writes: "abcdefg"
即弃即用用法可通过CommandFlags flags所有方法上的可选参数访问(默认为无)。在这种用法中,该方法立即返回默认值(因此,通常返回a的方法String将始终返回null,而通常返回an的方法Int64将始终返回0)。该操作将在后台继续。一个典型的用例是增加页面浏览量:

db.StringIncrement(pageKey, flags: CommandFlags.FireAndForget);
用户评论