FireAndForget和异步发布行为之间的区别

Wal*_*ira 3 redis stackexchange.redis

当前,我们正在使用StackExchange.Redis,并且由于它不提供“阻止弹出消息”,因此我们正在按照文档中的建议进行操作:

db.ListLeftPush(key, newWork, flags: CommandFlags.FireAndForget);
sub.Publish(channel, "");
Run Code Online (Sandbox Code Playgroud)

与以下内容有何不同?

db.ListLeftPushAsync(key, newWork);
sub.Publish(channel, "");
Run Code Online (Sandbox Code Playgroud)

我们知道这些命令的目的,我们想知道的是,它们在内部是否有任何差异或行为有所不同的风险?(执行命令等)

Mat*_*zer 7

比较即发即调用异步操作而不等待异步操作有一个主要区别。

失火意味着您不仅不等待结果,而且不在乎结果是否有效,而异步操作一旦出错就会在其结束后引发异常。

在另一方面,当你发出火灾和忘记命令,StackExchange.Redis不会尝试在内部检索命令的结果,这是更好,如果你只是想所谓的射后不理发出命令时的行为。

如果您打开您可以检查这个差异ConnectionMultiplexer源代码,你看怎么样ExecuteAsyncImpl/ ExecuteSyncImpl方法实现:

// For example, ExecuteAsyncImpl...
if (message.IsFireAndForget)
{
  TryPushMessageToBridge(message, processor, null, ref server);
  return CompletedTask<T>.Default(null); // F+F explicitly does not get async-state
}
else
{
  var tcs = TaskSource.CreateDenyExecSync<T>(state);
  var source = ResultBox<T>.Get(tcs);
  if (!TryPushMessageToBridge(message, processor, source, ref server))
  {
    ThrowFailed(tcs, ExceptionFactory.NoConnectionAvailable(IncludeDetailInExceptions, message.Command, message, server));
  }

  return tcs.Task;
} 
Run Code Online (Sandbox Code Playgroud)

回答一些OP评论

你好 感谢您的回答。我们知道命令的目的,我们想知道的是,命令内部是否存在差异或行为方式是否不同(执行顺序等)。

由于在Redis通道上发布消息时异步操作不会完成,因此可能会发生以下情况:发布消息后,操作永远不会执行。您失去了很多控制权。

当您发送即发即命令时,它可能也不会执行,但是您知道在发布频道消息之前尝试已完成。所以,你不应该使用异步操作以实现发射后不管使用StackExchange.Redis时的模式。

您可以检查其他相关的问答:Stackexchange.redis是否触发并忘记了担保交付?