Nag*_*gyI 136 transactions mongodb
我知道这里有类似的问题,但如果我需要事务或使用原子操作或两阶段提交,他们要么告诉我切换回常规RDBMS系统.第二种解决方案似乎是最佳选择.第三个我不想遵循,因为似乎很多事情都可能出错,我无法在各个方面进行测试.我很难重构我的项目来执行原子操作.我不知道这是否来自我有限的观点(到目前为止我只使用过SQL数据库),或者它是否真的无法完成.
我们想在我们公司试用MongoDB.我们选择了一个相对简单的项目 - 短信网关.它允许我们的软件向蜂窝网络发送SMS消息,并且网关执行肮脏的工作:实际上通过不同的通信协议与提供商进行通信.网关还管理消息的计费.申请服务的每个客户都必须购买一些积分.发送消息时,系统会自动降低用户的余额,如果余额不足,则拒绝访问.另外,由于我们是第三方SMS提供商的客户,我们也可能拥有自己的余额.我们也必须跟踪这些.
如果我减少了一些复杂性(外部计费,排队短信发送),我开始考虑如何用MongoDB存储所需的数据.来自SQL世界,我将为用户创建一个单独的表,另一个用于SMS消息,另一个用于存储有关用户余额的事务.假设我为MongoDB中的所有人创建了单独的集合.
想象一下SMS发送任务,在这个简化的系统中执行以下步骤:
检查用户是否有足够的余额; 如果没有足够的信用,请拒绝访问
使用详细信息和成本在SMS集合中发送和存储消息(在实时系统中,消息具有status属性,任务将接收它以进行传递,并根据SMS的当前状态设置SMS的价格)
通过发送消息的成本减少用户的余额
在事务集合中记录事务
那现在有什么问题?MongoDB只能在一个文档上进行原子更新.在之前的流程中,可能会发生某种错误,并且消息会存储在数据库中,但用户的余额未更新和/或未记录事务.
我提出了两个想法:
为用户创建单个集合,并将余额作为字段,用户相关事务和消息存储为用户文档中的子文档.因为我们可以原子地更新文档,这实际上解决了事务问题.缺点:如果用户发送许多SMS消息,文档的大小可能会变大,并且可能达到4MB的文档限制.也许我可以在这种情况下创建历史文档,但我认为这不是一个好主意.另外,我不知道如果我将越来越多的数据推送到同一个大文档,系统会有多快.
为用户创建一个集合,为事务创建一个集合.可以有两种交易:具有正余额变化的信用购买和具有负余额变化的消息.交易可能有一个子文件; 例如,在发送的消息中,SMS的详细信息可以嵌入到事务中.缺点:我没有存储当前的用户余额,因此每次用户尝试发送消息时都要计算它,以判断消息是否可以通过.我担心随着存储事务数量的增加,这种计算会变慢.
我对选择哪种方法有点困惑.还有其他解决方案吗?我在网上找不到关于如何解决这些问题的最佳实践.我想许多试图熟悉NoSQL世界的程序员一开始就面临着类似的问题.
xam*_*mir 82
事务支持ACID属性,但是虽然没有事务MongoDB,但我们确实有原子操作.好吧,原子操作意味着当您处理单个文档时,该工作将在其他人看到该文档之前完成.他们会看到我们所做的所有改变,或者没有改变.使用原子操作,您通常可以完成使用关系数据库中的事务完成的相同操作.原因是,在关系数据库中,我们需要跨多个表进行更改.通常需要加入的表格,因此我们希望一次完成所有这些操作.要做到这一点,因为有多个表,我们必须开始一个事务并执行所有这些更新,然后结束事务.但是MongoDB,我们将要嵌入数据,因为我们将在文档中预先加入它们,而这些文档是具有层次结构的丰富文档.我们经常可以完成同样的事情.例如,在博客示例中,如果我们想确保以原子方式更新博客文章,我们可以这样做,因为我们可以立即更新整个博客文章.如果它是一堆关系表,我们可能必须打开一个事务,以便我们可以更新帖子集合和评论集合.
那么,我们可以采取哪些方法MongoDB来克服缺乏交易?
Update,findAndModify,$addToSet(更新内)$push(更新内)操作在单个文档中以原子方式操作.
Gri*_*nik 19
从4.0开始,MongoDB将拥有多文档ACID事务.计划是首先启用副本集部署中的那些,然后是分片群集.MongoDB中的事务就像开发人员熟悉的关系数据库中的事务一样 - 它们将是多语句,具有类似的语义和语法(如start_transaction和commit_transaction).重要的是,对启用事务的MongoDB所做的更改不会影响不需要它们的工作负载的性能.
欲了解更多详情,请参见这里.
小智 11
提出要点:如果必须使用事务完整性,则不要使用MongoDB,而只使用支持事务的系统中的组件.在组件之上构建一些东西是非常困难的,以便为非ACID兼容组件提供类似ACID的功能.根据个人用例,以某种方式将操作分为事务性和非事务性操作可能是有意义的...
那现在有什么问题?MongoDB只能在一个文档上进行原子更新.在之前的流程中,可能会发生某种错误,并且消息会存储在数据库中,但用户的余额不会减少和/或事务未被记录.
这不是一个真正的问题.您提到的错误是逻辑(错误)或IO错误(网络,磁盘故障).这种错误会使无事务和事务存储处于不一致状态.例如,如果它已经发送了短信但是在发生存储消息错误时 - 它无法回滚短信发送,这意味着它不会被记录,用户余额也不会减少等.
这里真正的问题是用户可以利用竞争条件并发送比他的余额更多的消息.这也适用于RDBMS,除非您使用平衡字段锁定进行内部事务的SMS发送(这将是一个很大的瓶颈).因为MongoDB的一个可能的解决方案是findAndModify首先使用减少余额并检查它,如果它是否定的,则不允许发送和退还金额(原子增量).如果是肯定的,继续发送,如果它未能退还金额.还可以维护余额历史记录集合以帮助修复/验证余额字段.
该项目很简单,但您必须支持付款交易,这使整个事情变得困难.因此,例如,具有数百个集合(论坛,聊天,广告等)的复杂门户系统在某些方面更简单,因为如果您丢失了论坛或聊天条目,则没有人真正关心.另一方面,如果您失去了一个严重问题的支付交易.
所以,如果你真的想要MongoDB的试点项目,那么选择一个在这方面很简单的项目.
由于正当理由,MongoDB中缺少事务.这是使MongoDB更快的事情之一.
在你的情况下,如果交易是必须的,mongo似乎不太适合.
可能是RDMBS + MongoDB,但这会增加复杂性并使管理和支持应用程序变得更加困难.
这可能是我发现的关于为mongodb实现交易功能的最佳博客.
同步标志:最好只从主文档复制数据
工作队列:非常通用,解决了95%的案例.无论如何,大多数系统都需要至少有一个作业队列!
两阶段提交:此技术确保每个实体始终具有达到一致状态所需的所有信息
日志调节:最强大的技术,非常适合金融系统
版本控制:提供隔离并支持复杂的结构
阅读本文以获取更多信息:https: //dzone.com/articles/how-implement-robust-and
| 归档时间: |
|
| 查看次数: |
72542 次 |
| 最近记录: |