Mongo 作为循环缓冲区

Posted

技术标签:

【中文标题】Mongo 作为循环缓冲区【英文标题】:Mongo as circular buffer 【发布时间】:2021-09-01 01:51:38 【问题描述】:

我正在尝试找出一种将 Mongo 用作循环缓冲区的方法。 目前使用 SQL Lite,但性能方面不适合我们的情况。 需要满足的规范是: 集合必须每 x 秒清空一次。 当满足 y 个文档的限制时,集合必须自行清空。

通过 Mongo 文档,封顶集合以及更改事件似乎是一种方法。

https://docs.mongodb.com/manual/core/capped-collections/

https://docs.mongodb.com/manual/reference/change-events/

在文档中指出:“上限集合的工作方式类似于循环缓冲区”

但我不确定如何:

    每隔 x 秒清空一次集合。 Mongo TTL 功能不可行,因为上限集合不支持 TTL。其他替代方案? 检索任何“已删除的文档”。 更换变更事件的操作类型似乎是一种方法。其他替代方案?

有没有人尝试过使用 ? 上面的-Capped Collections/Change Events-是实现它的方法吗?

感谢您的回复。

【问题讨论】:

您的数据大小是多少? “x 秒”的范围是多少?上限集合限制文档总数,但是您要求删除所有个文档。一个普通的db.collection.drop() 可能会更快。在 MongoDB 中,如果新集合不存在,则会自动创建它。 当你实际要求删除它们时,你为什么喜欢检索它们? 您能否详细说明您对“循环缓冲区”的期望。这只是一种存储数据的方式。这就是上限集合的实现方式,它被用于副本集中的 oplog。因此,如果有人尝试使用它来回答您的问题 - 是的,有些人尝试过。 @WernfriedDomscheit 我想检索文档,因为在移除文档后需要进行进一步处理。 “x 秒”的当前值为 10 秒,但它是可配置的。数据量非常大 - 每月接近 50 万份文档,它是生产数据,我不知道确切的值。 @AlexBlex 我对循环缓冲区的期望是存储特定数量的文档(限制),能够检索在达到此限制时自动删除的所有文档。不过,正如我现在意识到的那样,Mongo 实际上会一个一个地删除文档.. 并不是为了清空集合而将它们全部一起删除.. 【参考方案1】:

来自https://en.wikipedia.org/wiki/Circular_buffer:

循环缓冲区 [...] 是一种使用单个固定大小缓冲区的数据结构,就好像它是端到端连接的一样。

恐怕您引用的“上限集合的工作方式类似于循环缓冲区”正是使用了循环缓冲区的这种定义。

上限集合受大小和/或文档数量的限制。旧文档不是由计时器删除,而是由新文档删除。想想看,就像新文档覆盖旧文档一样。

不幸的是,此功能无法从集合https://docs.mongodb.com/manual/core/capped-collections/#document-deletion 中删除文档。既不是通过 TTL 也不是明确的。并且由于没有正式删除,所以变更流中没有删除事件。

简单地说,如果您需要检索从缓冲区中逐出的文档,您需要自己实现它。

TTL 索引可能对您有用,但它是有时间限制的,而不是大小限制的。它将向更改流发出删除事件,但需要考虑以下三点:

您需要保持 changestream 客户端运行,以确保捕获所有事件。 TTL 索引过程是有代价的。 Mongodb 每一分钟都会运行 TTL Monitor 线程来删除过期的文档。它消耗资源。没有 sqlite 那么多,但系统性能可能会下降,并且如果文档正忙于其他一些操作,则可能不会在指定的时间后完全删除。

建议您自己控制和选择/删除文档。我知道您已经有一些使用 sqlite 的实现,因此只需将其调整为使用 mongodb。

db.collection.find().sort(_id:-1).limit(1)

将返回最旧的文档。它使用默认索引并且应该表现良好。

【讨论】:

非常感谢,确实,我所处的场景并不完全在循环缓冲区范围内。花了一些时间试图弄清楚 Mongo 上的触发器是否是一个选项,但不是直接的——所以毕竟不是一个选项。我倾向于相信按照您的建议“手动”处理选择/删除是可行的方法。

以上是关于Mongo 作为循环缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

操作系统缓冲区管理(单缓冲双缓冲循环缓冲以及缓冲池)

操作系统缓冲区管理(单缓冲双缓冲循环缓冲以及缓冲池)

操作系统缓冲区管理(单缓冲双缓冲循环缓冲以及缓冲池)

操作系统缓冲区管理(单缓冲双缓冲循环缓冲以及缓冲池)

如何将文件缓冲区转换为 <img> 标签 src?

将包含循环缓冲区的类添加到 Vector