广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Redis如何实现分布式锁详解
  • 560
分享到

Redis如何实现分布式锁详解

2024-04-02 19:04:59 560人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

目录一、前言二、实现原理2.1 加锁2.2 解锁三、通过RedisTemplate实现分布式锁四、通过Redisson实现一、前言 在Java的并发编程中,我们通过锁,来避免由于竞争

一、前言

在Java的并发编程中,我们通过锁,来避免由于竞争而造成的数据不一致问题。通常,我们以synchronized 、Lock来使用它。

但是Java中的锁,只能保证在同一个JVM进程内中执行。如果在分布式集群环境下,就需要分布式锁了。

通常的分布式锁的实现方式有redis,ZooKeeper,但是一般我们的程序中都会用到redis,用redis做分布式锁,也能够降低成本。

二、实现原理

2.1 加锁

加锁实际上就是在redis中,给Key键设置一个值,为避免死锁,并给定一个过期时间。

在Redis 2.6.12以及之前,可以通过setnx key value (key不存在才设置成功)设置值,通过expire key seconds设置过期时间。但是由于是两个命令,不是原子的。如果在设置值之后还没有来得及设置过期时间,程序挂掉了,那么这个key就永远的存在redis中了。

在Redis 2.6.12之后,redis提供了set key value EX seconds NX 和set key value PX millisecond NX  来原子性的设置值和设置过期时间。

2.2 解锁

解锁的过程就是将Key键删除。但也不能乱删,不能说客户端1的请求将客户端2的锁给删除掉,在删除前需要判断是不是设置的value,如果是才删除。

为了保证解锁操作的原子性,我们用lua脚本完成这一操作。先判断当前锁的字符串是否与传入的值相等,是的话就删除Key,解锁成功。LUA脚本如下:


if redis.call('get',KEYS[1]) == ARGV[1] then
   return redis.call('del',KEYS[1])
else
   return 0
end

三、通过RedisTemplate实现分布式锁

我们通过SpringBoot构建的应用程序一般都是用RedisTemplate来操作缓存redis。下面介绍基于RedisTemplate来实现分布式锁。


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
 
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
 
@Service
@Slf4j
public class RedisLockUtil {
 
    @Autowired
    private RedisTemplate redisTemplate;
 
    //获取锁超时时间
    private long timeout = 60000;
 
    
    public Boolean getLock(String key, String value, Long ms) {
        long startTime = System.currentTimeMillis();
        while (true) {
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, value, ms, TimeUnit.MILLISECONDS);
            if (flag) {
                return true;
            }
 
            //避免一直无限获取锁
            if (System.currentTimeMillis() - startTime > timeout) {
                return false;
            }
 
            try {
                log.info("{}重试锁", key);
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
 
    
    public Boolean unLock(String key, String value) {
        String script =
                "if redis.call('get',KEYS[1]) == ARGV[1] then" +
                        "   return redis.call('del',KEYS[1]) " +
                        "else" +
                        "   return 0 " +
                        "end";
 
        // 构造RedisScript并指定返回类类型
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        // 参数一:redisScript,参数二:key列表,参数三:arg(可多个)
        Object result = redisTemplate.execute(redisScript, Arrays.asList(key), value);
 
        return "1".equals(result.toString());
    }
}

四、通过Redisson实现

Redisson为我们封装了细节,可以开箱即用。

引入maven依赖:


<dependency>
	<groupId>org.redisson</groupId>
	<artifactId>redisson</artifactId>
	<version>3.14.0</version>
</dependency>

配置类:


import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 

@Configuration
@Data
public class RedissonConfig {
 
    @Value("${spring.redis.host}")
    private String host;
 
    @Value("${spring.redis.port}")
    private String port;
 
    @Value("${spring.redis.passWord}")
    private String password;
 
    @Bean
    public RedissonClient getRedisson(){
 
        Config config = new Config();
        config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
        //添加主从配置
//        config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"",""});
 
        return Redisson.create(config);
    }
}

redis属性配置:


spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: root

封装的加锁解锁工具类:


import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.util.concurrent.TimeUnit;
 

@Component
public class RedissLockUtil {
 
    @Autowired
    private RedissonClient redissonClient;
    
 
    
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }
 
    
    public  void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.unlock();
    }
    
    
    public void unlock(RLock lock) {
        lock.unlock();
    }
 
    
    public RLock lock(String lockKey, int timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, TimeUnit.SECONDS);
        return lock;
    }
    
    
    public RLock lock(String lockKey, TimeUnit unit , int timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock(timeout, unit);
        return lock;
    }
    
    
    public boolean tryLock(String lockKey, int waitTime, int leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }
    
    
    public boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime, leaseTime, unit);
        } catch (InterruptedException e) {
            return false;
        }
    }
}

到此这篇关于Redis如何实现分布式锁详解的文章就介绍到这了,更多相关Redis分布式锁内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Redis如何实现分布式锁详解

本文链接: https://www.lsjlt.com/news/127312.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 详解redis如何实现分布式锁
    小编这次要给大家分享的是详解redis如何实现分布式锁,文章内容丰富,感兴趣的小伙伴可以来了解一下,希望大家阅读完这篇文章之后能够有所收获。前言系统的不断扩大,分布式锁是最基本的保障。与单机的多线程不一样的...
    99+
    2022-10-18
  • Redis如何实现分布式锁详解
    目录一、前言二、实现原理2.1 加锁2.2 解锁三、通过RedisTemplate实现分布式锁四、通过Redisson实现一、前言 在Java的并发编程中,我们通过锁,来避免由于竞争...
    99+
    2022-11-12
  • Redis实现分布式锁详解
    目录一、前言为什么需要分布式锁?二、基于Redis实现分布式锁为什么redis可以实现分布式锁?如何实现?锁的获取锁的释放三、如何避免死锁?锁的过期时间如何设置?避免死锁锁过期处理释放其他服务的锁如何处理呢?那么redi...
    99+
    2023-04-09
    Redis实现分布式锁 Redis分布式锁
  • redis实现分布式锁实例详解
    目录1、业务场景引入2、基础环境准备2.1.准备库存数据库2.2.创建SpringBoot工程,pom.xml中导入依赖,请注意版本。2.3.application.properti...
    99+
    2022-11-13
  • 详解基于redis实现分布式锁
    目录前言原理剖析实现编写注解拦截器拦截上述提及工具问题分析前言 为了保证一个在高并发存场景下只能被同一个线程操作,java并发处理提供ReentrantLock或Synchroniz...
    99+
    2022-11-12
  • redis分布式锁的实现原理详解
    首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 1.互斥性。在任意时刻,只有一个客户端能持有锁。 2.不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有...
    99+
    2022-11-13
  • 一文详解如何使用Redis实现分布式锁
    目录1. 什么是分布式锁2. 使用Redis实现分布式锁2.1 加锁2.2 释放锁2.3 给锁设置有效期2.4 给锁设置唯一值2.5 通过Lua脚本实现释放锁的原子性3. 小结1. 什么是分布式锁 当我们在编写多线程代码...
    99+
    2022-09-06
  • Redis如何实现分布式锁
    目录一、前言二、正文今天我们来聊一聊分布式锁的那些事。 相信大家对锁已经不陌生了,我们在多线程环境中,如果需要对同一个资源进行操作,为了避免数据不一致,我们需要在操作共享资源之前进行...
    99+
    2022-11-12
  • Redis分布式锁如何实现
    这篇文章将为大家详细讲解有关Redis分布式锁如何实现,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。什么是分布式锁?要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、...
    99+
    2022-10-18
  • 详解Redis分布式锁的原理与实现
    目录前言使用场景为什么要使用分布式锁如何使用分布式锁流程图分布式锁的状态分布式锁的特点分布式锁的实现方式(以redis分布式锁实现为例)总结前言 在单体应用中,如果我们对共享数据不进行加锁操作,会出现数据一致性问题,我们...
    99+
    2022-06-23
    Redis分布式锁使用 Redis 分布式锁
  • Redis实现分布式锁
    单体锁存在的问题 在单体应用中,如果我们对共享数据不进行加锁操作,多线程操作共享数据时会出现数据一致性问题。 (下述实例是一个简单的下单问题:从redis中获取库存,检查库存是否够,>0才允许下单) 我们的解决办法通常是加锁。如下加单体锁...
    99+
    2023-08-16
    分布式 java jvm
  • Redis——》实现分布式锁
    推荐链接:     总结——》【Java】     总结——》【Mysql】     总结——》【Redis】     总结——》【Kafka】     总结——》【Spring】     总结—...
    99+
    2023-09-03
    redis 分布式 过期 lua
  • Redis实现分布式锁方法详细
    目录1. 单机数据一致性2. 分布式数据一致性3. Redis实现分布式锁3.1 方式一3.2 方式二(改进方式一)3.3 方式三(改进方式二)3.4 方式四(改进方式三)3.5 方...
    99+
    2022-11-12
  • SpringBoot+Redis如何实现分布式锁
    这篇文章主要介绍了SpringBoot+Redis如何实现分布式锁,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。jedis的nx生成锁 如何删除锁 模拟抢...
    99+
    2023-06-16
  • Redis中如何实现分布式锁
    这篇文章给大家介绍Redis中如何实现分布式锁,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Redis要实现分布式锁,以下条件应该得到满足互斥性 在任意时刻,只有一个客户端能持有锁。不能死锁 客户端...
    99+
    2023-06-16
  • Redis实现分布式锁的五种方法详解
    目录1. 单机数据一致性2. 分布式数据一致性3. Redis实现分布式锁3.1 方式一3.2 方式二(改进方式一)3.3 方式三(改进方式二)3.4 方式四(改进方式三)3.5 方式五(改进方式四)3.6 小结在单体应...
    99+
    2022-06-14
    Redis 分布式锁
  • 详解使用Redis SETNX 命令实现分布式锁
    使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法。 SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在。 ...
    99+
    2022-06-04
    分布式 详解 命令
  • PHP+Redis实现分布式锁
    目录 一、分布式锁概述 二、redis实现锁的命令 1、redis实现锁的命令 3、释放锁的步骤 三、PHP+redis分布式锁示例 四、redis集群分布式锁 一、分布式锁概述         在分布式环境下,各个线程通过对公共资...
    99+
    2023-09-15
    分布式锁
  • redis分布式锁的实现
    一、使用分布式锁要满足的几个条件:1、系统是一个分布式系统(关键是分布式,单机的可以使用ReentrantLock或者synchronized代码块来实现)2、共享资源(各个系统访问同一个资源,资源的载体可...
    99+
    2022-10-18
  • Redis Template实现分布式锁
    今天就跟大家聊聊有关Redis Template实现分布式锁,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。可靠性首先,为了确保分布式锁可用,我们至少...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作