我正在编写一个Node应用程序,我正在考虑扩展。据我了解,横向扩展是扩展应用程序以处理更多并发请求的更简单方法之一。我的工作副本目前在后端使用MongoDb。
因此我的问题是:我的数据结构类似于需要严格维护订单的链表。我(想象)担心的是,当通过多个节点实例存在数据库竞争条件时,链表的分辨率可能不正确。
举个例子:假设服务器有这个列表a-> b。实例1带有对象c,实例2带有对象d。可能存在竞争条件,其中两个实例都读取a-> b并且决定将它们自己的对象附加到列表。然后,实例1将其插入设想为a-> b-> c,而实例2认为当数据库实际保持a-> b>> c-> d时它是a-> b-> d
一般来说,这听起来像是乐观锁定的工作,但是,据我所知,MongoDB或Redis(我正在考虑的其他数据库)都不会以SQL方式进行事务处理。
因此,我认为解决方案是以下之一:
使用flags在MongoDB中实现我自己的事务。客户端对lock变量执行findAndModify,如果成功,则执行操作。如果不成功,客户端将在特定超时后重试。
使用Redis事务和pubsub来实现相同的效果。我还不确定如何做到这一点,但听起来似乎有道理。
实施某种智能负载平衡。如果多个客户端在同一项上运行,请将它们路由到同一个实例。由于JS是单线程的,因此问题将得到解决。不幸的是,我没有找到一个直截了当的解决方案。
我确信存在一种更好,更优雅的方式来实现上述目标,我很乐意听到任何解决方案或建议。谢谢!
答案 0 :(得分:0)
你想在mongodb上使用findAndModify命令来保证在返回新修改的doc时进行原子修改。由于更改是串行的,原子实例1将具有a-> b-> c,而实例2将具有a-> b>> c-> d
干杯
答案 1 :(得分:0)
如果你要做的就是在列表中添加新元素,你可以使用Redis列表并在你添加的每个值中包含时间。该列表可能在redis上未排序,但在检索时应该可以快速排序。
答案 2 :(得分:0)
如果我理解正确,并且列表存储为单个文档,您可能正在查看行版本控制。因此,在处理版本的文档中添加一个属性,在更新时,增加(或更改)版本并使其成为条件更新:
// update(condition,value)
更新({version:whateverYouReceivedWhenYouDidFind},newValue)
希望它有所帮助。 格斯