【发布时间】:2021-02-28 17:03:09
【问题描述】:
通过查看this official documentation,似乎MongoDB C#驱动程序抛出的错误基本上分为三种类型:
- 驱动程序无法正确选择或连接到服务器以发出查询时引发的错误。这些错误导致
TimeoutException - 驱动程序已成功选择要对其运行查询的服务器,但在执行查询时服务器关闭时引发的错误。这些错误表现为
MongoConnectionException - 写入操作期间引发的错误。这些错误会导致
MongoWriteException或MongoBulkWriteException,具体取决于正在执行的写入操作的类型。
我正在尝试使使用 MongoDB 的软件对暂时性错误更具弹性,因此我想找出哪些异常值得重试。
问题不在于实施可靠的重试策略(我通常使用Polly .NET for that),而是了解重试何时有意义。
我认为重试TimeoutException 类型的异常没有意义,因为驱动程序本身会在操作超时之前等待几秒钟(默认为 30 秒,但您可以通过连接字符串更改它选项)。这个想法是,在超时之前等待 30 秒后重试操作可能是浪费时间。例如,如果您决定实施 3 次重试,它们之间的等待时间为 1 秒,则操作失败最多需要 93 秒(30 + 30 + 30 + 1 + 1 + 1)。这是一个巨大的时代。
As documented here 重试MongoConnectionException 只有在进行幂等操作时才是安全的。从我的角度来看,只要执行的操作是幂等的,那么总是重试这类错误是有意义的。
决定一个好的写入重试策略的难点是当您遇到MongoWriteException 或MongoBulkWriteException 类型的异常时。
关于MongoWriteException 类型的异常可能值得重试所有具有ServerErrorCategory 除了 DuplicateKey 的异常。作为documented here,您可以使用MongoWriteException.WriteError 对象的this property 检测重复键错误。
重试重复键错误可能没有意义,因为您会再次得到它们(这不是暂时性错误)。
我不知道如何安全地处理MongoBulkWriteException 类型的错误。在这种情况下,您正在向 MongoDB 插入多个文档,并且完全有可能只有一些文档失败,而其他文档已成功写入 MongoDB。因此重试完全相同的批量插入操作可能会导致两次写入同一个文档(批量写入本质上不是幂等的)。我该如何处理这种情况?
你有什么建议吗?
您知道任何关于在 MongoDB 上为 C# 驱动程序重试查询的工作示例或参考吗?
【问题讨论】:
-
无!!!第 1 项:只需增加连接超时。 2)如果服务器在插入过程中出现故障,您将在数据库中获得重复的条目 3)同样,如果您写入多行,您最终会出现重复。
-
@jdweng 我不确定从不重试操作是最佳选择。例如,为什么在读取期间引发 MongoConnectionException 时我不应该重试失败的读取操作?同样,为什么我不应该在写入操作期间由于服务器临时缓慢而引发 MongoWriteException 时重试 InsertOne 操作?
-
真正的问题是,当您遇到错误并最终在数据库中出现重复条目时,您是否想要“重试”?您应该始终报告错误。
-
@jdweng 你是否建议即使从 mongodb 读取也跳过重试(在这种情况下,根本不可能破坏数据)?
-
为什么阅读会出错?您想在重试之前调查错误吗?你认为重试真的有用吗?当 TCP 层已经有重试方法时,我不喜欢重试。重试成功的机会非常小。