Grails 2.1(HibernateとSpring)を使用して、BidServiceの次の「ナイーブ」実装で入札システムを実装しようとしましたが、レイズ条件を防ぐことができず、異なる同時ユーザーからの「重複」入札が発生します。
いくつかの情報:-BidServiceはデフォルトでトランザクションです-アイテムと入札モデルは「バージョン:false」(悲観的ロック)を使用します
class BidService{
BidResult processBid(BidRequest bidRequest, Item item) throws BidException {
// 1. Validation
validateBid(bidRequest, item) // -> throws BidException if bidRequest do not comply with bidding rules (price too low, invalid user, ...)
// 2. Proces Bid (we have some complex rules to process the bids too, but at the end we only place the bid
Bid bid = placeBid(bidRequest, item)
return bid
}
Bid placeBid(BidRequest bidRequest, Item item){
// 1. Place Bid
Bid bid = new Bid(bidRequest) // create a bid with the bidRequest values
bid.save(flush: true, failOnError: true)
// 2. Update Item price
item.price = bid.value
item.save(flush: true, failOnError: true)
return bid
}
}
ただし、http: //grails.org/doc/latest/guide/services.htmlに記載されているように、 9.2スコープサービス:デフォルトでは、サービスメソッドへのアクセスは同期されないため、これらのメソッドの同時実行を妨げるものはありません。実際、サービスはシングルトンであり、同時に使用される可能性があるため、サービスに状態を格納する場合は十分に注意する必要があります。または、簡単な(そしてより良い)道を進み、サービスに状態を保存しないでください。
processBid()メソッド全体で「同期」を使用することを考えましたが、それはかなり失礼に聞こえ、活性の問題やデッドロックを引き起こす可能性があります。一方、入札を非同期で処理すると、オークションの勝ち負けに関するユーザーフィードバックを直接送信できなくなります。
この場合に使用するアドバイスやベストプラクティスはありますか?
PS:私はすでにgrails MLについて質問しましたが、それはかなり広いJava同時実行性の質問です。