在多个前端应用程序使用同一个 MongoDB 数据库时,可能会出现写入竞争的情况。这种情况下,多个应用程序同时尝试写入同一个文档,可能会导致数据冲突或丢失。为了避免这种情况,我们需要采取一些预防措施。
使用唯一的文档ID
在 MongoDB 中,每个文档都有一个唯一的_id属性,用于标识该文档。如果多个应用程序同时尝试写入一个文档,MongoDB 将根据其_id检查谁先完成写入。
为了确保_id的唯一性,我们可以使用MongoDB自动生成的ObjectId类型。同时,我们也可以使用自己的唯一标识符来作为_id,比如使用UUID。
const { v4: uuidv4 } = require('uuid'); const myDocument = { _id: uuidv4(), name: "John Doe", age: 35 }
使用乐观锁定
当两个应用程序同时修改同一个文档时,我们需要一种方法来确保数据的一致性。MongoDB 提供了一种乐观锁定的方式,可以帮助我们解决这个问题。
乐观锁定是一种乐观的方法,它假设在写操作发生之前,不会有任何其他应用程序可以修改文档。使用乐观锁定,我们可以在更新文档时,检查文档的版本号是否与预期的版本号一致。如果版本号一致,则继续更新操作。如果不一致,则表示有其他应用程序已经修改了文档,更新操作将被取消。
-- -------------------- ---- ------- ----- ---------- - ------------------------------ ----- ----------- - - ---- ------------------------------------- -------- -- ----- ------ -- ----- ----------- - - ---- ------------------------------------- -------- -- ----- ------ -- ----- ------ - ----- --------------------- - ---- ---------------- -------- ------------------- -- - ----- - ----- ---------------- -- ----- - -------- - - - -- -- -------------------- --- -- - ----- --- --------------- ------- ----------- -
使用悲观锁定
与乐观锁定相反,悲观锁定假设在写操作发生时,可能会发生其他应用程序同时修改文档的情况。因此,使用悲观锁定,我们可以通过在写操作发生之前,将文档锁定来避免写入竞争的发生。
MongoDB 支持基于行的悲观锁定,当文档被锁定时,其他应用程序将无法修改该文档。但是,请注意,使用悲观锁定可能会影响性能,并且不能保证所有应用程序都能在足够的时间内获得锁。
const collection = db.collection('myCollection'); const docToModify = { _id: ObjectId("5f9d2a9446dc4d5944694f77"), name: "John" }; await collection.findOneAndUpdate( { _id: docToModify._id }, { $set: { name: "Jane" } }, { returnOriginal: false, writeConcern: { w: "majority" }, maxTimeMS: 5000, $isolated: true } );
结论
在使用多个前端应用程序访问同一个 MongoDB 数据库时,写入竞争可能会导致数据冲突或丢失。为了避免这种情况,我们可以使用唯一的文档ID,乐观锁定或悲观锁定来保证数据的一致性。在选择哪种方法时,请考虑您的具体需求以及性能和可用性的权衡。
参考资料:
- MongoDB Concurrency: Avoiding Conflicts While Writing Data
- MongoDB Concurrency: Distributed Locking with Transactions
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67394bde317fbffedf1613d7