美文网首页一些收藏
分布式锁实现方案-Redis

分布式锁实现方案-Redis

作者: 洛神灬殇 | 来源:发表于2022-04-09 21:23 被阅读0次

一.Redis分布式锁实现分析

存在的问题:

如果某个线程执行的太慢,导致在有效期内还没有执行完,那么因为设置了锁超时自动释放机制,此时锁被自动释放,另一个线程进来拿到锁开始执行代码,就会出现同一时间有两个线程在执行互斥资源代码,可能出现数据不一致。
如何解决:

设置合理的超时时间 + 监控代码执行情况

自动续期,起一个定时任务,周期性扫描超距离时时间还剩多少时仍没有执行完的线程,自动延长时间。注定只能使用其他机制解决的难题

二.分布式锁实现方案

Redis锁开源实现:

三.自己实现一个基于Redis的分布式锁

package com.hong.redis;

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

import org.springframework.dao.DataAccessException;

import org.springframework.data.redis.connection.RedisConnection;

import org.springframework.data.redis.connection.RedisStringCommands;

import org.springframework.data.redis.core.RedisCallback;

import org.springframework.data.redis.core.StringRedisTemplate;

import org.springframework.data.redis.core.types.Expiration;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

/**

  • @author wanghong

**/

public class RedisLockImpl implements Lock {

@Autowired

private StringRedisTemplate stringRedisTemplate;

/**

* 你要锁的资源

*/

private String resourceName;

int timeout;

public RedisLockImpl(StringRedisTemplate stringRedisTemplate, String   

resourceName, int timeout) {

    this.stringRedisTemplate = stringRedisTemplate;

    this.resourceName = "lock_" + resourceName;

    this.timeout = timeout;

}

private Lock lock = new ReentrantLock();

/**

* 一直要等到抢到锁为止

*/

@Override

public void lock() {

    // 限制同一个JVM进程内的资源竞争,分布式锁(JVM之间的竞争) + JVM锁

    lock.lock();

    try {

        while (!tryLock()) {

            // 订阅指定的Redis主题,接收释放锁的信号

            stringRedisTemplate.execute(new RedisCallback<Long>() {

                @Override

                public Long doInRedis(RedisConnection redisConnection) throws 

                DataAccessException {

                    try {

                        CountDownLatch latch = new CountDownLatch(1);

                        // subscribe立马返回,是否订阅完毕,异步触发

                        redisConnection.subscribe((message, pattern) -> {

                            // 收到消息,不管结果,立刻再次抢锁

                            latch.countDown();

                          }, ("release_lock_" + resourceName).getBytes());

                        //等待有通知,才继续循环

                        latch.await(timeout, TimeUnit.SECONDS);

                    } catch (InterruptedException e) {

                        e.printStackTrace();

                    }

                    return 0L;

                }

            });

        }

    } finally {

        lock.unlock();

    }

}
@Override

public void lockInterruptibly() throws InterruptedException { }

@Override

public boolean tryLock() {

    // set命令,往redis存放锁的标记

    Boolean lockResult = stringRedisTemplate.execute(new RedisCallback<Boolean>() {

        @Override

        public Boolean doInRedis(RedisConnection redisConnection) throws DataAccessException {

            String value = "";

            Boolean result = redisConnection.set(resourceName.getBytes(),

                    value.getBytes(),

                    Expiration.seconds(timeout),

                    RedisStringCommands.SetOption.SET_IF_ABSENT

            );

            return result;

        }

    });

    return lockResult;

}

@Override

public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {

    return false;

}

@Override

public void unlock() {

    stringRedisTemplate.delete(resourceName);

    //通过Redis发布订阅机制,发送一个通知给其他等待的请求

    stringRedisTemplate.execute(new RedisCallback<Long>() {

        @Override

        public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {

            return redisConnection.publish(("release_lock_" + resourceName).getBytes(), resourceName.getBytes());

        }

    });

}

@Override

public Condition newCondition() {

    return null;

}

}

相关文章

  • 基于redis的分布式锁

    分布式锁实现方案 基于数据库实现分布式锁 基于缓存(redis,memcached,tair)实现分布式锁 基于Z...

  • 大佬浅谈分布式锁

    redis 实现 redis 分布锁一、redis 实现分布式锁(可重入锁)redission 实现分布式锁1、对...

  • zookeeper 锁

    常见的分布式锁实现方案里面,除了使用redis来实现之外,使用zookeeper也可以实现分布式锁。关于 redi...

  • 分布式锁的实现方案

    一,分布式锁的实现方案 1,基于数据库实现分布式锁 2,基于缓存实现数据库锁(redis) 3,基于zookeep...

  • Zookeeper实现分布式锁(一)While版

    前面文章讲解了用Redis实现分布式锁的方式: 分布式锁之Redis实现(acquire)分布式锁之Redis实现...

  • 基于redis实现的分布式锁

    本文要点 基于redis实现分布式锁demo 基于redis实现分布式锁原理 基于redis实现分布式锁优缺点 正...

  • Redis分布式锁

    Redis之分布式锁的实现方案 - 如何优雅地实现分布式锁(JAVA)博客地址 https://blog.piao...

  • Redis、Zookeeper实现分布式锁——原理与实践

    Redis与分布式锁的问题已经是老生常谈了,本文尝试总结一些Redis、Zookeeper实现分布式锁的常用方案,...

  • 主流分布式锁实现方案

    谈到分布式系统,就不得不谈谈分布式锁。而主流的实现java分布式锁实现方案也就那么几种,有基于Redis实现的,也...

  • 分布式锁

    针对分布式锁的实现,目前比较常用的有以下几种方案: 基于数据库实现分布式锁 基于缓存(redis,memcache...

网友评论

    本文标题:分布式锁实现方案-Redis

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