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