【问题标题】:(CursorNotFound) Cursor not found (namespace: 'dbName.collection', id: 885805460243113719)(CursorNotFound) 游标未找到 (命名空间: 'dbName.collection', id: 885805460243113719)
【发布时间】:2022-01-27 12:40:40
【问题描述】:

以下是从提供集合、过滤查询、排序查询和限制数量的数据库中获取结果的代码。

func DBFetch(collection *mongo.Collection, filter interface{}, sort interface{}, limit int64) ([]bson.M, error) {
    findOptions := options.Find()
    findOptions.SetLimit(limit)
    findOptions.SetSort(sort)
    cursor, err := collection.Find(context.Background(), filter, findOptions)
    var result []bson.M
    if err != nil {
        logger.Client().Error(err.Error())
        sentry.CaptureException(err)
        cursor.Close(context.Background())
        return nil, err
    }
    if err = cursor.All(context.Background(), &result); err != nil {
        logger.Client().Error(err.Error())
        sentry.CaptureMessage(err.Error())
        return nil, err
    }
    return result, nil
}
  1. 我正在使用 mongo-go 驱动程序版本 1.8.2
  2. mongodb community version 4.4.7 sharded mongo with 2 shards
  3. 每个分片在 k8 中有 30 个 CPU,245Gb 内存有 1 个副本
  4. API 为 200 rpm
  5. Api 从 mongo 获取数据并对其进行格式化并提供服务
  6. 我们在小学读和写。
  7. 大约每小时发生大量写入。
  8. 以毫秒为单位获取超时(大约 10ms-20ms)

【问题讨论】:

标签: mongodb go


【解决方案1】:

正如@R2D2在评论中指出的那样,当超过默认超时(10分钟)并且没有go请求下一组数据时,不会发生游标超时错误。

您可以采取多种变通方法来减轻出现此错误的情况。

第一个选项是使用以下选项为您的查找查询设置批量大小。通过这样做,您是在指示 MongoDB 以指定的块发送数据,而不是发送更多数据。请注意,这通常会增加 MongoDB 和 Go 服务器之间的往返时间。

findOptions := options.Find()
findOptions.SetBatchSize(10)  // <- Batch size is set to `10`

cursor, err := collection.Find(context.Background(), filter, findOptions)

此外,您可以设置NoCursorTimeout 选项,这将使您的 MongoDB 查找查询结果光标指针保持活动状态,除非您手动关闭它。此选项是一把双刃剑,因为一旦不再需要该光标,您必须手动关闭该光标,否则该光标将在内存中保留很长时间。

findOptions := options.Find()
findOptions.SetNoCursorTimeout(true)  // <- Applies no cursor timeout option

cursor, err := collection.Find(context.Background(), filter, findOptions)

// VERY IMPORTANT
_ = cursor.Close(context.Background())  // <- Don't forget to close the cursor

结合以上两个选项,下面就是你的完整代码了。

func DBFetch(collection *mongo.Collection, filter interface{}, sort interface{}, limit int64) ([]bson.M, error) {
    findOptions := options.Find()
    findOptions.SetLimit(limit)
    findOptions.SetSort(sort)
    findOptions.SetBatchSize(10)  // <- Batch size is set to `10`
    findOptions.SetNoCursorTimeout(true)  // <- Applies no cursor timeout option
    cursor, err := collection.Find(context.Background(), filter, findOptions)
    var result []bson.M
    if err != nil {
        //logger.Client().Error(err.Error())
        //sentry.CaptureException(err)
        _ = cursor.Close(context.Background())
        return nil, err
    }
    if err = cursor.All(context.Background(), &result); err != nil {
        //logger.Client().Error(err.Error())
        //sentry.CaptureMessage(err.Error())
        return nil, err
    }
    // VERY IMPORTANT
    _ = cursor.Close(context.Background())  // <- Don't forget to close the cursor
    return result, nil
}

【讨论】:

  • @hhharsh36 我在 8 - 10 毫秒内有光标超时,并添加到问题中。
  • @SachinJoshi 我从未听说过 10 毫秒的光标超时。查询和 MongoDB 连接在 Mongo Shell 上是否正常工作?
猜你喜欢
  • 2020-04-10
  • 2015-02-16
  • 2019-11-20
  • 1970-01-01
  • 1970-01-01
  • 2019-03-03
  • 1970-01-01
  • 2012-03-31
相关资源
最近更新 更多