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 作为循环缓冲区的主要内容,如果未能解决你的问题,请参考以下文章