Java-Redis

作者: GoGooGooo | 来源:发表于2018-01-09 19:30 被阅读14次

    程序在单台应用的时候,程序上完全可以用synchronized同步锁来限制多线程对共享资源的访问,但在分布式环境下同步锁无法控制不同进程之间的线程,这种情况下就需要找一种单进程可串行处理的“锁”,
    所以产生了分布式锁这个玩意;
    至于 分布式锁我了解到的实现有三种方案
    期初在做这个的时候也考虑了他们的实现优缺点

    zookeeper分布式锁

    优点:
    锁安全性高,zk可持久化。当然 redis 也可以实现持久化。
    缺点:
    性能开销比较高。因为其需要动态产生、销毁瞬时节点来实现锁功能。

    memcached分布式锁

    优点:
    并发高效。
    缺点:
    (1)memcached采用列入LRU置换策略,所以如果内存不够,可能导致缓存中的锁信息丢失。
    (2)memcached无法持久化,一旦重启,将导致信息丢失。

    redis 分布式锁

    也是我最推荐的
    redis分布式锁即可以结合zk分布式锁锁高度安全和memcached并发场景下效率很好的优点,可以利用jedis客户端实现。代码见最后。

    怎么使用

    RedisLock redisLockN = redisLock.newInstance(RedisKey.KEY_SETUP_ACCOUNT.getCode(), 10000);
    
    if (redisLockN.lock()) {
        //业务代码
        redisLockN.unlock();
       LOGGER.info(" 释放redis分布式锁");
    } else {
            LOGGER.error("获取redis分布式锁失败 请检查");
            throw new 抛出异常
    }
    

    具体实现

    把我们的核心代码都复制出来,不知道老大会不会出来打我

    @Component
    public class RedisLock {
    
        private static final Logger LOGGER = LoggerFactory.getLogger(RedisLock.class);
    
        private static final int DEFAULT_LOCK_EXPIRSE_MILL_SECONDS = 1000*30;
    
        private static final int DEFAULT_LOCK_WAIT_DEFAULT_TIME_OUT = 1000*10;
    
        private static final int DEFAULT_LOOP_WAIT_TIME = 150;
    
        private boolean lock = false;
    
        private String lockKey = null;
    
        private int lockExpriseTimeout;
    
        private int lockWaitTimeOut;
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @Deprecated
        public RedisLock(){}
    
        public RedisLock(String lockKey,int lockExpriseTimeout,int lockWaitTimeOut)
        {
            this.lockKey = lockKey;
    
            this.lockExpriseTimeout = lockExpriseTimeout;
    
            this.lockWaitTimeOut = lockWaitTimeOut;
        }
    
        public RedisLock newInstance(String lockKey,int lockWaitTimeOut)
        {
            if(lockWaitTimeOut == 0)
            {
                lockWaitTimeOut = DEFAULT_LOCK_WAIT_DEFAULT_TIME_OUT;
            }
    
            RedisLock lock = new RedisLock(lockKey,DEFAULT_LOCK_EXPIRSE_MILL_SECONDS,lockWaitTimeOut);
    
            lock.setStringRedisTemplate(this.stringRedisTemplate);
    
            return lock;
        }
    
    
        private boolean putIfAbsent(String expirseTimeStr)
        {
            return this.stringRedisTemplate.opsForValue().setIfAbsent(this.lockKey,expirseTimeStr);
        }
    
        private String getAndSet(String expirseTimeStr)
        {
            return this.stringRedisTemplate.opsForValue().getAndSet(this.lockKey,expirseTimeStr);
        }
    
        public boolean lock()
        {
            int lockWaitMillSeconds = this.lockWaitTimeOut;
    
            String redis_value = String.valueOf(System.currentTimeMillis()+this.lockExpriseTimeout);
    
            while(lockWaitMillSeconds > 0)
            {
                lock = this.putIfAbsent(redis_value);
    
                if(lock)
                {
                    this.lock = true;
    
                    return this.lock;
                }
                else
                {
                    String oldRedisValue = this.stringRedisTemplate.opsForValue().get(this.lockKey);
    
                    long currentTimeMillSeconds = System.currentTimeMillis();
    
                    if(!StringUtils.isEmpty(oldRedisValue) && Long.parseLong(oldRedisValue) < currentTimeMillSeconds)
                    {
                        String currentRedisValue = this.getAndSet(String.valueOf(currentTimeMillSeconds+this.lockExpriseTimeout));
    
                        if(oldRedisValue.equals(currentRedisValue))
                        {
                            this.lock = true;
    
                            return this.lock;
                        }
                    }
                }
    
                lockWaitMillSeconds -= DEFAULT_LOOP_WAIT_TIME;
    
                try
                {
                    Thread.sleep(DEFAULT_LOOP_WAIT_TIME);
                }
                catch (Exception ex)
                {
                    LOGGER.error("redis同步锁 出现未知异常",ex);
                }
            }
    
            return false;
        }
    
        public void unlock()
        {
            if (this.lock) {
                this.stringRedisTemplate.delete(this.lockKey);
                this.lock = false;
            }
        }
    
        public boolean isLock() {
            return lock;
        }
    
        public void setLock(boolean lock) {
            this.lock = lock;
        }
    
        public String getLockKey() {
            return lockKey;
        }
    
        public void setLockKey(String lockKey) {
            this.lockKey = lockKey;
        }
    
        public int getLockExpriseTimeout() {
            return lockExpriseTimeout;
        }
    
        public void setLockExpriseTimeout(int lockExpriseTimeout) {
            this.lockExpriseTimeout = lockExpriseTimeout;
        }
    
        public int getLockWaitTimeOut() {
            return lockWaitTimeOut;
        }
    
        public void setLockWaitTimeOut(int lockWaitTimeOut) {
            this.lockWaitTimeOut = lockWaitTimeOut;
        }
        public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
            this.stringRedisTemplate = stringRedisTemplate;
        }
    }
    

    相关文章

      网友评论

        本文标题:Java-Redis

        本文链接:https://www.haomeiwen.com/subject/dkmgnxtx.html