如何解决 MongoDB 中缺少事务的问题? [英] How to work around the lack of transactions in MongoDB?

查看:61
本文介绍了如何解决 MongoDB 中缺少事务的问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这里有类似的问题,但他们要么告诉我切换回常规 RDBMS 系统,如果我需要事务或使用原子操作两阶段提交.第二种解决方案似乎是最好的选择.第三个我不想遵循,因为似乎很多事情都可能出错,我无法在每个方面都对其进行测试.我很难重构我的项目以执行原子操作.不知道是我的观点有限(我目前只接触过SQL数据库),还是真的做不到.

I know there are similar questions here but they are either telling me to switch back to regular RDBMS systems if I need transactions or use atomic operations or two-phase commit. The second solution seems the best choice. The third I don't wish to follow because it seems that many things could go wrong and I can't test it in every aspect. I'm having a hard time refactoring my project to perform atomic operations. I don't know whether this comes from my limited viewpoint (I have only worked with SQL databases so far), or whether it actually can't be done.

我们想在我们公司试点测试 MongoDB.我们选择了一个相对简单的项目——短信网关.它允许我们的软件将 SMS 消息发送到蜂窝网络,网关会做一些肮脏的工作:实际上是通过不同的通信协议与提供商进行通信.网关还管理消息的计费.每个申请该服务的客户都必须购买一些积分.系统在发送消息时自动减少用户的余额,如果余额不足则拒绝访问.此外,由于我们是第三方 SMS 提供商的客户,我们也可能与他们有自己的余额.我们也必须跟踪这些.

We would like to pilot test MongoDB at our company. We have chosen a relatively simple project - an SMS gateway. It allows our software to send SMS messages to the cellular network and the gateway does the dirty work: actually communicating with the providers via different communication protocols. The gateway also manages the billing of the messages. Every customer who applies for the service has to buy some credits. The system automatically decreases the user's balance when a message is sent and denies the access if the balance is insufficient. Also because we are customers of third party SMS providers, we may also have our own balances with them. We have to keep track of those as well.

我开始考虑如果我减少一些复杂性(外部计费、排队的 SMS 发送),我可以如何使用 MongoDB 存储所需的数据.来自 SQL 世界,我将为用户创建一个单独的表,另一个用于 SMS 消息,一个用于存储有关用户余额的交易.假设我为 MongoDB 中的所有集合创建了单独的集合.

I started thinking about how I can store the required data with MongoDB if I cut down some complexity (external billing, queued SMS sending). Coming from the SQL world, I would create a separate table for users, another one for SMS messages, and one for storing the transactions regarding the users' balance. Let's say I create separate collections for all of those in MongoDB.

想象一下在这个简化的系统中执行以下步骤的 SMS 发送任务:

Imagine an SMS sending task with the following steps in this simplified system:

  1. 检查用户是否有足够的余额;如果没有足够的信用,则拒绝访问

  1. check if the user has sufficient balance; deny access if there's not enough credit

将带有详细信息和费用的消息发送并存储在 SMS 集合中(在实时系统中,该消息将具有 status 属性,并且任务将接收它以进行传送并设置短信的价格(根据其当前状态)

send and store the message in the SMS collection with the details and cost (in the live system the message would have a status attribute and a task would pick up it for delivery and set the price of the SMS according to its current state)

通过发送消息的成本减少用户的余额

decrease the users's balance by the cost of the sent message

在交易集合中记录交易

现在有什么问题吗?MongoDB 只能对一个文档进行原子更新.在前面的流程中,可能会发生某种错误,消息会存储在数据库中,但用户的余额没有更新和/或交易没有记录.

Now what's the problem with that? MongoDB can do atomic updates only on one document. In the previous flow it could happen that some kind of error creeps in and the message gets stored in the database but the user's balance is not updated and/or the transaction is not logged.

我想出了两个想法:

  • 为用户创建单个集合,并将余额存储为字段,用户相关的交易和消息存储为用户文档中的子文档.因为我们可以原子地更新文档,这实际上解决了事务问题.缺点:如果用户发送大量短信,文件大小可能会变大,可能会达到4MB 的文件限制.也许我可以在这种情况下创建历史文档,但我认为这不是一个好主意.另外我不知道如果我将越来越多的数据推送到同一个大文档中,系统会有多快.

  • Create a single collection for the users, and store the balance as a field, user related transactions and messages as sub documents in the user's document. Because we can update documents atomically, this actually solves the transaction problem. Disadvantages: if the user sends many SMS messages, the size of the document could become large and the 4MB document limit could be reached. Maybe I can create history documents in such scenarios, but I don't think this would be a good idea. Also I don't know how fast the system would be if I push more and more data to the same big document.

为用户创建一个集合,为交易创建一个集合.可以有两种交易:信用购买,余额变化为正,消息发送,余额变化为负.交易可能有一个子文件;例如,在发送的消息中,SMS 的详细信息可以嵌入到交易中.缺点:我不存储当前用户余额,因此每次用户尝试发送消息时我都必须计算它以判断消息是否可以通过.恐怕随着存储交易数量的增加,这种计算会变得很慢.

Create one collection for users, and one for transactions. There can be two kinds of transactions: credit purchase with positive balance change and messages sent with negative balance change. Transaction may have a subdocument; for example in messages sent the details of the SMS can be embedded in the transaction. Disadvantages: I don't store the current user balance so I have to calculate it every time a user tries to send a message to tell if the message could go through or not. I'm afraid this calculation can became slow as the number of stored transactions grows.

我对选择哪种方法有点困惑.还有其他解决方案吗?我在网上找不到任何关于如何解决这些问题的最佳实践.我想很多试图熟悉 NoSQL 世界的程序员在一开始都面临着类似的问题.

I'm a little bit confused about which method to pick. Are there other solutions? I couldn't find any best practices online about how to work around these kinds of problems. I guess many programmers who are trying to become familiar with the NoSQL world are facing similar problems in the beginning.

推荐答案

从 4.0 开始,MongoDB 将具有多文档 ACID 事务.计划是首先启用副本集部署中的那些,然后是分片集群.MongoDB 中的事务感觉就像开发人员熟悉的关系数据库中的事务一样——它们是多语句的,具有相似的语义和语法(如 start_transactioncommit_transaction).重要的是,启用事务的 MongoDB 更改不会影响不需要它们的工作负载的性能.

As of 4.0, MongoDB will have multi-document ACID transactions. The plan is to enable those in replica set deployments first, followed by the sharded clusters. Transactions in MongoDB will feel just like transactions developers are familiar with from relational databases - they'll be multi-statement, with similar semantics and syntax (like start_transaction and commit_transaction). Importantly, the changes to MongoDB that enable transactions do not impact performance for workloads that do not require them.

有关详细信息,请参阅此处.

For more details see here.

拥有分布式事务并不意味着您应该像在表格关系数据库中那样对数据进行建模.拥抱文档模型的强大功能并遵循良好且推荐的实践数据建模.

Having distributed transactions, doesn't mean that you should model your data like in tabular relational databases. Embrace the power of the document model and follow the good and recommended practices of data modeling.

这篇关于如何解决 MongoDB 中缺少事务的问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆