工具类:
package com.midea.mideacloud.paascommon.helper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.Objects;
@Slf4j
@Component
public class RedisLockHelper {
public static final String PACKAGE_PREFIX = "redis_lock";
public static final String LOCK_PREFIX = "redis_lock_";
public static final int LOCK_EXPIRE = 1800000; // 单位ms 30分钟过期
@Autowired
StringRedisTemplate stringRedisTemplate;
/**
* redis分布式锁
*
* @param key
* @return 是否获取到
*/
public boolean lock(String key){
String lock = PACKAGE_PREFIX+":"+LOCK_PREFIX + key;
return (Boolean) stringRedisTemplate.execute((RedisCallback) connection -> {
long expireAt = System.currentTimeMillis() + LOCK_EXPIRE + 1;
Boolean acquire = connection.setNX(lock.getBytes(), String.valueOf(expireAt).getBytes());
if (acquire) {
return true;
} else {
byte[] value = connection.get(lock.getBytes());
if (Objects.nonNull(value) && value.length > 0) {
long expireTime = Long.parseLong(new String(value));
if (expireTime < System.currentTimeMillis()) {
// 如果锁已经过期,获取旧值设置新值,防止死锁
byte[] oldValue = connection.getSet(lock.getBytes(), String.valueOf(System.currentTimeMillis() + LOCK_EXPIRE + 1).getBytes());
return Long.parseLong(new String(oldValue)) < System.currentTimeMillis();
}
}
}
return false;
});
}
/**
* 删除锁
*
* @param key
*/
public void delete(String key) {
stringRedisTemplate.delete(PACKAGE_PREFIX+":"+LOCK_PREFIX + key);
}
}
使用:
package com.midea.mideacloud.paasservice.scheduler;
import com.midea.mideacloud.paascommon.helper.RedisLockHelper;
import com.midea.mideacloud.paasservice.domain.api.NoticeRecordsFeign;
import com.midea.mideacloud.paasservice.domain.dto.NoticeRecordsDto;
import com.midea.mideacloud.paasservice.service.ICommonNoticeService;
import com.mideaframework.core.web.JsonResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
@Component
@Slf4j
public class NoticeReSendTask extends RedisLockHelper{
@Autowired
NoticeRecordsFeign noticeRecordsFeign;
@Autowired
ICommonNoticeService commonNoticeService;
@Scheduled(cron = "0 0/30 * * * ?")
public void reSendNotice(){
if (!this.lock("reSend-task")){
log.info("获取reSend锁失败,退出");
return;
}
log.info("获得reSend锁,重发通知开始");
NoticeRecordsDto noticeRecords = new NoticeRecordsDto();
noticeRecords.setStatus(1);
noticeRecords.setSendTime(LocalDateTime.now().minusMinutes(30));
noticeRecords.setRetryTimes(3);
JsonResponse<List<NoticeRecordsDto>> list = noticeRecordsFeign.list(noticeRecords);
if (list != null && CollectionUtils.isNotEmpty(list.getData())){
for (NoticeRecordsDto dto: list.getData()) {
commonNoticeService.reSendNotice(dto);
}
}
this.delete("reSend-task");
log.info("重发通知结束");
}
}