一.情景介绍: 1.有一个接口提供update数据的功能,但这个接口在update时,需要做一些额外的操作,即需要通过先find后update的方式来修改数据,这样在并发的情况下如何保证数据的一致性? 2.使用mongoose 二.相关伪代码如下:
const user = await user.find({"id":id}).exec();
//要对user的属性做一些修改
user.xxx = xxxxxx;
await user.save();
当这个接口被并发调用时,就会出现值覆盖的问题,比如第一个请求是把user.age + 1,第二个请求同第一个请求,但实际效果user.age可能只加了1,因为第二个请求取到的user.age时,第一个请求还没有执行完save操作,导致第二个请求读到了脏数据,所以后面的值会覆盖前面的值. 三.局限性 1.中间的这部分修改操作是必须的,且无法转换成mongo原生支持的操作符(指$inc等),通常见于利用原属性值计算新值,比如user.age = (new Date().getTime() - user.birthday).必须在内存中计算属性值. 2.这个接口是并发调用,不能很好的实现队列的机制. 3.mongodb不支持行级锁,且没有暴露出来,所以通过mongodb的锁机制去搞这个感觉也没什么思路 四.方法一 1.把最后那个user.save()改成 user.findOneAndUpdate({"id":id,"updated_at":user.updated_at},{update属性}) ,返回找不到对应的document时,可以重新走一遍这个流程,如果返回数据了,证明修改成功,这个依赖的是每次update操作,都会更新其updated_at字段,变相的用程序实现乐观锁,这样做会不会陷入死循环状态?这样会不会有其它问题? 2.希望各位大神有其它的思路和方法指教一下.