分布式服务的时,如何确保只有一个服务做了执行?
业务需求
有一些业务,比如说定时清除临时数据,定时处理支付超时的业务。如果你有多个服务程序,也就是集群部署的,如果每个服务都执行了处理超时订单,查询可能没问题,修改可能会出问题。
我们可以加锁处理,也可以用信号量的方式去执行,哪个服务拿到执行权执行就好。
以下是我用redison信号量处理的方式。
初始化信号量
在程序启动的时候,去获取信号号,并且设置允许的数量。
@EnableScheduling
public class ServiceApiApp {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(ServiceApiApp.class, args);
//初始化定时器的信号量
RedissonClient redisSon = ctx.getBean(RedissonClient.class);
RSemaphore handlePayTimeOutOrderSemaphore = redisSon.getSemaphore("handlePayTimeOutOrder");
int handlePayTimeOutOrderSemaphoreCount = handlePayTimeOutOrderSemaphore.availablePermits();
log.info("handlePayTimeOutOrderSemaphoreCount ==> " + handlePayTimeOutOrderSemaphoreCount);
if (handlePayTimeOutOrderSemaphoreCount != 1) {
handlePayTimeOutOrderSemaphore.trySetPermits(1);
}
}
}
定时器里的代码
定时器里我30秒执行一次
@Scheduled(cron = "0/30 * * * * ?")
public void handlePayTimeOutOrder() {
//log.warn("handlePayTimeOutOrder");
String isCheck = (String) redisUtil.get(GConfig.RedisKey.ORDER_TIME_OUT_CHECK);
if (TextUtils.isEmpty(isCheck)) {
return;
}
RSemaphore rSemaphore = redisSon.getSemaphore("handlePayTimeOutOrder");
if (rSemaphore.tryAcquire(1)) {
try {
//TODO:处理业务
} catch (Exception e) {
e.printStackTrace();
} finally {
rSemaphore.release();
}
}
}
这样子就可以确保多个服务实例的时候,谁拿到信号量谁就去执行。