首页 > 解决方案 > 读写MongoDB(C#驱动)时,如何判断哪些异常值得重试?

问题描述

通过查看这个官方文档,似乎 MongoDB C# 驱动程序基本上抛出了三种类型的错误:

我正在尝试使使用 MongoDB 的软件对瞬态错误更具弹性,因此我想找出哪些异常值得重试。

问题不在于实施可靠的重试策略(我通常为此使用 Polly .NET),而是理解重试何时有意义。

我认为重试类型的异常TimeoutException没有意义,因为驱动程序本身会在操作超时之前等待几秒钟(默认值为 30 秒,但您可以通过连接字符串选项更改它)。这个想法是,在超时之前等待 30 秒后重试操作可能是浪费时间。例如,如果您决定实施 3 次重试,它们之间的等待时间为 1 秒,则操作失败最多需要 93 秒(30 + 30 + 30 + 1 + 1 + 1)。这是一个巨大的时代。

如此处所述,仅在执行幂等操作时重试MongoConnectionException才是安全的。从我的角度来看,只要执行的操作是幂等的,那么总是重试这类错误是有意义的。

决定一个好的写入重试策略的难点是当你遇到类型MongoWriteExceptionMongoBulkWriteException.

关于类型的异常可能值得重试所有MongoWriteException具有. 如此所述,您可以使用对象的此属性检测重复键错误ServerErrorCategory DuplicateKeyMongoWriteException.WriteError

重试重复键错误可能没有意义,因为您会再次得到它们(这不是暂时性错误)。

我不知道如何MongoBulkWriteException安全地处理类型错误。在这种情况下,您正在向 MongoDB 插入多个文档,并且完全有可能只有其中一些文档失败,而其他文档已成功写入 MongoDB。因此,重试完全相同的批量插入操作可能会导致两次写入同一个文档(批量写入本质上不是幂等的)。我该如何处理这种情况?

你有什么建议吗?

您是否知道有关在 MongoDB 上为 C# 驱动程序重试查询的任何工作示例或参考?

标签: c#.netmongodbpolly

解决方案


重试

让我们从重试的基础开始。

在某些情况下,您请求的操作依赖于在某个时间点可能无法访问的资源。换句话说,可能存在一个时间问题,它迟早会消失。这类问题可能会导致暂时性故障。通过重试,您可以通过尝试在未来的特定时刻重做相同的操作来克服这些问题。为了能够使用此机制,应满足以下标准组:

  • 潜在引入的可观察影响是可以接受的
  • 该操作可以重做,没有任何不可逆转的副作用
  • 与承诺的可靠性相比,引入的复杂性可以忽略不计

让我们一一回顾:

  • 失败一词表示请求者也可以观察到效果,例如通过更高的延迟/降低的吞吐量等。如果“惩罚”(延迟或降低的性能)是不可接受的,那么重试不是您的选择。
  • 此要求也称为幂等操作。如果我多次使用相同的输入调用该操作,那么它将产生完全相同的结果。换句话说,操作的行为就像它只取决于它的参数,而没有其他任何东西会影响结果(就像其他对象的状态一样)。
  • 这个条件虽然是最关键的条件之一,但几乎总是被遗忘。与往常一样,存在权衡(如果我引入 Z,那么它将增加 X,但可能会减少 Y),我们应该充分意识到它们。除非它会在最意想不到的时间内给我们一些不想要的惊喜。

蒙哥异常

让我们继续讨论 MongoDb 的 C# 客户端可以抛出的异常。

过去几年我没有使用过 MongoDb,所以这些知识可能已经过时了。但我希望本质没有改变。

我还鼓励您在尝试缓解问题(例如重试)之前先引入检测逻辑(捕获和日志)。这将提供有关发生频率和数量的信息。它还将让您深入了解问题的性质。

  • MongoConnectionExceptionSocketException作为内部
    • 什么时候:
      • 有服务器选择问题
      • 连接已超时
      • 选择的服务器不可用
    • 重试:
      • 如果问题是由于网络问题,那么重试可能会很有用
      • 如果根本原因是配置错误,那么重试将无济于事
    • 日志:
  • MongoWriteException或者MongoWriteConcernException
    • 什么时候:
      • 存在持久性问题
    • 重试:
      • 这取决于,如果您执行创建操作并且服务器可以检测到重复项(DuplicateKeyError),那么最好尝试多次写入记录,然后尝试一次失败的写入尝试
      • 大多数时候更新不是幂等的,但是如果您使用某种记录版本控制,那么您可以尝试在乐观锁定期间执行重试并失败
      • 删除可以以幂等方式实现。这对于软删除和硬删除也是如此。
    • 日志:

推荐阅读