在 AWS DocumentDB(MongoDB 兼容版)中,没有像 MySQL 中的 SELECT ... FOR UPDATE
语法来直接加读锁。AWS DocumentDB 主要依赖 MongoDB 的读写操作和事务支持来管理并发访问和数据一致性。以下是在 AWS DocumentDB 中处理并发访问和数据一致性的一些方法:
1. 事务支持
AWS DocumentDB 支持 MongoDB 4.0 兼容的事务操作。通过使用事务,可以确保在一组操作中实现原子性、一致性、隔离性和持久性(ACID 特性)。在事务中执行的操作会在提交之前进行锁定,确保其他事务不会对相同的文档进行修改。
示例代码:
import com.mongodb.client.MongoClients;
import com.mongodb.client.ClientSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class ProductService {@Autowiredprivate MongoTemplate mongoTemplate;@Transactionalpublic void purchaseProduct(String productId, int quantity) {ClientSession session = mongoTemplate.getSession();try {session.startTransaction();Product product = mongoTemplate.findById(productId, Product.class);if (product != null && product.getQuantity() >= quantity) {// Deduct from inventoryproduct.setQuantity(product.getQuantity() - quantity);mongoTemplate.save(product);// Record transactionTransaction transaction = new Transaction(productId, quantity);mongoTemplate.save(transaction);}session.commitTransaction();} catch (Exception e) {session.abortTransaction();throw e;}}
}
2. Pessimistic Locking
尽管 AWS DocumentDB 不直接支持 SELECT ... FOR UPDATE
类型的锁定语法,但可以通过编程实现悲观锁定(Pessimistic Locking)。在读取文档时,通过使用 ClientSession
和事务来实现锁定效果,确保其他事务不会在你处理完毕之前修改文档。
示例代码:
import com.mongodb.client.MongoClients;
import com.mongodb.client.ClientSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;@Service
public class ProductService {@Autowiredprivate MongoTemplate mongoTemplate;public void purchaseProductWithLock(String productId, int quantity) {ClientSession session = mongoTemplate.getSession();session.startTransaction();try {// Lock document for updateProduct product = mongoTemplate.findById(productId, Product.class);if (product != null && product.getQuantity() >= quantity) {// Deduct from inventoryproduct.setQuantity(product.getQuantity() - quantity);mongoTemplate.save(product);// Record transactionTransaction transaction = new Transaction(productId, quantity);mongoTemplate.save(transaction);}session.commitTransaction();} catch (Exception e) {session.abortTransaction();throw e;}}
}
3. 使用乐观锁定 (Optimistic Locking)
另一种方式是通过实现乐观锁定来确保并发修改的一致性。在 AWS DocumentDB 中,可以通过在文档中添加版本号(例如 _version
字段),在更新操作时比较版本号,如果版本号不匹配则拒绝更新,从而避免并发冲突。
示例代码:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.data.mongodb.core.FindAndModifyOptions;@Service
public class ProductService {@Autowiredprivate MongoTemplate mongoTemplate;public boolean purchaseProduct(String productId, int quantity) {Query query = new Query(Criteria.where("_id").is(productId).and("quantity").gte(quantity));Product product = mongoTemplate.findAndModify(query,new Update().inc("quantity", -quantity),new FindAndModifyOptions().returnNew(true),Product.class);return product != null;}
}
总结
虽然 AWS DocumentDB 不支持类似 MySQL 的 SELECT ... FOR UPDATE
的直接读锁操作,但可以通过事务、悲观锁定和乐观锁定等方式来管理并发访问和数据一致性。选择合适的并发控制方式取决于你的应用需求和 AWS DocumentDB 的支持特性。