我正在开发一个具有以下特征的实时应用程序:
换句话说(和 tl;dr),客户端可以容忍延迟,但他们需要大量可信赖的写入吞吐量 - 比“一次写入是一次磁盘操作”更高的吞吐量。
我正在设想一个数据库,它的实现方式如下:接受(理论上受文件描述符数量限制)数量的 TCP 连接,在内存中缓冲这些写入,尽可能频繁地将它们的批处理记录到磁盘(以及对自动递增索引的更新),并且仅在相关的磁盘写入操作完成时才响应这些 TCP 连接。或者它可以像延迟写入数据库一样简单,它发布一条已完成磁盘写入的消息(客户端等待延迟响应,然后等待写入消息报告成功)。
我认为具有如此高的延迟容忍度,这并不过分要求。而且我想其他人也遇到过这个问题,例如金融公司,它们无法承受丢失数据,但可以承受延迟对任何客户的响应。
是否有任何久经考验的数据库解决方案(如 Postgres、CouchDB/Couchbase 或 MongoDB)支持这样的操作模式?
最佳答案
PostgreSQL 应该非常适合这种工作负载;您指定的几乎所有内容都在其正常功能集中。 Pg 符合 ACID,支持组提交以减少同步开销,写入器不会阻塞读取器,并且它使用操作系统进行缓存,因此它自然倾向于仅将热数据集保留在内存中。
"Clients are willing to wait on the order of seconds for confirmation - long enough for multiple disk seeks and writes to happen"
如果考虑 PostgreSQL,您的应用程序非常适合大型 commit_delay
,这将极大地帮助提高写入吞吐量。您不能使用 synchronous_commit = off
因为您需要在回复之前确认提交,但您可以将提交排队等待几秒钟以节省同步成本。
如果您将 Pg 用于这样的工作,您将需要调整检查点以确保检查点不会停止 I/O。确保 bgwriter 积极地写出脏缓冲区。确保 autovaccum 经常运行 - 您没有从表中删除,但索引仍需要维护,表统计信息也需要维护。
如果您期望 大量 数据并且您的查询通常包含时间元素,请考虑 partitioning the table第 1 年(例如)1 个月的 block ,将 12 个月以上的所有内容合并到按年份分区的表中。 Pg 只有有限的内置分区(它使用继承和约束排除一起被破解)所以你必须使用触发器手动/脚本来完成,但它可以完成这项工作。
见:
commit_delay
configuration option https://stackoverflow.com/questions/12832816/
相关文章:
php - MongoDB/Doctrine : can't nest $or in $and
node.js - 从 Mongoose 模型中找到的 native 驱动程序不返回光标
node.js - 我应该将图像存储在 MongoDB 中还是本地文件系统中(通过 Node.js)
ruby-on-rails - 获取字段最大值的对象[Mongoid]
mongodb - MongoDB 的 fsync 是做什么用的?
mongodb - 设置 MongoDB 数据库配额 (SIZE)
java - MongoDB : how to index the keys of a Map