优惠券超发问题该怎么测试?

Redission红锁其实是上述redis分布式锁的升级版,主要是框架已经封装好了我们需要的方法,实际过程中只要引入相应的jar包,使用对应的api即可。

Maven引入:

   org.redisson
   redisson
   3.17.4

伪代码如下:

public JsonData getCoupon(long couponId, CouponCategoryEnum categoryEnum) {
    String key = "lock:coupon:" + couponId;
    RLock rLock = redisson.getLock(key);
    LoginUser loginUser = LoginInterceptor.threadLocal.get();
    rLock.lock();
    try{
       //业务逻辑
    }finally {
        rLock.unlock();
    }
    return JsonData.buildSuccess();
}

使用这种方式也无需关心 key 过期时间续期的问题,因为在 Redisson 一旦加锁成功,就会启动一个 watch dog,你可以将它理解成一个守护线程,它默认会每隔 30 秒(可灵活配置)检查一下,如果当前客户端还占有这把锁,它会自动对这个锁的过期时间进行延长。

Zookeeper分布式锁

Zookeeper分布式锁应用了临时顺序节点。具体如何实现呢?让我们来看一看详细步骤:

获取锁:

首先,在Zookeeper当中创建一个持久节点ParentLock。当第一个客户端(Client1)想要获得锁时,需要在ParentLock这个节点下面创建一个临时顺序节点 Lock1。

面对优惠券超发问题该怎么测试?

之后,Client1查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock1是不是顺序最靠前的一个。如果是第一个节点,则成功获得锁。

面对优惠券超发问题该怎么测试?

这时候,如果再有一个客户端 Client2 前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock2。

面对优惠券超发问题该怎么测试?

Client2查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock2是不是顺序最靠前的一个,结果发现节点Lock2并不是最小的。

于是,Client2向排序仅比它靠前的节点Lock1注册Watcher,用于监听Lock1节点是否存在。这意味着Client2抢锁失败,进入了等待状态。

面对优惠券超发问题该怎么测试?

这时候,如果又有一个客户端Client3前来获取锁,则在ParentLock下载再创建一个临时顺序节点Lock3。

面对优惠券超发问题该怎么测试?

Client3查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点Lock3是不是顺序最靠前的一个,结果同样发现节点Lock3并不是最靠前的。

于是,Client3向排序仅比它靠前的节点Lock2注册Watcher,用于监听Lock2节点是否存在。这意味着Client3同样抢锁失败,进入了等待状态。

面对优惠券超发问题该怎么测试?

这样一来,Client1得到了锁,Client2监听了Lock1,Client3监听了Lock2。这恰恰形成了一个等待队列,很像是Java当中ReentrantLock所依赖的AQS。

怎么测试并发安全问题?

首先我们要保证测试环境的项目是分布式、集群部署,其次可以根据线上获取优惠券接口的实际QPS,在测试环境使用工具jmeter并发请求优惠券接口,运行一段时间后,再去看下数据库相应的数据,譬如优惠券库存信息,抢购优惠券信息等等,反复多次运行看下效果。

总结

本篇文章主要分享了电商项目中一种常见的并发安全问题,以及相应的解决方案,如果从性能的角度去考虑应该是Redis > zookeeper > 数据库。从可靠性(安全)性角度:zookeeper > Redis > 数据库。

源自公众号  懂Java的测试

上一页12下一页


留言