通过redis实现对于分布式的环境下的并发管理

使用定时器时,部署到多个节点,共同访问一个库,导致任务重复执行,然后想到了使用redis来实现锁原理.

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;

import java.util.concurrent.TimeUnit;

/**
 * 通过redis实现对于分布式的环境下的并发管理(通过redis锁实现并发处理)
 */
public class RedisDistributionLock implements DistributionLock {
    private long lockTimeout;
    private final RedisTemplate<String, RedisLockObject> redisTemplate;
    private final String lockKey;
    private final RedisSerializer keyRedisSerializer;
    private final RedisSerializer valueRedisSerializer;

    public RedisDistributionLock(RedisTemplate<String, RedisLockObject> redisTemplate, String key, long timeout) {
        this.redisTemplate = redisTemplate;
        this.lockTimeout = timeout;
        this.lockKey = key;
        this.keyRedisSerializer = redisTemplate.getKeySerializer();
        this.valueRedisSerializer = redisTemplate.getValueSerializer();

    }

    //尝试获取一次锁
    public synchronized boolean tryLock() {
        long currentTime = System.currentTimeMillis();
        Long lock_timeout = currentTime + lockTimeout;
        if (redisTemplate.execute(new LockRedisCallBack(this.lockKey, lock_timeout))) {
            redisTemplate.expire(lockKey, lockTimeout, TimeUnit.MILLISECONDS);
            return true;
        } else {
            RedisLockObject redisLockObject = null;
            try {
                Object object = redisTemplate.opsForValue().get(lockKey);
                if (object != null) {
                    redisLockObject = (RedisLockObject) redisTemplate.opsForValue().get(lockKey);
                }

            } catch (Exception err) {
                redisTemplate.delete(lockKey);
                err.printStackTrace();
            }
            if (redisLockObject != null && (redisLockObject.getTimeout() < currentTime)) {
                long oldTimeout = redisLockObject.getTimeout();
                redisLockObject.setTimeout(lockTimeout);
                RedisLockObject oldRedisLockObject = (RedisLockObject) redisTemplate.opsForValue().getAndSet(lockKey, redisLockObject);
                if (oldRedisLockObject != null && oldRedisLockObject.getTimeout() == oldTimeout) {
                    redisTemplate.expire(lockKey, lockTimeout, TimeUnit.MILLISECONDS);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 加锁 取到锁加锁,取不到锁就返回
     *
     * @return
     */
    @Override
    public synchronized long lock() {
        while (true) {
            if (tryLock()) {
                return System.currentTimeMillis() + lockTimeout;
            }
            try {
                Thread.sleep(10);
            } catch (Exception err) {
                err.printStackTrace();
            }
        }
    }

    /**
     * 解锁
     */
    @Override
    public synchronized void unlock() {
        RedisLockObject redisLockObject = (RedisLockObject) redisTemplate.opsForValue().get(lockKey);
        if (redisLockObject != null) {
            redisTemplate.delete(lockKey);
        }
    }


    @SuppressWarnings("rawtypes")
    private class LockRedisCallBack implements RedisCallback<Boolean> {
        private long timeOut;

        public LockRedisCallBack(String key, long timeOut) {
            this.timeOut = timeOut;
        }


        @SuppressWarnings("unchecked")
        @Override
        public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
            RedisLockObject redisLockObject = new RedisLockObject();
            redisLockObject.setTimeout(timeOut);
            byte[] value = valueRedisSerializer.serialize(redisLockObject);
            byte[] key = valueRedisSerializer.serialize(lockKey);
            return connection.setNX(key, value);
        }
    }
}
public interface DistributionLock {

    public long lock();

    public void unlock();

}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 现在的人太容易给自己盖上标签,自定义自己,或是吃货,或是其他等等,我觉得他们其实是为了一个噱头,一个能让别人假赞的...
    叫兽黄小海阅读 174评论 0 0

友情链接更多精彩内容