我正在研究一个包含一些重要数据的项目.这意味着如果灯或服务器发生故障,我们不能丢失任何一个.我们正在使用MongoDB作为数据库.如果没有插入一个元素,我想确保在插入和回滚整个批处理之后我的数据在数据库中.我知道Mongo背后的哲学是我们不需要交易但是如何确保我的数据在插入后真的安全存储而不是发送到某个"黑洞".
我应该搜索一下吗?
我应该使用一些特定的mongoDB命令吗?
我是否应该使用分片,即使一台服务器足以满足
速度,如果灯光
熄灭,它也不能保证任何东西?
什么是最好的解决方案?
您最好的选择是使用写问题 - 这些允许您告诉MongoDB一个数据的重要性.最快的Write Concern也是最不安全的 - 在下一次预定的刷新之前,数据不会刷新到磁盘.最安全的将确认数据已在多台机器上写入磁盘,然后再返回.
您正在寻找的写入问题是FSYNC_SAFE(至少从Java驱动程序的角度来看它是调用的)或REPLICAS_SAFE,它确认您的数据已被复制.
请记住,MongoDB没有传统意义上的事务 - 您必须手动滚动回滚,因为您无法告诉Mongo数据库为您执行此操作.
您需要做的另一件事是使用相对较新的--journal
选项(使用Write Ahead Log),或使用副本集在多台计算机之间共享数据,以便在崩溃/断电时最大限度地提高数据完整性.
在处理特别大的数据集时,分片不是一种防止硬件故障作为共享负载的方法 - 分片不应该与副本集混淆,副本集是一种将数据写入多个机器上的多个磁盘的方法.
因此,如果您的数据足够有价值,您肯定应该使用副本集,甚至可能选择其他数据中心/可用区/机架/等中的从站,以提供您所需的弹性.
有/将会(不记得是否已经实现)这是一种指定副本集中各个节点的优先级的方法,这样如果主节点关闭,则选择的新主节点是同一数据中的一个中心,如果这样的机器可用(即阻止国家另一边的奴隶成为主人,除非它真的是唯一的其他选择).
我收到了Google群组中一个名为GVP的人的非常好的回答.我会引用它(基本上它加起来Rich的答案):
如果没有插入一个元素,我想确保在插入和回滚整个批处理之后我的数据在数据库中.
这是一个复杂的主题,您需要在此处考虑几个权衡因素.
我应该使用分片吗?
分片用于缩放写入.为了数据安全,您希望查看副本集.
我应该使用一些特定的mongoDB命令吗?
首先要考虑的是"安全"模式或"getLastError()",如Andreas所示.如果发出"安全"写入,则表示数据库已收到插入并应用了写入.但是,MongoDB每60秒只刷新一次磁盘,因此服务器可能会在没有磁盘数据的情况下发生故障.
要考虑的第二件事是"日记"(v1.8 +).打开日记功能后,每隔100毫秒将数据刷新到日志.所以你在失败之前有一个较小的时间窗口.驱动程序有一个"fsync"选项(检查该名称)比"安全"更进一步,它等待确认数据已刷新到磁盘(即日志文件).但是,这仅涵盖一台服务器.如果服务器上的硬盘刚刚死掉会怎么样?那么你需要第二份副本.
要考虑的第三件事是复制.在返回之前,驱动程序支持"W"参数,该参数表示"将此数据复制到N个节点".如果写入在某个超时之前没有到达"N"节点,则写入失败(抛出异常).但是,您必须根据副本集中的节点数正确配置"W".同样,因为硬盘驱动器可能会失败,即使使用日记功能,您也会想要查看复制.然后是跨数据中心的复制,这太长了,无法进入这里.最后要考虑的是你需要"回滚".根据我的理解,MongoDB没有这种"回滚"能力.如果您正在进行批量插入,那么您将获得的最佳结果表明哪些元素失败了.
以下是此驱动程序上PHP驱动程序的链接:http://it.php.net/manual/en/mongocollection.batchinsert.php 您必须检查有关复制和W参数的详细信息.我相信这里也适用同样的限制.