【问题标题】:Is it possible to do transaction processing using node.js and a noSQL db?是否可以使用 node.js 和 noSQL 数据库进行事务处理?
【发布时间】:2012-07-24 03:57:36
【问题描述】:

我说的不是真钱交易

我正在做的项目是一个玩家互相交换东西的游戏。这基本上是一个交易过程,玩家 A 给玩家 B 10 块钱来换取 30 头奶牛,你懂的。

但由于它是交互式的,并且同时有很多玩家,在一个类似聊天室的环境中,所有交易都是随机的,我想知道是否可以用node.js 做这样的事情,但我发现了一些问题。

我来自数据库背景,处理事务和rollbackcommit 的性质对于维护数据库的健康状态是必要的。但是,如果我们谈论的是 node.js 加上 mongoDB(或任何其他 noSQL DB),那肯定是一种完全不同的心态,但我只是不明白它如何处理只有两个各方应该参与而不诉诸某种形式的锁定,但这肯定不是node 的目的。

我还没有找到任何东西,但这并不让我感到惊讶,因为node.js 太新了。

更新 我知道交易的机制——尤其是银行风格的交易,但这不是一回事。我可能没有说清楚,但问题是玩家 B 正在向买家社区出售东西。

这意味着尽管玩家 A 在客户端发起了购买指令,但也有可能大约在同一时间,玩家 C D 或 E 也点击购买同一头牛。

现在在正常事务中,至少第一个获得记录级表锁的人至少会阻止其他方在该时间点继续进行。

但是节点的使用性质,特别是它的速度、并发处理和用于显示实时更新数据库的用途意味着我可以很容易地想象最慢的人(我们说的是毫秒)获胜。

例如,玩家 A 在玩家 C 的同时发起购买。玩家 A 交易完成,Groats 被支付给玩家 B,而奶牛在数据库中被分配给玩家 A。一毫秒后,Cow 被分配给玩家 C。

我希望这能更好地解释这个问题。

【问题讨论】:

    标签: node.js transactions nosql


    【解决方案1】:

    我正在为 node.js 开发一个名为 Waterline 的 oss 应用程序级事务数据库。

    我们从全面的 CRUD 静音开始,但很快意识到这非常困难。最好把它留给数据库。但有时你不想——因为你希望能够切换数据库并保持你的代码不可知。因此,我们将其简化为下一个最简单的部分——命名交易。

    因此,没有内置回滚支持(您现在仍然需要自己做),但至少 Waterline 可以防止您进行并发访问。

    在你的例子中(假设你在 express/connect/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});
                   });
    
                });
             });
          });
    
       });
    }
    

    希望对您有所帮助。我欢迎您的反馈(也许还有提交?)

    【讨论】:

    • 这可能很有趣,尽管我们已经采取了另一条轨道来推进项目,因为自从发布问题以来,关于这个主题的知识非常少。
    • 有道理——好吧,如果你想看看的话,我昨晚完成了 waterline 的第一个版本:github.com/mikermcneil/waterline 它设置为使用dirtydb,一个内存数据库。我的下一步将是创建一个 mongodb 适配器,然后是 mySQL(mySQL 适配器将使用 mySQL 的内置事务)
    • 我知道现在是 2018 年,但是如果事务应该进行两次或多次更新并且在第一次失败后进行一些更新,该怎么办?
    【解决方案2】:

    要使用文档数据库进行银行式交易,通常使用交易日志模式。在这种模式中,您会将每个 transaction 编写为它自己的文档。您不维护与每个帐户余额相对应的文档。相反,您在查询时卷起交易文档,以提供当前余额。

    这是一个适用于 Couchbase map reduce 的示例:http://guide.couchdb.org/draft/recipes.html

    【讨论】:

      【解决方案3】:

      这与 Node.JS 无关。 Node.JS 只连接到数据库,事务由数据库本身完成(除非您想在 Node.JS 中手动实现事务,这可能有点困难 - 但对于任何用任何语言编写的 Web 服务器都是一样的)。

      您可以轻松地将 MySQL 与支持事务的 Node.JS 一起使用(例如)。所以你要问的问题是:我可以用 MongoDB 做交易吗?答案是:不是,是的。

      不,因为 MongoDB 不支持开箱即用的事务。

      是的,因为您可以使用一些技巧来模拟交易。参见例如this article

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-25
        • 1970-01-01
        • 2013-09-01
        • 1970-01-01
        • 2021-08-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多