我知道这里有类似的问题,但是如果我需要事务或者使用 原子操作或者 两阶段提交,它们可以是 告诉我切换回常规的 RDBMS 系统。第二种解决方案似乎是最佳选择。第三个我不希望遵循,因为它似乎很多事情可能会出错,我不能测试它的每一个方面。我很难重构我的项目来执行原子操作。我不知道这是出于我有限的观点(到目前为止我只处理过 SQL 数据库) ,还是实际上不可能做到。
我们想在我们公司试点测试 MongoDB。我们选择了一个相对简单的项目-短信网关。它允许我们的软件向蜂窝网络发送短信息,而网关则完成这些繁琐的工作: 实际上通过不同的通信协议与提供商进行通信。网关还管理消息的计费。每个申请这项服务的顾客都必须购买一些积分。当发送消息时,系统会自动减少用户的余额,并在余额不足时拒绝访问。此外,因为我们是第三方短信服务提供商的客户,我们也可能有我们自己的余额与他们。我们还要记录这些。
我开始考虑如何用 MongoDB 存储所需的数据,如果我降低一些复杂性(外部计费、排队发送短信)。来自 SQL 世界的我将为用户创建一个单独的表,另一个用于 SMS 消息,还有一个用于存储关于用户余额的事务。假设我为 MongoDB 中的所有这些集合创建了单独的集合。
设想一个短信发送任务,在这个简化的系统中有以下步骤:
检查用户是否有足够的余额; 如果没有足够的信用,则拒绝访问
在 SMS 集合中发送和存储带有详细信息和成本的消息(在活动系统中,消息将具有 status
属性,任务将接收它并根据其当前状态设置 SMS 的价格)
通过发送消息的成本来减少用户的余额
在事务集合中记录事务
这有什么问题吗?MongoDB 只能对一个文档进行原子更新。在前面的流程中,可能会发生某种错误,消息被存储在数据库中,但是用户的余额没有更新,并且/或者事务没有被记录。
我有两个主意:
为用户创建单个集合,并将余额存储为字段、用户相关事务和消息作为子文档存储在用户文档中。因为我们可以自动更新文档,这实际上解决了事务问题。缺点: 如果用户发送许多 SMS 消息,文档的大小可能会变大,并且可能达到4MB 的文档限制。也许我可以在这种情况下创建历史文档,但我不认为这是一个好主意。我也不知道如果我把越来越多的数据推到同一个大文档中,系统会有多快。
为用户创建一个集合,为事务创建一个集合。可以有两种交易: 正余额变化的 信用购买和负余额变化的 信息已发送。事务可能有一个子文档; 例如,在 信息已发送中,SMS 的详细信息可以嵌入到事务中。缺点: 我不存储当前的用户余额,所以每次用户尝试发送消息时,我都必须计算余额,以告诉用户该消息是否可以通过。我担心随着存储事务数量的增长,这种计算可能会变慢。
我有点不知道该选哪种方法。还有别的解决办法吗?我在网上找不到任何关于如何解决这类问题的最佳实践。我猜想,许多试图熟悉 NoSQL 世界的程序员一开始都面临着类似的问题。