【发布时间】:2011-10-01 22:02:50
【问题描述】:
我知道这里也有类似的问题,但如果我需要事务或使用atomic operations 或two-phase commit,它们要么是telling me 以切换回常规RDBMS 系统。第二种解决方案似乎是最佳选择。第三个我不想遵循,因为似乎很多事情都可能出错,而且我无法在各个方面都对其进行测试。我很难重构我的项目以执行原子操作。我不知道这是否来自我有限的观点(我到目前为止只使用过 SQL 数据库),还是实际上无法做到。
我们想在我们公司对 MongoDB 进行试点测试。我们选择了一个比较简单的项目——短信网关。它允许我们的软件向蜂窝网络发送 SMS 消息,而网关则完成了这项繁琐的工作:实际上是通过不同的通信协议与提供商进行通信。网关还管理消息的计费。每个申请该服务的客户都必须购买一些积分。系统在发送消息时自动减少用户的余额,如果余额不足则拒绝访问。此外,由于我们是第三方 SMS 提供商的客户,我们也可能与他们有自己的余额。我们还必须跟踪这些。
我开始考虑如果我降低一些复杂性(外部计费、排队的 SMS 发送),如何使用 MongoDB 存储所需的数据。来自 SQL 世界,我将为用户创建一个单独的表,另一个用于 SMS 消息,以及一个用于存储有关用户余额的交易。假设我为 MongoDB 中的所有集合创建了单独的集合。
在这个简化的系统中想象一个具有以下步骤的 SMS 发送任务:
检查用户是否有足够的余额;如果信用不足,则拒绝访问
发送消息并将其存储在 SMS 集合中,其中包含详细信息和费用(在实时系统中,消息将具有
status属性,并且任务将提取它以进行传递并设置 SMS 的价格根据当前状态)通过发送消息的成本减少用户的余额
在事务集合中记录事务
现在有什么问题? MongoDB 只能对一个文档进行原子更新。在前面的流程中,可能会出现某种错误,消息被存储在数据库中,但用户的余额没有更新和/或交易没有记录。
我想出了两个想法:
为用户创建单个集合,并将余额作为字段存储,用户相关的交易和消息作为子文档存储在用户的文档中。因为我们可以原子地更新文档,这实际上解决了事务问题。缺点:如果用户发送很多短信,文档会变大,可能会达到4MB文档的限制。也许我可以在这种情况下创建历史文档,但我认为这不是一个好主意。另外,如果我将越来越多的数据推送到同一个大文档中,我也不知道系统会多快。
为用户创建一个集合,为事务创建一个。可以有两种交易:信用购买,余额为正数,消息发送,余额为负数。交易可能有一个子文件;例如,在 messages sent 中,SMS 的详细信息可以嵌入到交易中。缺点:我不存储当前的用户余额,所以每次用户尝试发送消息时我都必须计算它来判断消息是否可以通过。恐怕随着存储交易数量的增加,这种计算会变慢。
我对选择哪种方法有点困惑。还有其他解决方案吗?我在网上找不到任何关于如何解决这类问题的最佳实践。我想很多试图熟悉 NoSQL 世界的程序员一开始都面临着类似的问题。
【问题讨论】:
-
如果我错了,请原谅我,但看起来这个项目将使用 NoSQL 数据存储,无论它是否会从中受益。 NoSQL 不是作为“时尚”选择的 SQL 的替代品,而是当关系 RDBMS 的技术不适合问题空间而非关系数据存储适合时。您的很多问题都是“如果是 SQL,那么……”,这给我敲响了警钟。所有的 NoSQL 都来自于解决 SQL 无法解决的问题的需要,然后它们被普遍化以使其更易于使用,然后当然潮流开始滚动。
-
我知道这个项目并不是尝试 NoSQL 的最佳选择。但是我很害怕如果我们开始将它与其他项目一起使用(假设是图书馆馆藏管理软件,因为我们从事馆藏管理)并且突然出现某种需要交易的请求(实际上它就在那里,想象一本书从一个集合转移到另一个集合)我们需要知道如何克服这个问题。也许只是我心胸狭窄,认为交易总是有必要的。但可能有办法以某种方式克服这些问题。
-
我同意 PurplePilot,您应该选择适合解决方案的技术,而不是试图将不适合的解决方案移植到问题上。图数据库的数据建模与 RDBMS 设计是完全不同的范式,你必须忘记你所知道的一切,重新学习新的思维方式。
-
我明白我应该使用适当的工具来完成这项任务。但是对我来说——当我读到这样的答案时——NoSQL 似乎不适用于数据至关重要的任何事情。这对 Facebook 或 Twitter 来说是件好事,如果一些 cmets 迷路了,世界还在继续,但除此之外的任何东西都停业了。如果那是真的,我不明白为什么其他人关心建设例如。一个带有 MongoDB 的网上商店:kylebanker.com/blog/2010/04/30/mongodb-and-ecommerce 它甚至提到大多数事务都可以通过原子操作来克服。我正在寻找的是方法。
-
您说“NoSQL 似乎不适用于数据至关重要的任何事情”在它不好(也许)是事务性 ACID 类型事务处理的地方是不正确的。此外,NoSQL 专为分布式数据存储而设计,当您进入主从复制场景时,SQL 类型的存储可能很难实现。 NoSQL 有最终一致性的策略,并确保只使用最新的数据集而不是 ACID。
标签: mongodb transactions