zoukankan      html  css  js  c++  java
  • redis分布式锁实现

    public interface DistributedLock {
        /**
         * 加锁
         * @param lockKey 锁定的key
         * @param lockSeconds  锁定时间(单位:秒),超过该锁定时间会自动释放锁,可能会导致并发问题。
         * @param expirySeconds  本次获取锁请求失效时间(单位:秒)
         * @param sleepMillisecond 本次获取锁失败,等到多少毫秒再次尝试获取(单位:毫秒)
         * @return 返回值大于0,则说明获取到锁,调用者需要保留该值,并在解锁时传入。
         */
        public Long lock(String lockKey,long lockSeconds, long expirySeconds, int sleepMillisecond);
        
        /**
         * 解锁
         * @param lockKey 锁定的key
         */
        public void unlock(String lockKey,long lockValue);
    }
    import java.util.concurrent.TimeUnit;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    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.StringRedisTemplate;
    import org.springframework.stereotype.Service;
    
    import com.aaron.redis.lock.DistributedLock;
    
    @Service("redisDistributedLock")
    public class RedisDistributedLockImpl implements DistributedLock {
        private static final Logger LOG = LoggerFactory.getLogger(RedisDistributedLockImpl.class);
    
        /**
         * 锁定超时时间60秒, 单位毫秒, 意味着加锁期间内执行完操作 如果未完成会自动过期释放锁,造成并发问题。
         */
        private static final long DEFAULT_LOCK_TIMEOUT = 60 * 1000;
    
        @Autowired
        protected StringRedisTemplate stringRedisTemplate;
    
        @Override
        public Long lock(String lockKey, long lockSeconds, long expirySeconds, int sleepMillisecond) {
            Long lockVal = 0L;
            long currMs = System.currentTimeMillis();
            if (lockSeconds > 0L) {
                lockSeconds = lockSeconds * 1000;
            } else {
                lockSeconds = DEFAULT_LOCK_TIMEOUT;
            }
            while (true) {
                Long nextmin = getNextMin();
    
                boolean lockResult = stringRedisTemplate.execute(new RedisCallback<Boolean>() {
                    @Override
                    public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                        return connection.setNX(lockKey.getBytes(), String.valueOf(nextmin).getBytes());
                    }
                });
                if (lockResult) {// 获得锁
                    LOG.debug("+++key:{} lock success", lockKey);
                    stringRedisTemplate.expire(lockKey, lockSeconds, TimeUnit.MILLISECONDS); // 设置超时时间,释放内存
                    lockVal = nextmin;
                    break;
                } else {
                    // 调用get
                    String lockTimeObj = stringRedisTemplate.opsForValue().get(lockKey); // redis里的时间
    
                    if (null != lockTimeObj) {
                        Long ts = Long.valueOf(lockTimeObj);
                        long nowTs = System.currentTimeMillis();
                        if (nowTs - ts >= 0) {// 锁已经失效
                            // 调用getset,获取旧值,写入新值,获取不到值为null
                            long nextminVal = getNextMin();
                            String lockTimeObj1 = stringRedisTemplate.opsForValue().getAndSet(lockKey,
                                    String.valueOf(nextminVal));
                            if (null == lockTimeObj1 || lockTimeObj.equals(lockTimeObj1)) {
                                stringRedisTemplate.expire(lockKey, lockSeconds, TimeUnit.MILLISECONDS); // 设置超时时间,释放内存
                                lockVal = nextminVal;
                                break;
                            }
                        }
                    }
    
                    if (lockVal == 0L) {
                        if (checkTimeout(currMs, expirySeconds)) {
                            break;
                        }
                        sleep(sleepMillisecond);
                    }
                }
            }
            return lockVal;
        }
    
        @Override
        public void unlock(String lockKey, long lockValue) {
            if (lockValue <= 0L) {
                return;
            }
            String objVal = stringRedisTemplate.opsForValue().get(lockKey);
            if (objVal != null && objVal.equals(String.valueOf(lockValue))) {
                stringRedisTemplate.delete(lockKey); // 删除键
                LOG.debug("+++key:{} release success", lockKey);
            }
        }
    
        private boolean checkTimeout(long currMs, long expirySeconds) {
            return (System.currentTimeMillis() - currMs) > (expirySeconds * 1000);
        }
    
        private long getNextMin() {
            return System.currentTimeMillis() + 60000;
        }
    
        private void sleep(int ms) {
            try {
                if (ms <= 0) {
                    ms = 50;
                }
                Thread.sleep(ms);
            } catch (InterruptedException e) {
            }
        }
    
    }

            //lockKey
            String lockKey = "lockKey"; //key
            //获取到锁,则锁定30秒
            long lockSeconds = 30;
            //请求200秒如果还没获取到锁就超时返回
            long expirySeconds = 0;
            //未获取到锁,则休息30毫秒然后重试,直到expirySeconds过期
            int sleepMillisecond = 30;
            //获取锁
            long lockVal = redisDistributedLock.lock(lockKey, lockSeconds, expirySeconds, sleepMillisecond);
            //获取锁成功
            if(lockVal > 0L){
                try{
              //执行逻辑
           }catch (Exception e){
    }
    finally{ //释放锁 redisDistributedLock.unlock(lockKey, lockVal); } }else{ //获取锁失败 } }
  • 相关阅读:
    Compression algorithm (deflate)
    tcpip数据包编码解析(chunk and gzip)_space of Jialy_百度空间
    What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
    gzip压缩算法: gzip 所使用压缩算法的基本原理
    Decompressing a GZip Stream with Zlib
    Frequently Asked Questions about zlib
    how to decompress gzip stream with zlib
    自己动手写web服务器四(web服务器是如何通过压缩数据,web服务器的gzip模块的实现)
    What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
    C语言抓http gzip包并解压 失败 C/C++ ChinaUnix.net
  • 原文地址:https://www.cnblogs.com/aaronzheng/p/12106064.html
Copyright © 2011-2022 走看看