素材牛VIP会员
nodejs单进程产生的数据库连接多线程并发问题探讨
 坐***来  分类:Node.js  人气:719  回帖:5  发布于6年前 收藏

举例,假设有100个请求node服务器,每个请求会执行一次查询,修改数据库操作。假设10个请求按顺序被node接收处理 等待各自判定库存查询数据库io操作,但是库存只有5个,问题来了,这时候10个查询都判定库存还有,然后继续下面的下单操作。当100个请求甚至更多时,问题会被更加放大 又不能同步加锁,哪位朋友有比较合理的思路 不吝赐教~

 标签:mysqlnode.js

讨论这个帖子(5)垃圾回帖将一律封号处理……

Lv5 码农
bb***82 Linux系统工程师 6年前#1

站内搜“抢购”
https://segmentfault.com/sear...

极端情况为“秒杀”
https://segmentfault.com/sear...

Lv4 码徒
sk***e4 页面重构设计 6年前#2

题主有找到解决方案么

Lv7 码师
雪***狐 职业无 6年前#3

事务 + 条件更新 从设计上避免了超卖。

Lv4 码徒
大***咒 JAVA开发工程师 6年前#4

你这种情况应该加上事务

----- 更新下答案 -----

查询和实际数据不一致的问题是无法避免的,我的理解题主的意思应该是在更新callback之前有其他用户购买成功的情况会导致购买失败的问题,因此可以通过加锁解决,其实如果异步操作都使用 promise 的情况下,可以通过Promise 模拟顺序调用来实现类似java方法加锁的特性

通过 decorator 对返回 promise 的方法实现类似java synchronized 关键字的同步调用


// decorator

let p
function sync(target, name) {
  const method = target[name]
  target[name] = function(...args) {
    if (p) {
      p = p.then(() => method.apply(target, args))
    } else {
      p = method.apply(target, args)
    }
    return p
  }
}

class Model {
  constructor () {
    // super()
    this._cardCount = 5
    sync(this, 'buyOneCard')
  }
  // @sync // 注解需要编译,暂时手动调用下
  buyOneCard (user) {
    console.log('buyonecard', this._cardCount)
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        this._cardCount = --this._cardCount
    
        this._cardCount < 0
          ? reject(this._cardCount)  
          : resolve(this._cardCount)
      }, 100)
    })
  }
}

const m = new Model()
for(let i=0;i<10;i++) m.buyOneCard().then(c => console.log(c))

chrome 下运行通过。。

----- 再更新 ----

github 上已经有类似工具
https://github.com/sindresorh...

Lv5 码农
牛***满 产品经理 6年前#5

谢谢楼上两位,首先我描述的场景是正常商品销售,如果是抢购倒好办 直接用redis队列可以解决,但是商品种类多的时候 这种方式不可取。

  回复楼上,这里面事务是肯定有的,但是事务并不能解决这种并发超卖的情景。

 最后,如果这是用java可以很方便用队列或同步锁解决,但是node并不适用以上场景,redis也只能解决抢购,谁有还有合适的方案 ,期待中~
 文明上网,理性发言!   😉 阿里云幸运券,戳我领取