最近项目中新上线了抢优惠券功能,虽然用户不多但是,如何防止超发呢?单体应用情况下只需要在抢券方法前用synchronized修饰即可,但是目前大部分项目都是分布式微服务架构,所以就需要加分布式锁。项目用的SpringMVC+dubbo,注册中心使用的zookeeper,所以就选用的基于zookeeper的分布式锁。
原生的zookeeper分布式锁写起来比较复杂,使用zookeeper的Curator框架轻松实现,代码实现:
pom文件
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.6</version> </dependency> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-recipes</artifactId> <version>4.0.1</version> </dependency>
Spring集成
<!-- 重连策略 --> <bean id="retryPolicy" class="org.apache.curator.retry.ExponentialBackoffRetry"> <!-- 间隔时间基数 --> <constructor-arg index="0" value="1000" /> <!-- 重连策略 --> <constructor-arg index="1" value="3" /> </bean> <bean id="curatorFramework" class="org.apache.curator.framework.CuratorFrameworkFactory" factory-method="newClient" init-method="start"> <constructor-arg index="0" value="#{globalConfig.zk_address}" /> <!-- sessionTimeoutMs会话超时时间,单位为毫秒。默认是60000ms --> <constructor-arg index="1" value="5000" /> <!-- connectionTimeoutMs连接创建超时时间,单位毫秒,默认15000ms --> <constructor-arg index="2" value="3000" /> <constructor-arg index="3" ref="retryPolicy" /> </bean>
@Autowired
private CuratorFramework curatorFramework;
//定义锁路径
String path = "/lock/discount/" + discountId;
InterProcessMutex lock = new InterProcessMutex(curatorFramework, path);
//获取锁
if (lock.acquire(3000, TimeUnit.MILLISECONDS)) {
//do something
}
//释放锁
lock.release();
分布式锁配合事务使用时,不要加到事务方法上,在外层调用者上加锁,否则存在事务未提交即获取锁;
来源:oschina
链接:https://my.oschina.net/u/250524/blog/3102192