node.js - 在 MongoDB 中保持并发读取操作的一致性
问题描述
我在 Node.js 中有一个 API,说它/create/appointment
执行 2 个操作
第 1 步:检查数据库中的活动约会。
第 2 步:如果不存在,则创建一个约会。
我有 3 个收藏
doctors
patients
appointments
约会集合有 3 个主要领域
doctor_id
:MongoDb ObjectID
patient_id
:MongoDB ObjectID
is_active
:布尔值
STEP 1 包含一个 DB 读取操作。STEP 2 包含一个 DB 写操作。当 API 同时触发多次时,第二个循环的 STEP 1 在第一个循环的 STEP 2 完成之前执行。由于第一个周期的 STEP 2 没有完成,所以第二个周期的 STEP 1 不会返回在第一个周期中创建的活动约会条目。
我不能在以下位置使用复合唯一索引:
{doctor_id, patient_id}
,因为appointment
集合可以包含历史数据。
{doctor_id, patient_id, is_active}
,则appointment
集合只能包含一个非活动条目。
执行:
// All functions below return promise object.
doctorManager
.getDoctor(doctor_id)
.then(doctor => {
// throw error if doctor does not exist
return patientManager.getPatient(patient_id);
})
.then(patient => {
// throw error if patient does not exist
return getActiveAppointment(doctor_id, patient_id)
})
.then(activeAppointment => {
// throw error if active appointment exist
return appointmentManager.createAppointment(doctor_id, patient_id)
})
.then(() => {
// return API response
})
.catch(error => {
// handel error
});
有没有办法appointment
在进行任何类型的操作时锁定集合,或者任何其他更好的解决方案。我不能对我的数据库进行分片,也不能设置复制。
解决方案
这是使用异步等待功能时的外观。它不是问题解决方案,而只是正确处理问题的示例。
doctor = await doctorManager.getDoctor(doctor_id);
patient = await patientManager.getPatient(patient_id);
appointment = await doAppointmentExists(doctor_id, patient_id);
if(isEmpty(appointment)) {
create appointment = await appointmentManager.createAppointment(doctor_id, patient_id)
} else {
throw new Error("Duplicate Appointment");
}
推荐阅读
- php - 前/后输入显示结果
- react-admin - 单个页面上有两个不同的 List 组件
- stm32 - STM32 SAI:了解FIFO
- bash - 为什么当通过管道传输到其他命令时 docker 伪 tty 会破坏输出?
- dart - 如何在文本下添加按钮
- excel - ALV 网格仅加载前 64 行,如何更改默认加载
- google-maps - Clojurescript - 无法限制到 Google Places Autocomplete API 中的城市
- machine-learning - 如何训练用于提取值的对话流可能不会被空间分割
- azure - 此版本的 SQL Server 不支持“CREATE CREDENTIAL”
- java - 在java流中使用return语句