简单的分布式锁+队列

业务逻辑:多个数据同步请求并发访问,需要做到请求次数不丢失,比如产生50个请求,那么50个同步请求需要按顺序执行,同步50次;涉及到的环境为2台tomcat服务器双活模式

代码逻辑:首先将每次请求均存入至redis队列 network_queue,而后使用springboot定时触发(之所以使用springboot定时方式,而不用线程池是因为springboot定时调度是单线程串行的,只有上一个任务执行完后 下一个任务才会进行)

package com.hansight.abc.listener;

import com.hansight.abc.redis.RedisUtil;
import com.hansight.abc.util.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 定时任务 + 分布式锁
 */
@Component
public class NetworkTest {

    private static final Logger logger = LoggerFactory.getLogger(NetworkTest.class);
    @Autowired
    private RedisUtil redisUtil;

    @Scheduled(cron = "*/20 * * * * ?")
    public void run() throws UnknownHostException {
        logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        Long size = redisUtil.llen("network_queue");
        logger.info("当前本地网段redis队列长度为 {}", size);
        String time = String.valueOf((new Date()).getTime()) + "_" + UUID.randomUUID().toString();
        Long status = redisUtil.setnx("network_lock",  time,60);
        logger.info("time {} 是否抢到锁 {}",time,status==1?"是":"否");
        String nxVlue = redisUtil.get("network_lock");
        if ( size >0 && status == 1) {
            String value = redisUtil.rpop("network_queue");
            logger.info("已加锁 {} 本地网段redis中取出值为 {}", nxVlue, value);
            UUIDUtil.test(value);
        }
        logger.info("nxVlue.equals(time) {}",nxVlue.equals(time));
        if (status == 1 && nxVlue.equals(time)) {
            redisUtil.remove("network_lock");
            logger.info("已删除当前锁  nxVlue  {}  time  {}",nxVlue,time);
        }
    }
}

package com.hansight.abc.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
public class RedisUtil {
    private static final Logger logger = LoggerFactory.getLogger(RedisUtil.class);

    @Autowired
    private JedisSentinelPool jedisSentinelPool;

    public void remove(final String... keys) {
        for (String key : keys) {
            remove(key);
        }
    }

    public void remove(final String key) {
        if (exists(key)) {
            try (Jedis jedis = jedisSentinelPool.getResource()) {
                jedis.del(key);
                jedis.close();
            } catch (Exception e) {
                logger.error("Error on delete key: {}", key, e);
            }
        }
    }

    public boolean exists(final String key) {
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            Boolean exists = jedis.exists(key);
            jedis.close();
            return exists;
        } catch (Exception e) {
            logger.error("Error on check key exists: {}", key, e);
        }
        return false;
    }

    public String get(final String key) {
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            String s = jedis.get(key);
            jedis.close();
            return s;
        } catch (Exception e) {
            logger.error("Error on get value by key: {}", key, e);
        }
        return null;
    }

    public boolean set(final String key, Object value) {
        if (value == null) {
            logger.warn("invalid value for key: {}", key);
            return false;
        }
        boolean result = false;
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            jedis.set(key, value.toString());
            jedis.close();
            result = true;
        } catch (Exception e) {
            logger.error("Error on set value to key: {}", key, e);
        }
        return result;
    }

    public boolean set(final String key, Object value, int expireTime) {
        if (value == null) {
            logger.warn("invalid value for key: {}", key);
            return false;
        }
        boolean result = false;
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            jedis.set(key, value.toString());
            jedis.expire(key, expireTime);
            jedis.close();
            result = true;
        } catch (Exception e) {
            logger.error("Error on set value to key with expire time in seconds {}: {}", expireTime, key, e);
        }
        return result;
    }

    public Long putSet(final String key, final String[] value) {
        if (value == null || value.length <= 0) {
            logger.warn("invalid value for key: {}", key);
            return 0L;
        }
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            Long sadd = jedis.sadd(key, value);
            jedis.close();
            return sadd;
        } catch (Exception e) {
            logger.error("Error on execute set-add to key: {}", key, e);
            return -1L;
        }
    }

    public Long putSet(final String key, final List<String> value) {
        return putSet(key, value.toArray(new String[0]));
    }

    public Set<String> getSet(final String key) {
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            Set<String> smembers = jedis.smembers(key);
            jedis.close();
            return smembers;
        } catch (Exception e) {
            logger.error("Error on get set-members from key: {}", key, e);
            return new HashSet<>();
        }
    }

    public void rename(String oldKey, String newKey) {
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            jedis.rename(oldKey, newKey);
            jedis.close();
        } catch (Exception e) {
            logger.error("Error on rename key from [{}] to [{}]", oldKey, newKey, e);
        }
    }

    public Long increment(String key, int increment) {
        Long res = 0L;
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            res =  jedis.incrBy(key, increment);
            jedis.close();
        } catch (Exception e) {
            logger.error("Error on incrBy key {},increment {} ", key, increment, e);
        }
        return res;
    }

    public Set<String> keys(final String key) {
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            Set<String> keys = jedis.keys(key);
            jedis.close();
            return keys;
        } catch (Exception e) {
            logger.error("Error on check key keys: {}", key, e);
        }
        return null;
    }

    public Long llen(String key) {
        Long result = 0L;
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            result = jedis.llen(key);
        } catch (Exception e) {
            logger.error("Error on check key keys: {}", key, e);
        }
        return result;
    }

    public Long setnx(String key,String value,int expirTime){
        Long result = 0L;
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            result = jedis.setnx(key,value);
            if(result==1){
                jedis.expire(key,expirTime);
            }
        } catch (Exception e) {
            logger.error("Error on check key keys: {}", key, e);
        }
        return result;
    }

    public String rpop(String key) {
        String result = null;
        try (Jedis jedis = jedisSentinelPool.getResource()) {
            result = jedis.rpop(key);
        } catch (Exception e) {
            logger.error("Error on check key keys: {}", key, e);
        }
        return result;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值