Php 如何让MongoDB在确认写入后将实际数据返回给其他读卡器?

Php 如何让MongoDB在确认写入后将实际数据返回给其他读卡器?,php,multithreading,mongodb,consistency,Php,Multithreading,Mongodb,Consistency,我试图在MongoDB中模拟某种“事务”。 我正在锁定关键代码部分(使用memcache),从MongoDB读取文档,对其进行一些更改,然后将其写回并解锁该部分。 然而,如果并发运行,这些操作很少会像预期的那样工作。 确认(w=1)后,写入另一个线程仍可以读取文档的以前版本。在高负载(10+并发请求)下,这种情况大约发生1/1000次,但破坏了整个想法 我尝试使用fsync选项,但它使写入速度太慢,无法使用(这些操作应该经常运行)。日记选项(j=1)无法解决此问题。 有没有办法让其他线程在从某个

我试图在MongoDB中模拟某种“事务”。 我正在锁定关键代码部分(使用memcache),从MongoDB读取文档,对其进行一些更改,然后将其写回并解锁该部分。 然而,如果并发运行,这些操作很少会像预期的那样工作。 确认(w=1)后,写入另一个线程仍可以读取文档的以前版本。在高负载(10+并发请求)下,这种情况大约发生1/1000次,但破坏了整个想法

我尝试使用fsync选项,但它使写入速度太慢,无法使用(这些操作应该经常运行)。日记选项(j=1)无法解决此问题。 有没有办法让其他线程在从某个线程确认写入后读取文档的一致版本

下面是示例代码(我将其更改为simple counter,问题仍然可以重现):

预期输出是从1到10000的序列号。 但如果没有fsync选项,有时我们会得到双倍:

[Tue Oct 01 00:53:53 2013] [error] [client 127.0.0.1] PHP Notice:  344 in /var/www/test.php on line 49
[Tue Oct 01 00:53:53 2013] [error] [client 127.0.0.1] PHP Notice:  344 in /var/www/test.php on line 49
现在我只看到一种可能的解决方案:在document和findAndModify中使用“version”变量对DB执行操作,以确保只有在操作之间版本没有更改时,文档才会更新。
但是代码看起来很难看,所以我想知道是否有其他方法可以解决这个问题。

我发现您的代码中有一些问题,可以解释:

但如果没有fsync选项,有时我们会得到双倍:

[Tue Oct 01 00:53:53 2013] [error] [client 127.0.0.1] PHP Notice:  344 in /var/www/test.php on line 49
[Tue Oct 01 00:53:53 2013] [error] [client 127.0.0.1] PHP Notice:  344 in /var/www/test.php on line 49
您就是其中之一,使用不推荐的
Mongo
类:

$m = new Mongo($connstr);
此操作的默认写入关注点是套接字确认

通常情况下,这将通过以下措施来应对:

$mongoopts = array("w" => 1);
但是
w
Mongo
不兼容,而是与
MongoClient
兼容。
Mongo
的选项是
safe

这意味着您实际上从未从MongoDB获得成功操作的确认,而只是从套接字获得确认

尝试修复代码,看看问题是否会再次出现


不过,此链接可能会有所帮助:从MongoDB获取原子的、无竞争条件的递增密钥。

似乎只需将Mongo替换为MongoClient,问题就真的解决了。我是多么盲目,以至于在最新版本的mongo驱动程序中没有注意到这种变化。多谢各位。我将进一步测试它,并将您的答案标记为解决方案。
$mongoopts = array("w" => 1);