mongo 的 api 都是回调的方式,我每次从库里查出符合条件的记录,然后在回调函数中将这几条记录 update 掉状态,让他们不会再其他请求中被查找出来,相当于被消费掉了。
虽然还没遇到脏读的情况,但是我心里觉得是有隐患的。因为查找和更新不是一个事务里,而 node 处理事件的方式又是可以并发的,所以我担心并发的情况下,会造成 mongodb 脏读,多次消费同一个记录。
有没有好的解决方法?比如类似于 Critical Section 的方案,让竞争资源的代码不可以同时运行?
1
jukka 2016-03-25 15:49:13 +08:00 1
mongo 自己是没有事物的。
你要用类似 async 来控制并发,让你这些访问数据库的操作顺序执行。 |
2
whahuzhihao OP @jukka async 确实可以控制并发,但是我用的 mongojs 的 api 对于库的操作,还是异步的。。
所以即使控制了并发请求,让其串行处理,还是不能解决问题。 |
3
lynnworld 2016-03-25 16:26:21 +08:00 1
用 findAndModify .设个状态字段, undo,doing,done,
|
4
tabris17 2016-03-25 16:29:09 +08:00 1
那只能模拟 MVVC 了
|
5
whahuzhihao OP @lynnworld 其实我也想用这个 findAndModify ……
但是因为要随机取,所以用的是 aggregate + $sample 管道。貌似 aggregate 里没有同时修改的方法。 |
6
incompatible 2016-03-25 16:46:56 +08:00 via iPhone
1. 换 mysql ,用悲观锁
2. 用 CAS 机制自己做乐观锁 |
7
fengkuok 2016-03-25 16:48:34 +08:00
@whahuzhihao async 不是解决办法,集群不照样有问题
|
8
MiguelValentine 2016-03-25 16:58:04 +08:00
用集群,由 master 做锁调度
|
9
BOYPT 2016-03-25 23:09:16 +08:00
@whahuzhihao 不需要同时修改吧, findAndModify 时候如果已经被消费了就不会产生任何效果。
|
10
magicdawn 2016-03-26 13:47:53 +08:00
|
11
fds 2016-03-26 14:29:19 +08:00
查找到数据后, update 时带上查找条件,比如
collection.update({_id:123,proc:{$exists:false}},{$set:{proc:1}}) 然后看返回的 modified 数量是不是 1 ,不是就不要处理。 不过一般还得考虑处理超时后别的进程接手的情况呢。 |