Based on multi-threaded Division lock redis

public interface DistributeLock {
	
	/**
	 * 获取分布式锁,没有获取成功,阻塞直到默认超时
	 */
	boolean lock(String key);
	
	/**
	 * 获取分布式锁,没有获取成功,阻塞直到超时
	 * @param timeout
	 */
	boolean lock(String key,int timeout);
	
	/**
	 * 释放锁
	 */
	void release(String key);

}
package com.amarsoft.sea.processor.icdata.icalter.yszx.Timer;

import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.amarsoft.sea.utils.RedisUtils;

/**
 * 基于redis实现的分布式锁
 */
@Component
public class RedisDistributeLock implements DistributeLock {
	
	private final String LOCK_KEY_PREFIX = "hubservice.redislock.";
	
	private final int DEFAULT_TIME_OUT = 2 * 60;
    //设置过期时间,以防一个服务挂掉,不会释放锁
	
	@Autowired
	private RedisUtils redisUtils;

	@Override
	public boolean lock(String key) {
		return doLock(key, DEFAULT_TIME_OUT);
	}

	@Override
	public boolean lock(String key,int timeout) {
		return doLock(key, timeout);
	}
	
	private boolean tryLock(String key,int timeout) {
		List<String> keys = Arrays.asList(key);
		List<String> args = Arrays.asList(String.valueOf(timeout));
		String luaScript = createLuaScript();
		Object result = redisUtils.executeLua(luaScript, keys, args);
		if (result == null) {
			return false;
		}
		String value = result.toString().trim();
		return value.equals("1") ? true : false;
	}
	
	private boolean doLock(String key,int timeout) {
		String lockKey = LOCK_KEY_PREFIX + key;
		return tryLock(lockKey, timeout);
	}

	@Override
	public void release(String key) {
		String lockKey = LOCK_KEY_PREFIX + key;
		redisUtils.remove(lockKey);//释放锁的最佳方式就是删除它
	}
	
	private String createLuaScript() {
		String luaScript = "" + 
					"local lockKey = KEYS[1];\n" +
					"local timeout = ARGV[1];\n" + 
					"if (redis.call('exists',lockKey) == 0) then \n" +
					"	redis.call('setex',lockKey,timeout,'1');\n" +
					"	return 1;\n" +
					"else \n" +
					"	return 0;\n" +
					"end \n";
		
		return luaScript;
	}

}
package com.amarsoft.sea.processor.icdata.icalter.yszx.Timer;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.amarsoft.sea.dao.crsbjt.ICTaskRepository;
import com.amarsoft.sea.entity.crsbjt.ICTask;
import com.amarsoft.sea.processor.icdata.icalter.yszx.EntICAlterYszx;

@Component
public class ScheduledExecutorService2ICAlterYszx {
	
	private final static Logger LOGGER = LoggerFactory.getLogger(ScheduledExecutorService2ICAlterYszx.class);
	
	@Autowired
	private ICTaskRepository ICTaskRep;
	
	@Autowired
	private EntICAlterYszx entICAlterYszx;
	
	@Autowired
	private RedisDistributeLock lock;
	
	@Value("${seaservice.period:20}")
	private long time;
	
	@PostConstruct
	public void init() {
		LOGGER.info("定时任务已启动...");
		ScheduledExecutorService service = Executors.newScheduledThreadPool(5);
		service.scheduleAtFixedRate(new processTask(), 1, time, TimeUnit.MINUTES);
	
	}
	
	private class processTask implements Runnable{
		
		@Override
		public void run() {
			//加锁
			String key = "ic.alter.fail.retry";
			try {
				boolean flag = lock.lock(key);
				if (!flag) {
					return;
				}
				List<ICTask> iCTask = ICTaskRep.findFailStatus();
				JSONArray array = new JSONArray();
				iCTask.forEach(result -> {
					array.add(JSONObject.parseObject(result.getAttribute2()));
				});
				if(array.size() > 0){
					JSONObject jsonObject = new JSONObject();
					jsonObject.put("count", String.valueOf(array.size()));
					jsonObject.put("data", array);
					entICAlterYszx.processMsg(jsonObject.toJSONString());
				}
			}catch (Throwable e) {
				LOGGER.error("重试机制消费失败消息出错!!!",e);
			} finally {
				lock.release(key);
			}
		}
		
	}

}
package com.amarsoft.sea.utils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.*;

/**
 * redis 工具类
 */
@Component("redisUtils")
public class RedisUtils {

    private volatile JedisSentinelPool pool;

    @Value("${redis.sentinels.hosts}")
    private String sentinelHosts;

    @Value("${redis.maxActive}")
    private Integer maxActive;

    @Value("${redis.maxIdel}")
    private Integer maxIdel;

    @Value("${redis.maxWait}")
    private Integer maxWait;

    @Value("${redis.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${redis.masterName}")
    private String masterName;

    @Value("${redis.keyExpire:600}")
    private Integer keyExpireTime;

    @PostConstruct
    public void init() {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(maxActive);
        poolConfig.setMaxIdle(maxIdel);
        poolConfig.setMaxWaitMillis(maxWait);
        poolConfig.setTestOnBorrow(testOnBorrow);

        Set<String> sentinels = new HashSet<String>();
        sentinels.addAll(Arrays.asList(sentinelHosts.split(",")));

        pool = new JedisSentinelPool(masterName,sentinels,poolConfig);
    }


    public String get(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.get(key);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public void set(String key,String value) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            jedis.setex(key,keyExpireTime,value);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    public void remove(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            jedis.del(key);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    public void incr(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            jedis.incr(key);
            jedis.expire(key,keyExpireTime);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    public void hmset(String key,Map<String,String> hash) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            jedis.hmset(key,hash);
            jedis.expire(key,keyExpireTime);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public String hmget(String key,String field) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            List<String> list = jedis.hmget(key,field);
            if (list == null || list.size() == 0) {
                return null;
            } else {
                return list.get(0);
            }
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public Map<String,String> hmget(String key,String ...fields) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            List<String> list = jedis.hmget(key,fields);
            Map<String,String> map = new HashMap<String,String>();
            for (int i = 0; i < fields.length; i++) {
                map.put(fields[i],list.get(i));
            }

            return map;
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }


    public Object executeLua(String luaScript,List<String> keys,List<String> args) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.eval(luaScript,keys,args);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public boolean hexists(String key,String field) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.hexists(key,field);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    public boolean exists(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.exists(key);
        }finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    @PreDestroy
    public void close(){
        if (pool != null) {
            pool.close();
        }
    }


}

 

Guess you like

Origin blog.csdn.net/John_Kry/article/details/95207541