StackExchange.Redis官方文档(六)【事件,发布订阅,服务器命令】

事件

ConnectionMultiplexer 类型公开了多个事件,可以用来了解正在发生的事件。这是非常有用的特别是在记录日志的时候:

  • ConfigurationChanged 当 ConnectionMultiplexer 里面的连接配置被更改后触发

  • ConfigurationChangedBroadcast 通过发布/订阅功能接受到一个重新配置的消息的时候;这通常是由于使用 IServer.MakeMaster 更改了一个节点的复制配置,也可以选择广播某个请求给所有的客户。

  • ConnectionFailed 当连接失败的时候;注意:对于该连接你不会收到 ConnectionFailed 的通知,直到连接重新建立。

  • ConnectionRestored 当重新建立连接到之前失败的那个节点的时候

  • ErrorMessage 当用户发起的请求的时候,Redis服务器给出一个错误消息的响应;这是除了常规异常/故障之外,立即报告给调用方的。

  • HashSlotMoved 当 “Redis集群” 表示 hash-slot 已经被迁移到节点之间的时候,注意:请求通常会被自动重新路由,所以用户不会在这里要求做任何指定的事情。

  • InternalError 当Redis类库内部执行发生了某种不可预期的失败的时候;这主要是为了用于调试,大多数用户应该不需要这个事件。

注意:StackExchange.Redis 实现的 pub/sub 工作原理类似于事件,Subscribe / SubscribeAsync 接受一个 Action

发布/订阅 消息顺序

当使用 pub/sub API的时候,你需要做一个决定:那就是对于来自同一个连接的消息是应该按顺序处理还是应该并行处理。

按顺序处理意味着你不需要关心线程安全,并且保持了事件的顺序;消息会以完全相同的顺序接收处理(通过队列),因此,这意味着消息能够被相互延迟。

另外一种选择是并发处理。使用并发处理 不能保证 工作处理的有序性,并且你的代码要对并行消息完全负责确保它不会破坏内部状态;使得处理速度更快并且扩展性伸缩性更好。如果消息是互不相干的,那么选择这种方式处理是特别好的。

为了安全,默认是 有序处理;但是,强烈建议你尽可能的使用并发处理。示例如下:

multiplexer.PreserveAsyncOrder = false;

这不是一个配置选项的原因是:这样做是否合理,这完全取决于你的订阅消息的代码。


KEYS,SCAN,FLUSHDB 等等,这些命令在哪里?

一些常见的重复性的问题是:

好像没有看到如:Key(…) 或者 Scan(…) 方法?我该怎么才能查询哪些key是在数据库中的?

或者

好像也没有 Flush(…) 方法?我该怎样才能移除掉所有在数据库中的key?

The key word here, oddly enough, is the last one: database. 这句话真不知道该怎么翻译

奇怪的是这里的关键字的最后一个是:数据库。????

由于StackExchange.Redis 服务的目标场景(或者宗旨)是集群服务,重要的是要知道命令所面向的数据库(可分布在多个节点的逻辑数据库),还有命令所面向的服务器。下面这些命令都是面向单个服务器的:

  • KEYS / SCAN
  • FLUSHDB / FLUSHALL
  • RANDOMKEY
  • CLIENT
  • CLUSTER
  • CONFIG / INFO / TIME
  • SLAVEOF
  • SAVE / BGSAVE / LASTSAVE
  • SCRIPT ( 不要与 EVAL / EVALSHA 混淆 )
  • SHUTDOWN
  • SLOWLOG
  • PUBSUB ( 不要与 PUBLISH / SUBSCRIBE 等命令混淆 )
  • 一些 DEBUG 操作

(我可能遗忘了多个命令没有列举) 其中大多数会显得很明显,但是前三行就不那么明显:

  • KEYS / SCAN 不是在所有的逻辑数据库中,而是仅列出当前服务器的key;
  • FLUSHDB / FLUSHALL 不是在所有的逻辑数据库中,而是仅移除当前数据库中的key;
  • RANDOMKEY 不是在所有的逻辑数据库中,而是仅在当前数据库中选出一个key;

事实上,StackExchange.Redis 在使用 IDatabase API的时候,欺骗了 RANDOMKEY 命令,实际上它是以一个随机的方式选择了一台目标服务器。但这对其它的来说是不可能的。

那么我该怎么使用它们?

让我们先从一个服务器开始,而不是从一个数据库开始。

// 取得目标服务器
var server = conn.GetServer(someServer);

// 在索引为0的数据库中展示出所有的key,这个key的名字必须匹配 *foo*
foreach(var key in server.Keys(pattern: "*foo*")) {
    Console.WriteLine(key);
}

// 从索引为0的数据库中清除所有的key
server.FlushDatabase();

注意:这个和 IDatabase API是不同的(在调用 GetDatabase() 方法的时候目标数据库已被选择),可以给这些方法传一个可选参数来选择数据库,默认是0。

值得特别注意的是 Keys(…) 方法:该方法没有一个对应的 *Async 异步方法。原因是在后台运作,由系统确定出一个最合适的方法来使用(KEYS vs SCAN, 基于服务器的版本),并且如果可能的话将会使用 SCAN 方法来处理你回传的 IEnumerable 参数,内部会对该参数分页处理:所以你绝不会看到游标操作的详细实现。如果 SCAN 是不可用的,那么将会使用 KEYS,这个可能会在服务器导致阻塞。无论哪种方式,SCANKEYS 都需要扫描整个键空间,所以应该避免在生产服务器上使用;或者至少值针对从服务器。

那么我需要记住我所连接的服务器吗? 那简直糟透了!

不完全是这样的,你可以使用 coon.GetEndPoints() 方法列出端点(要么是所有已知的,要么是在原始配置中指定的:这未必是同一个事情),还可以迭代 GetServer() 方法去找到你想要的服务器(例如:选择一个从服务器)。

你可能感兴趣的:(服务器,发布,订阅,命令)