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

查看:657
本文介绍了如何解决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消息发送到蜂窝网络,而网关则可以完成肮脏的工作:实际上是通过不同的通信协议与提供者进行通信.网关还管理消息的计费.每个申请该服务的客户都必须购买一些积分.发送消息时,系统自动减少用户的余额,如果余额不足,则拒绝访问.另外,由于我们是第三方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属性,任务将提取该消息以进行传递并设置SMS的价格根据其当前状态)

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.

我想出了两个主意:

  • 为用户创建一个集合,并将余额存储为字段,将与用户相关的交易和消息存储为用户文档中的子文档.因为我们可以原子地更新文档,所以这实际上解决了交易问题.缺点:如果用户发送许多SMS消息,则文档的大小可能会变大,并且可能会达到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天全站免登陆