snake107

redis锁

工具类:

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("重发通知结束");
    }

}
posted @ 2020-01-02 15:36  爱喝奶茶的皮卡丘  阅读(278)  评论(0编辑  收藏  举报