Grails - MongoDB Gorm插件 - 竞争条件 - 悲观锁定解决方案?信号?

时间:2015-04-08 22:31:12

标签: mongodb grails

我目前有一些Grails应用程序使用单个MongoDB副本集来处理某些共享信息。最近,一场比赛条件可再现地发生在:

  1. 用户在启动后端流程的前端执行了操作
  2. 后端流程的一部分涉及在两个域对象上保存新状态
  3. 后端进程向外部服务器生成消息,通知事件
  4. 外部服务器在收到消息后生成了有关相关域对象的更多详细信息的请求
  5. 我的应用程序回复了一个资源的陈旧数据和另一个资源的准确(最新)数据。
  6. 重试时,外部服务器生成了相同的请求,并收到了两种资源的预期(准确)数据。
  7. 没有使用flush调用save:true,但是第一个资源save在第二个资源保存之前发生了两行,而其间的行是对第二个资源的更改。冲洗可能会解决这个问题,但我想实施一个解决方案,以保证不再出现具体情况。

    我对解决方案的一些天真/第一推力实施涉及到& amp;发布信号量方法:

    public synchronized boolean releaseSemaphore(Thing thing){
        if(thing.semaphore==true){
            thing.semaphore=false
            if(thing.save(failOnError:true, flush:true)){
                return true
            }
            else{
                log.warn "releasing thing semaphore, thing: "+thing.id+", failed on thing.save()"
                return false
            }
        }
        else{
            log.error "releaseThingSemaphore called with thing: "+thing.id+" when semaphore not held."
            return false
        }
    }
    
    public synchronized getThingWithSemaphore(String thingId){
        def thing = Thing.get(thingId)
        if(thing){
            if(thing.semaphore==false){
                thing.semaphore=true
                if(thing.save(failOnError:true, flush:true)){
                    return [thing, true]
                }
                else{
                    log.debug "Failed to get lock on thing: "+thingId
                    return [null, false]
                }
            }
            else{
                log.warn "Thing: "+thingId+" was locked when getThingWithSemaphore was called"
                return [null, false]
            }
        }
        else{
            return [null, false]
        }
    }
    

    GORM API的Thing.lock(thingId){(http://grails.github.io/grails-doc/3.0.x/guide/GORM.html#locking).lock()}是否会完成我在上面的实现中尝试实现的相同保证(在写入之前获取信号量时)阅读重大行动)?

    http://www.anyware.co.uk/2005/2012/11/12/the-false-optimism-of-gorm-and-hibernate/(虽然我意识到它的旧)声称.lock()方法用于在事务外部静默失败,而不是实际锁定任何东西。这仍然是这样吗?

    (我也担心MongoDB对事务的一般支持级别,以及这对GORM .lock()调用的影响)

    如果我要在需要跨应用程序实例锁定的不同数据中心部署相同应用程序的多个实例(或交叉不同的应用程序共享相同的MongoDB复制集数据源),我是否能够利用GORM API启用跨应用程序文档锁定?

0 个答案:

没有答案