iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >怎么在SpringBoot中使用Redis实现分布式锁
  • 817
分享到

怎么在SpringBoot中使用Redis实现分布式锁

2023-07-05 18:07:27 817人浏览 安东尼
摘要

这篇文章主要介绍了怎么在SpringBoot中使用Redis实现分布式锁的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么在springBoot中使用Redis实现分布式锁文章都会有所收获,下面我们一起来看看吧

这篇文章主要介绍了怎么在SpringBoot中使用Redis实现分布式的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么在springBoot中使用Redis实现分布式锁文章都会有所收获,下面我们一起来看看吧。

一、Redis实现分布式锁原理

为什么需要分布式锁

在聊分布式锁之前,有必要先解释一下,为什么需要分布式锁

与分布式锁相对就的是单机锁,我们在写多线程程序时,避免同时操作一个共享变量产生数据问题,通常会使用一把锁来互斥以保证共享变量的正确性,其使用范围是在同一个进程中。如果换做是多个进程,需要同时操作一个共享资源,如何互斥呢?现在的业务应用通常是微服务架构,这也意味着一个应用会部署多个进程,多个进程如果需要修改MySQL中的同一行记录,为了避免操作乱序导致脏数据,此时就需要引入分布式锁了。

怎么在SpringBoot中使用Redis实现分布式锁

想要实现分布式锁,必须借助一个外部系统,所有进程都去这个系统上申请加锁。而这个外部系统,必须要实现互斥能力,即两个请求同时进来,只会给一个进程加锁成功,另一个失败。这个外部系统可以是数据库,也可以是Redis或ZooKeeper,但为了追求性能,我们通常会选择使用Redis或Zookeeper来做。

Redis本身可以被多个客户端共享访问,正好就是一个共享存储系统,可以用来保存分布式锁。而且 Redis 的读写性能高,可以应对高并发的锁操作场景。本文主要探讨如何基于Redis实现分布式锁以及实现过程中可能面临的问题。

分布式锁如何实现

作为分布式锁实现过程中的共享存储系统,Redis可以使用键值对来保存锁变量,在接收和处理不同客户端发送的加锁和释放锁的操作请求。那么,键值对的键和值具体是怎么定的呢?我们要赋予锁变量一个变量名,把这个变量名作为键值对的键,而锁变量的值,则是键值对的值,这样一来,Redis就能保存锁变量了,客户端也就可以通过Redis的命令操作来实现锁操作。

想要实现分布式锁,必须要求Redis有互斥的能力。可以使用SETNX命令,其含义是SET IF NOT EXIST,即如果key不存在,才会设置它的值,否则什么也不做。两个客户端进程可以执行这个命令,达到互斥,就可以实现一个分布式锁。

以下展示了Redis使用key/value对保存锁变量,以及两个客户端同时请求加锁的操作过程。

怎么在SpringBoot中使用Redis实现分布式锁

加锁操作完成后,加锁成功的客户端,就可以去操作共享资源,例如,修改Mysql的某一行数据。操作完成后,还要及时释放锁,给后来者让出操作共享资源的机会。如何释放锁呢?直接使用DEL命令删除这个key即可。这个逻辑非常简单,整体的流程写成伪代码就是下面这样。

// 加锁SETNX lock_key 1// 业务逻辑DO THINGS// 释放锁DEL lock_key

但是,以上实现存在一个很大的问题,当客户端1拿到锁后,如果发生下面的场景,就会造成死锁。

程序处理业务逻辑异常,没及时释放锁进程挂了,没机会释放锁

以上情况会导致已经获得锁的客户端一直占用锁,其他客户端永远无法获取到锁。

如何避免死锁

为了解决以上死锁问题,最容易想到的方案是在申请锁时,在Redis中实现时,给锁设置一个过期时间,假设操作共享资源的时间不会超过10s,那么加锁时,给这个key设置10s过期即可。

但以上操作还是有问题,加锁、设置过期时间是2条命令,有可能只执行了第一条,第二条却执行失败,例如:

SETNX执行成功,执行EXPIRE时由于网络问题,执行失败
2.SETNX执行成功,Redis异常宕机,EXPIRE没有机会执行
3.SETNX执行成功,客户端异常崩溃,EXPIRE没有机会执行

总之这两条命令如果不能保证是原子操作,就有潜在的风险导致过期时间设置失败,依旧有可能发生死锁问题。幸好在Redis 2.6.12之后,Redis扩展了SET命令的参数,可以在SET的同时指定EXPIRE时间,这条操作是原子的,例如以下命令是设置锁的过期时间为10秒。

SET lock_key 1 EX 10 NX

至此,解决了死锁问题,但还是有其他问题。想像下面这个这样一种场景:

怎么在SpringBoot中使用Redis实现分布式锁

  1. 客户端1加锁成功,开始操作共享资源

  2. 客户端1操作共享资源耗时太久,超过了锁的过期时间,锁失效(锁被自动释放)

  3. 客户端2加锁成功,开始操作共享资源

  4. 客户端1操作共享资源完成,在finally块中手动释放锁,但此时它释放的是客户端2的锁。

这里存在两个严重的问题:

  • 锁过期

  • 释放了别人的锁

第1个问题是评估操作共享资源的时间不准确导致的,如果只是一味增大过期时间,只能缓解问题降低出现问题的概率,依旧无法彻底解决问题。原因在于客户端在拿到锁之后,在操作共享资源时,遇到的场景是很复杂的,既然是预估的时间,也只能是大致的计算,不可能覆盖所有导致耗时变长的场景

第2个问题是释放了别人的锁,原因在于释放锁的操作是无脑操作,并没有检查这把锁的归属,这样解锁不严谨。如何解决呢?

锁被别人给释放了

解决办法是,客户端在加锁时,设置一个只有自己知道的唯一标识进去,例如可以是自己的线程ID,如果是redis实现,就是SET key unique_value EX 10 NX。之后在释放锁时,要先判断这把锁是否归自己持有,只有是自己的才能释放它。

//释放锁 比较unique_value是否相等,避免误释放if redis.get("key") == unique_value then    return redis.del("key")

这里释放锁使用的是GET + DEL两条命令,这时又会遇到原子性问题了。

  1. 客户端1执行GET,判断锁是自己的

  2. 客户端2执行了SET命令,强制获取到锁(虽然发生概念很低,但要严谨考虑锁的安全性)

  3. 客户端1执行DEL,却释放了客户端2的锁

由此可见,以上GET + DEL两个命令还是必须原子的执行才行。怎样原子执行两条命令呢?答案是lua脚本,可以把以上逻辑写成Lua脚本,让Redis执行。因为Redis处理每个请求是单线程执行的,在执行一个Lua脚本时其它请求必须等待,直到这个Lua脚本处理完成,这样一来GET+DEL之间就不会有其他命令执行了。

以下是使用Lua脚本(unlock.script)实现的释放锁操作的伪代码,其中,KEYS[1]表示lock_key,ARGV[1]是当前客户端的唯一标识,这两个值都是我们在执行 Lua脚本时作为参数传入的。

//Lua脚本语言,释放锁 比较unique_value是否相等,避免误释放if redis.call("get",KEYS[1]) == ARGV[1] then    return redis.call("del",KEYS[1])else    return 0end

最后我们执行以下命令,即可

redis-cli  --eval  unlock.script lock_key , unique_value

这样一路优先下来,整个加锁、解锁流程就更严谨了,先小结一下,基于Redis实现的分布式锁,一个严谨的流程如下:

  1. 加锁时要设置过期时间SET lock_key unique_value EX expire_time NX

  2. 操作共享资源

  3. 释放锁:Lua脚本,先GET判断锁是否归属自己,再DEL释放锁

有了这个严谨的锁模型,我们还需要重新思考之前的那个问题,锁的过期时间不好评估怎么办。

如何确定锁的过期时间

前面提到过,过期时间如果评估得不好,这个锁就会有提前过期的风险,一种妥协的解决方案是,尽量冗余过期时间,降低锁提前过期的概率,但这个方案并不能完美解决问题。是否可以设置这样的方案,加锁时,先设置一个预估的过期时间,然后开启一个守护线程,定时去检测这个锁的失效时间,如果锁快要过期了,操作共享资源还未完成,那么就自动对锁进行续期,重新设置过期时间

这是一种比较好的方案,已经有一个库把这些工作都封装好了,它就是Redisson。Redisson是一个Java语言实现的Redis SDK客户端,在使用分布式锁时,它就采用了自动续期的方案来避免锁过期,这个守护线程我们一般叫它看门狗线程。这个SDK提供的api非常友好,它可以像操作本地锁一样操作分布式锁。客户端一旦加锁成功,就会启动一个watch dog看门狗线程,它是一个后台线程,会每隔一段时间(这段时间的长度与设置的锁的过期时间有关)检查一下,如果检查时客户端还持有锁key(也就是说还在操作共享资源),那么就会延长锁key的生存时间。

怎么在SpringBoot中使用Redis实现分布式锁

那如果客户端在加锁成功后就宕机了呢?宕机了那么看门狗任务就不存在了,也就无法为锁续期了,锁到期自动失效。

Redis的部署方式对锁的影响

上面讨论的情况,都是锁在单个Redis 实例中可能产生的问题,并没有涉及到Redis的部署架构细节。

Redis发展到现在,几种常见的部署架构有:

  • 单机模式;

  • 主从模式;

  • 哨兵(sentinel)模式;

  • 集群模式;

我们使用Redis时,一般会采用主从集群+哨兵的模式部署,哨兵的作用就是监测redis节点的运行状态。普通的主从模式,当master崩溃时,需要手动切换让slave成为master,使用主从+哨兵结合的好处在于,当master异常宕机时,哨兵可以实现故障自动切换,把slave提升为新的master,继续提供服务,以此保证可用性。那么当主从发生切换时,分布式锁依旧安全吗?

怎么在SpringBoot中使用Redis实现分布式锁

想像这样的场景:

  1. 客户端1在master上执行SET命令,加锁成功

  2. 此时,master异常宕机,SET命令还未同步到slave上(主从复制是异步的)

  3. 哨兵将slave提升为新的master,但这个锁在新的master上丢失了,导致客户端2来加锁成功了,两个客户端共同操作共享资源

可见,当引入Redis副本后,分布式锁还是可能受到影响。即使Redis通过sentinel保证高可用,如果这个master节点由于某些原因发生了主从切换,那么就会出现锁丢失的情况。

集群模式+Redlock实现高可靠的分布式锁

为了避免Redis实例故障而导致的锁无法工作的问题,Redis的开发者 Antirez提出了分布式锁算法Redlock。Redlock算法的基本思路,是让客户端和多个独立的Redis实例依次请求加锁,如果客户端能够和半数以上的实例成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁了,否则加锁失败。这样一来,即使有单个Redis实例发生故障,因为锁变量在其它实例上也有保存,所以,客户端仍然可以正常地进行锁操作,锁变量并不会丢失。

来具体看下Redlock算法的执行步骤。Redlock算法的实现要求Redis采用集群部署模式,无哨兵节点,需要有N个独立的Redis实例(官方推荐至少5个实例)。接下来,我们可以分成3步来完成加锁操作。

怎么在SpringBoot中使用Redis实现分布式锁

第一步是,客户端获取当前时间。

第二步是,客户端按顺序依次向N个Redis实例执行加锁操作。

这里的加锁操作和在单实例上执行的加锁操作一样,使用SET命令,带上NX、EX/PX选项,以及带上客户端的唯一标识。当然,如果某个Redis实例发生故障了,为了保证在这种情况下,Redlock算法能够继续运行,我们需要给加锁操作设置一个超时时间。如果客户端在和一个Redis实例请求加锁时,一直到超时都没有成功,那么此时,客户端会和下一个Redis实例继续请求加锁。加锁操作的超时时间需要远远地小于锁的有效时间,一般也就是设置为几十毫秒。

第三步是,一旦客户端完成了和所有Redis实例的加锁操作,客户端就要计算整个加锁过程的总耗时。

客户端只有在满足两个条件时,才能认为是加锁成功,条件一是客户端从超过半数(大于等于 N/2+1)的Redis实例上成功获取到了锁;条件二是客户端获取锁的总耗时没有超过锁的有效时间。

为什么大多数实例加锁成功才能算成功呢?多个Redis实例一起来用,其实就组成了一个分布式系统。在分布式系统中总会出现异常节点,所以在谈论分布式系统时,需要考虑异常节点达到多少个,也依旧不影响整个系统的正确运行。这是一个分布式系统的容错问题,这个问题的结论是:如果只存在故障节点,只要大多数节点正常,那么整个系统依旧可以提供正确服务。

在满足了这两个条件后,我们需要重新计算这把锁的有效时间,计算的结果是锁的最初有效时间减去客户端为获取锁的总耗时。如果锁的有效时间已经来不及完成共享数据的操作了,我们可以释放锁,以免出现还没完成共享资源操作,锁就过期了的情况

当然,如果客户端在和所有实例执行完加锁操作后,没能同时满足这两个条件,那么,客户端就要向所有Redis节点发起释放锁的操作。为什么释放锁,要操作所有的节点呢,不能只操作那些加锁成功的节点吗?因为在某一个Redis节点加锁时,可能因为网络原因导致加锁失败,例如一个客户端在一个Redis实例上加锁成功,但在读取响应结果时由于网络问题导致读取失败,那这把锁其实已经在Redis上加锁成功了。所以释放锁时,不管之前有没有加锁成功,需要释放所有节点上的锁以保证清理节点上的残留的锁

在Redlock算法中,释放锁的操作和在单实例上释放锁的操作一样,只要执行释放锁的 Lua脚本就可以了。这样一来,只要N个Redis实例中的半数以上实例能正常工作,就能保证分布式锁的正常工作了。所以,在实际的业务应用中,如果你想要提升分布式锁的可靠性,就可以通过Redlock算法来实现。

二、代码实现Redis分布式锁

1.SpringBoot整合redis用到最多的当然属于我们的老朋友RedisTemplate,pom依赖如下:

<!-- springboot整合redis --><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-redis</artifactId></dependency>

2.Redis配置类:

package com.example.redisdemo.config;import com.fasterxml.jackson.annotation.JSONAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.Jackson2jsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configurationpublic class RedisConfig {    @Bean    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {        // 设置序列化        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);        ObjectMapper om = new ObjectMapper();        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);        om.configure(DeserializationFeature.FaiL_ON_UNKNOWN_PROPERTIES, false);        jackson2JsonRedisSerializer.setObjectMapper(om);        // 配置redisTemplate        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();        redisTemplate.setConnectionFactory(lettuceConnectionFactory);        RedisSerializer<?> stringSerializer = new StringRedisSerializer();        redisTemplate.seTKEySerializer(stringSerializer);// key序列化        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);// value序列化        redisTemplate.setHashKeySerializer(stringSerializer);// Hash key序列化        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);// Hash value序列化        redisTemplate.afterPropertiesSet();        return redisTemplate;    }}

3.Service层面

package com.example.redisdemo.service;import com.example.redisdemo.entity.CustomerBalance;import java.util.concurrent.Callable;public interface RedisService {    <T> T callWithLock(CustomerBalance customerBalance, Callable<T> callable) throws Exception;}
package com.example.redisdemo.service.impl;import com.example.redisdemo.entity.CustomerBalance;import com.example.redisdemo.service.RedisService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.connection.RedisStrinGCommands;import org.springframework.data.redis.connection.ReturnType;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.types.Expiration;import org.springframework.stereotype.Service;import java.NIO.charset.StandardCharsets;import java.util.UUID;import java.util.concurrent.Callable;import java.util.concurrent.TimeUnit;@Service@Slf4jpublic class RedisServiceImpl implements RedisService {    //设置默认过期时间    private final static int DEFAULT_LOCK_EXPIRY_TIME = 20;    //自定义lock key前缀    private final static String LOCK_PREFIX = "LOCK:CUSTOMER_BALANCE";    @Autowired    private RedisTemplate redisTemplate;    @Override    public <T> T callWithLock(CustomerBalance customerBalance, Callable<T> callable) throws Exception{        //自定义lock key        String lockKey = getLockKey(customerBalance.getCustomerNumber(), customerBalance.getSubAccountNumber(), customerBalance.getCurrencyCode());        //将UUID当做value,确保唯一性        String lockReference = UUID.randomUUID().toString();        try {            if (!lock(lockKey, lockReference, DEFAULT_LOCK_EXPIRY_TIME, TimeUnit.SECONDS)) {                throw new Exception("lock加锁失败");            }            return callable.call();        } finally {            unlock(lockKey, lockReference);        }    }    //定义lock key    String getLockKey(String customerNumber, String subAccountNumber, String currencyCode) {        return String.fORMat("%s:%s:%s:%s", LOCK_PREFIX, customerNumber, subAccountNumber, currencyCode);    }    //redis加锁    private boolean lock(String key, String value, long timeout, TimeUnit timeUnit) {        Boolean locked;        try {            //SET_IF_ABSENT --> NX: Only set the key if it does not already exist.            //SET_IF_PRESENT --> XX: Only set the key if it already exist.            locked = (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection ->                    connection.set(key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8),                            Expiration.from(timeout, timeUnit), RedisStringCommands.SetOption.SET_IF_ABSENT));        } catch (Exception e) {            log.error("Lock failed for redis key: {}, value: {}", key, value);            locked = false;        }        return locked != null && locked;    }    //redis解锁    private boolean unlock(String key, String value) {        try {            //使用lua脚本保证删除的原子性,确保解锁            String script = "if redis.call('get', KEYS[1]) == ARGV[1] " +                            "then return redis.call('del', KEYS[1]) " +                            "else return 0 end";            Boolean unlockState = (Boolean) redisTemplate.execute((RedisCallback<Boolean>) connection ->                    connection.eval(script.getBytes(), ReturnType.BOOLEAN, 1,                            key.getBytes(StandardCharsets.UTF_8), value.getBytes(StandardCharsets.UTF_8)));            return unlockState == null || !unlockState;        } catch (Exception e) {            log.error("unLock failed for redis key: {}, value: {}", key, value);            return false;        }    }}

4.业务调用实现分布式锁示例:

    @Override    public int updateById(CustomerBalance customerBalance) throws Exception {        return redisService.callWithLock(customerBalance, ()-> customerBalanceMapper.updateById(customerBalance));    }

关于“怎么在SpringBoot中使用Redis实现分布式锁”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“怎么在SpringBoot中使用Redis实现分布式锁”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

--结束END--

本文标题: 怎么在SpringBoot中使用Redis实现分布式锁

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

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

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

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

下载Word文档
猜你喜欢
  • 怎么在SpringBoot中使用Redis实现分布式锁
    这篇文章主要介绍了怎么在SpringBoot中使用Redis实现分布式锁的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么在SpringBoot中使用Redis实现分布式锁文章都会有所收获,下面我们一起来看看吧...
    99+
    2023-07-05
  • 怎么在Java中使用redis实现分布式锁
    本篇文章给大家分享的是有关怎么在Java中使用redis实现分布式锁,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。原理剖析上述三种分布式锁都是通过各自为依据对各个请求进行上锁,...
    99+
    2023-06-15
  • Java中怎么使用Redis实现分布式锁
    这篇“Java中怎么使用Redis实现分布式锁”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇...
    99+
    2023-05-25
    java redis
  • SpringBoot之如何使用Redis实现分布式锁
    小编给大家分享一下SpringBoot之如何使用Redis实现分布式锁,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!springboot是什么springboot一种全新的编程规范,其设计目的是用来简化新Spring应用的...
    99+
    2023-06-14
  • SpringBoot+Redis如何实现分布式锁
    这篇文章主要介绍了SpringBoot+Redis如何实现分布式锁,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。jedis的nx生成锁 如何删除锁 模拟抢...
    99+
    2023-06-16
  • java怎么使用redis实现分布式锁
    在Java中使用Redis实现分布式锁可以通过以下步骤:1. 引入Redis相关的依赖,例如Jedis或Lettuce。2. 创建一...
    99+
    2023-10-09
    java redis
  • Redis中怎么实现分布式锁
    本篇内容介绍了“Redis中怎么实现分布式锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!为什么需要分布式...
    99+
    2024-04-02
  • 怎么用Redis实现分布式锁
    本文小编为大家详细介绍“怎么用Redis实现分布式锁”,内容详细,步骤清晰,细节处理妥当,希望这篇“怎么用Redis实现分布式锁”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。单机...
    99+
    2024-04-02
  • Redis怎么实现分布式锁
    这篇文章主要介绍“Redis怎么实现分布式锁”,在日常操作中,相信很多人在Redis怎么实现分布式锁问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis怎么实现分布式锁”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-02
  • Redis分布式锁怎么实现
    这篇文章给大家分享的是有关Redis分布式锁怎么实现的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。分布式锁一般有三种实现方式:1、数据库乐观锁;2、基于Redis的分布式锁;3、...
    99+
    2024-04-02
  • Redisson中怎么实现Redis分布式锁
    Redisson中怎么实现Redis分布式锁,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。Redis几种架构Redis发展到现在,几种常见的部署架构有:单机模式;主从模式;...
    99+
    2023-06-20
  • 如何在Redis中实现分布式锁
    在Redis中实现分布式锁可以通过以下方式: 使用SETNX命令:在Redis中可以使用SETNX命令(SET if Not e...
    99+
    2024-04-09
    Redis
  • SpringBoot之使用Redis实现分布式锁(秒杀系统)
    目录一、Redis分布式锁概念篇1.1、为什么要使用分布式锁1.2、分布式锁应具备哪些条件1.3、分布式锁的三种实现方式二、Redis分布式锁实战篇2.1、导入依赖2.2、配置Red...
    99+
    2024-04-02
  • 怎么用Go+Redis实现分布式锁
    这篇文章主要介绍怎么用Go+Redis实现分布式锁,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!为什么需要分布式锁用户下单锁住 uid,防止重复下单。库存扣减锁住库存,防止超卖。余额扣减锁住账户,防止并发操作。分布式...
    99+
    2023-06-22
  • SpringBoot利用注解来实现Redis分布式锁
    目录一、业务背景二、分析流程加锁超时问题解决方案:增加一个「续时」三、设计方案四、实操相关属性类配置核心切面拦截的操作五、开始测试六、总结一、业务背景 有些业务请求,属于耗时操作,需...
    99+
    2024-04-02
  • 怎么用springboot+zookeeper实现分布式锁
    本篇内容主要讲解“怎么用springboot+zookeeper实现分布式锁”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用springboot+zookeeper实现分布式锁”吧!Inte...
    99+
    2023-06-29
  • 怎么使用redis分布式锁
    本篇内容介绍了“怎么使用redis分布式锁”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. redis在实际的应用中不仅可以用来缓存数据,...
    99+
    2023-06-25
  • Redis中怎么利用Redlock实现分布式锁
    Redis中怎么利用Redlock实现分布式锁,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。普通实现说道Redis分布式锁大部分人都会想到:setnx+lua,或者知道se...
    99+
    2023-06-20
  • redis分布式锁怎么使用
    使用Redis分布式锁的一般步骤如下: 获取锁:在Redis中使用SET命令尝试设置一个带有过期时间的键值对作为锁。可以使用命令...
    99+
    2023-10-21
    redis
  • Redis——》实现分布式锁
    推荐链接:     总结——》【Java】     总结——》【Mysql】     总结——》【Redis】     总结——》【Kafka】     总结——》【Spring】     总结—...
    99+
    2023-09-03
    redis 分布式 过期 lua
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作