使用ELock实现高性能分布式锁(非轮询)

本文介绍了如何在高并发场景下避免使用分布式锁,提出了一个简单的业务处理方案。接着,作者分享了自己开发的ELock,这是一款非轮询阻塞的分布式锁插件,适用于互联网产品,已在大型直播系统中应用。文章详细讲解了ELock的使用方法,包括在Spring环境下的注解和执行器两种加锁方式,并对比了ELock与传统轮询分布式锁的性能差异,指出ELock如何利用消息订阅机制避免DDoS攻击。
摘要由CSDN通过智能技术生成

前言:

    随着笔者的颜值不断提高,用户量的日益增长,传统的单机方案已经不能满足产品的需求。笔者在网上寻遍方案,发现均为人云亦云,一份以毫秒为精度的轮询分布式锁被转发转载上万次。然,该方案没法满足笔者性能要求。故此,笔者研发ELock插件,并发布本文章。

其实集群也好,分布式服务也好。当我们不能保证团队成员的整体素质,那么在某些业务上,分布式锁自然没法避免。

公认开发原则:能不使用分布式锁的,尽可能不使用

举个例子,一个商品交易,需要检查库存、检查余额、扣库存、扣款、生成订单。可能很多人觉得,在分布式环境下一定要分布式锁才能安全。

致此,笔者提供一种简单的方案:

订单处理{
    if(库存不足){
        return 库存不足;
    }
    if(余额不足){
        return 余额不足;
    }
    事务管理(rollbackFor = Exception.class){
        //扣库存
        int changeLine = 执行语句(update 商品表 set 库存=库存-购买数量 where 库存>购买数量 and 商品ID = ?);
        if(changeLine != 1){
            return 库存不足;
        }
        double 扣款金额= 商品价格 x 购买数量;
        //扣款
        changeLine = 执行语句(update 用户余额表 set 余额=余额-扣款金额 where 余额 > 扣款金额 and 扣款金额 > 0 and 用户ID = ?);
        if(changeLine != 1){
            throw CustomRuntimeException("余额不足");
        }
        //生成订单
        changeLine = 执行语句( insert into 订单表 set ......);
        if(changeLine < 1){
            throw CustomRuntimeException("订单生成失败");
        }
    }
}

我们仔细来分析一下如上的整个逻辑

1、当一个业务进入逻辑体,先检查余额和库存,不满足条件则返回错误(可阻挡非并发情况下的大部分业务流入事物)

2、进入事物后,先扣取库存,当扣取失败,直接返回错误

3、扣取库存后,则进行扣款,当扣款失败,则抛出异常(由于在业务体走到这里,已经扣取了库存,本处不能return,需抛出异常,让事物回滚)

4、扣款成功后,则生成订单,当订单生成失败,则抛出异常(理由同第三点)

特别注意:语句中,通过where来进行余额不足和库存不足的条件判断。通过执行语句返回的影响行数,来判断是否扣取成功。 在以上流程中,我们发现,即便不使用分布式锁,也无并发问题。

============================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值