# 7、高并发抢红包示例(非事务版本)

'use strict';
module.exports = {
  /**
   * 高并发抢红包示例
   * @url db_api/sys/concurrent 前端调用的url参数地址
   */
  main: async (event) => {
    let { data = {}, userInfo, util, filterResponse, originalParam } = event;
    let { customUtil, config, pubFun, vk, db, _ } = util;
    let { uid } = data;
    let res = { code: 0, msg: "" };
    // 业务逻辑开始-----------------------------------------------------------
    let money = 1; // 每次抢红包的金额
  
    res.num = await vk.baseDao.update({
      dbName:"vk-test",         // 红包测试表
      whereJson:{
        _id:_id,                // 红包id,
        money: _.gte(money),    // 判断当前红包金额必须>=要扣除的金额
        receive_uid: _.nin([uid]), // 只有我没领过才可以领
      },
      dataJson:{
        money: _.inc(money*-1),  // 减当前红包金额
        receive_uid: _.push(uid), // 将当前登录用户的id写入该红包,防止重复领取
      }
    });
    // 利用update + where 形成数据库乐观锁达到控制高并发下不会扣成负数。
    if(res.num <= 0){
      return { code: -1, msg: "未抢到红包,您已抢过或红包已抢完!" };
    }
    // 给用户加余额
    await vk.baseDao.update({
      dbName:"vk-test-balance",  // 用户余额测试表
      whereJson:{
        user_id : uid
      },
      dataJson:{
        balance: _.inc(money)    // 加抢到的当前红包金额
      }
    });
    res.msg = `恭喜,抢到了${money}元红包`;

    // 业务逻辑结束-----------------------------------------------------------
    return res;
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47