分布式锁初探--数据库行锁

前言

关于抢红包服务一次数据库行锁控制并发,在此记录一下,或许里面还存在很多不足。

场景

抢红包应用:一个红包分为100个子红包,可以有N个人来抢这个红包,这时主要保证当有大于100个人来同时抢到这个红包,只能前100名抢到,并且所分配的红包金额不能大于发放红包金额。

1、发放红包

发红包过程比较简单,不涉及并发,这里简单说明。
这里写图片描述
以上为发放红包简单流程。
主代码生成主红记录,记录红包

insert into main_package(total_amount,remain_amout,total_num,remain_num)

2、抢红包流程

这里写图片描述
这里抢红包主要是控制并发,这里用了数据库行锁来控制伪代码如下:

int tryCount=0;
//加while循环,在发生并发时 失失败的情况可以重试,并且重试次数不大于10,避免数据库死锁,导致系统死循环
while(true && tryCount<10){
    tryCount ++;
    MainPackage mainPackage = select remain_amout,remain_num from main_package where orderid='orderid';
    //红包余额小于等于0,红包已被抢光,返回
    if(null == mainPacage || mainPackage.remainAmout<=0){
        return false;
    }
    //生成随机金额
    int randomAmount = getRandomAmount(mainPackage.remainAmout,mainPackage.remainNum);
    //防止随机金额生成错误
    if(randomAmount<=0){
        return false;
    }
    //更新主红包剩余金额及剩余个数,这里是利用 where条件里面加上红包余额来控制并发的
    int updateStatus = update main_package set remain_amout = mainPacage.remainAmout-randomAmount,
                              remain_num = remain_num-1 
                             where orderid='orderid' and remain_amout= mainPacage.remainAmout;
    if(updateStatus>0){
        //生成子红包,这里没有控制事物,子表手机号作为唯一索引防止并发重复抢红包。
        try{
        instert into sub_package(orderid,sub_orderid,amount,mobile  );
        }catch{
	         //如果插入失败,将主表扣去的金额加回去
	         try{
	              update main_package
	        set REMAININGAMOUNT = REMAININGAMOUNT + #{redSubAmt}, REMAININGNUMBER = REMAININGNUMBER+1, where ORDERID = #{orderId}         
	         }catch(){
	            return;
	         }
        }
        break;      
    }
}

我们做了并发测试,在qps可达到3000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值