2012-07-25 26 views
4

我不是在談論真金白銀交易是否有可能使用node.js和noSQL db進行事務處理?

我工作的這個項目是一個遊戲,玩家之間相互交易的東西。這基本上是一個交易過程,玩家A給了玩家B 10粒去交換30頭奶牛,你明白了。

但是因爲它是互動的,並且有很多玩家同時在類似聊天室的環境中進行隨機交易,我想知道是否有可能通過node.js來做這樣的事情,但我看到了問題。

我來自數據庫背景,其中處理交易和rollbackcommit的性質是必要的,以維護數據庫的健康狀態。但如果我們談論node.jsmongoDB(或任何其他的noSQL DB),這肯定是一個完全不同的思路,但我不明白它是如何處理交易的,因爲只有兩方應該參與而不訴諸某種形式的鎖定,但肯定不是什麼node

我還沒有找到任何東西,但這並不令我感到意外,因爲node.js太新穎了。

UPDATE我意識到交易的機制 - 特別是銀行風格的交易,但這不是同一回事。我可能沒有說清楚,但問題是,玩家B正在向買家羣體推銷某些東西。

這意味着雖然玩家A在客戶端發起購買指令,但也有可能大約在同一時間玩家C D或E也點擊購買相同的牛。

現在在正常的交易中,預計至少第一個獲得記錄級別表的人至少阻止其他方在該時間點繼續進行。

然而,節點的使用性質,特別是其速度,併發處理和顯示實時更新數據庫的使用意味着我可以輕易想象,最慢的人(我們正在說毫秒)獲勝。

例如玩家A在與玩家C同時發起購買。玩家交易完成並且將銀幣支付給玩家B,並且將牛分配給數據庫上的玩家A.一毫秒後牛被分配給玩家C.

我希望能更好地解釋這個問題。

回答

4

這與Node.JS無關。 Node.JS只連接到數據庫,事務由數據庫本身完成(除非你想在Node.JS中手動實現事務,這可能有點困難 - 但任何語言編寫的任何Web服務器都是如此)。

你可以很容易地使用MySQL(例如)支持事務的Node.JS。所以你問的問題是:我可以使用MongoDB進行交易嗎?答案是:不,是。

不,因爲MongoDB不支持開箱即用的交易。

是的,因爲您可以使用一些技巧來模擬交易。例如參見this article

1

要使用文檔數據庫進行銀行業務式交易,通常使用事務日誌模式。在這種模式下,您可以將每個交易寫爲自己的憑證。您不保留與每個賬戶餘額相對應的文件。相反,您在查詢時上傳交易文件,以提供當前餘額。

下面是適用於Couchbase地圖縮小的例子:http://guide.couchdb.org/draft/recipes.html

2

我工作的OSS應用程序級的事務數據庫上的node.js稱爲Waterline

我們從全增長的CRUD開始,但很快就意識到這很難。最好把它留給數據庫。但有時你不想 - 因爲你希望能夠切換數據庫並保持你的代碼不可知。那麼我們簡化到下一個最簡單的命名交易。

因此,沒有內置回滾支持(您現在仍然必須自己做),但至少Waterline會阻止您同時訪問。

在您的例子(假設你在快遞是/連接/ Sails)它可能看起來像:

function buyCow (req,res) { 
    Cow.find(req.param('cowId'),function (err,cow) { 
     if (err) return req.send(500,err); 

     Cow.transaction('buy_cow',function (err, unlock) { 
     if (err) { 
      // Notice how I unlock before each exit point? REALLY important. 
      // (would love to hear thoughts on an easier way to do this) 
      unlock(); 
      return res.send(500,err); 
     } 

     User.find(req.session.userId,function (err,user) { 
      // If there's not enough cash, send an error 
      if (user.money - cow.price < 0) { 
       unlock(); 
       return res.send(500,'Not enough cash!'); 
      } 

      // Update the user's bank account 
      User.update(user.id,{ 
       money: user.money - cow.price 
      }, function (err,user) { 
       if (err) { unlock(); return res.send(500,err); } 

       Cow.update(cow.id, {owner: user.id}, function (err, cow) { 
        if (err) { unlock(); return res.send(500,err); } 

        // Success! 
        unlock(); 
        res.json({success: true}); 
       }); 

      }); 
     }); 
     }); 

    }); 
} 

希望有所幫助。我歡迎您的反饋意見(也許是提交?)

+0

這可能很有意思,但我們已經採取了另一種方式來推進項目,因爲發佈該問題後對此主題知之甚少。 – T9b 2012-12-30 13:46:17

+0

有道理 - 那麼,如果你想查看它,我昨晚完成了第一個水線的發佈:http://github.com/mikermcneil/waterline 它設置爲使用dirtydb,一個內存數據庫。我的下一步是創建一個mongodb適配器,然後創建mySQL(mySQL適配器將使用mySQL的內置事務) – mikermcneil 2012-12-30 23:46:25

相關問題