详解SpringBoot分布式锁

一、为什么需要分布式锁?

在分布式系统中,多个节点需要对同一资源进行并发访问和操作。如果没有分布式锁,很容易出现资源竞争问题,引发数据错误或系统崩溃的风险。

例如,假设有两个客户端对订单进行支付,如果没有分布式锁,那么可能会出现一次性支付多次的问题。

分布式锁能够有效地解决这些问题,保证各节点之间数据访问的正确性。

二、SpringBoot分布式锁的实现方式

1. 基于Redis实现分布式锁

Redis相当于开发人员搭建分布式锁的一种途径,在Redis中提供了setnx方法,如果key不存在则设置成功。因此,我们可以在加锁时采用setnx方法,如果设置成功则获取到锁,否则等待。同时,为了消除其他线程在出现竞争时获取锁的等待时间,需使用Redis的Expire命令。


 public boolean lock(String key) {
        long expires = 5 * 60 * 1000;
        long currentValue = System.currentTimeMillis() + expires + 1;
        String currentValueStr = String.valueOf(currentValue);
        if (redisTemplate.opsForValue().setIfAbsent(key, currentValueStr)){
            return true;
        }

        //key 存在,获取值
        String oldValueStr = (String) redisTemplate.opsForValue().get(key);
        if (oldValueStr !=null && Long.parseLong(oldValueStr) < System.currentTimeMillis()){
            // 获取上一个锁到期时间,并设置现在的锁到期时间
            String  getValue = (String) redisTemplate.opsForValue().getAndSet(key, currentValueStr);
            if (getValue !=null && getValue.equals(oldValueStr)){
                return true;
            }
        }
        return false;
    }

2. 基于Zookeeper实现的分布式锁

Zookeeper提供丰富的锁机制,Zookeeper锁节点的特性自动具有排他性质,基于此可以轻松地搭建分布式锁,实现分布式锁的本质就是创建一个znode节点。同样的,当多个线程尝试创建znode时,只会有最先创建的线程创建成功,其他线程创建失败,并进入等待状态。一旦拥有锁的客户端释放了锁,Zookeeper集群中的所有客户端都会被通知,然后再次尝试锁。


public boolean lock(String lockName) {
    if (zookeeper == null) {
        return false;
    }
    String path = "/lock/" + lockName;
    try {
        Stat stat = zookeeper.exists(path, false);
        if (stat == null) {
            // 如果节点不存在,则创建
            zookeeper.create(path, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        }
        return true;
    } catch (KeeperException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return false;
}

三、SpringBoot分布式锁的应用

1. 避免缓存穿透

缓存穿透指查询一个一定不存在的数据,导致这个查询落在数据库上,造成数据库压力过大。可以通过分布式锁来避免缓存穿透的问题。当锁被占用时,其他线程只需要等待锁释放即可,不会重复查询数据库。

2. 避免重复提交

在高并发环境下,重复提交请求会使得服务端创建多个相同的订单,导致数据错误。可以在用户提交订单时,采用分布式锁来避免重复提交。

3. 控制资源访问数量

有时候,我们需要限制并发数,比如短信发送接口,单个用户每次只能发送一个短信。这时可以通过分布式锁来限制并发数,保证接口的正常可用。

四、总结

SpringBoot分布式锁是解决分布式系统资源安全共享和并发操作的一种重要手段。本文从实现方式和应用场景两个方面阐述了SpringBoot分布式锁的实现方法以及常见应用场景。但该方案并非万能之策,我们在实际使用中也需要根据具体情况进行分析,避免误用。

原创文章,作者:MYQDI,如若转载,请注明出处:https://www.506064.com/n/371606.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
MYQDIMYQDI
上一篇 2025-04-23 18:08
下一篇 2025-04-23 18:08

相关推荐

  • KeyDB Java:完美的分布式高速缓存方案

    本文将从以下几个方面对KeyDB Java进行详细阐述:KeyDB Java的特点、安装和配置、使用示例、性能测试。 一、KeyDB Java的特点 KeyDB Java是KeyD…

    编程 2025-04-29
  • 从ga角度解读springboot

    springboot作为目前广受欢迎的Java开发框架,其中的ga机制在整个开发过程中起着至关重要的作用。 一、ga是什么 ga即Group Artifacts的缩写,它是Mave…

    编程 2025-04-29
  • Java Hmily分布式事务解决方案

    分布式系统是现在互联网公司架构中的必备项,但随着业务的不断扩展,分布式事务的问题也日益凸显。为了解决分布式事务问题,Java Hmily分布式事务解决方案应运而生。本文将对Java…

    编程 2025-04-28
  • JL Transaction – 实现分布式事务管理的利器

    本文将为大家介绍JL Transaction,这是一款可以实现分布式事务管理的开源事务框架,它可以帮助企业在分布式环境下有效地解决事务的一致性问题,从而保障系统的稳定性和可靠性。 …

    编程 2025-04-28
  • 使用RPC研发云实现分布式服务交互

    本文将基于RPC研发云,阐述分布式服务交互实现的过程和实现方式。 一、RPC研发云简介 RPC研发云是一种基于分布式架构的服务框架,在处理不同语言之间的通信上变得越来越流行。通过使…

    编程 2025-04-28
  • SpringBoot Get方式请求传参用法介绍

    本文将从以下多个方面对SpringBoot Get方式请求传参做详细的阐述,包括URL传参、路径传参、请求头传参、请求体传参等,帮助读者更加深入地了解Get请求方式下传参的相关知识…

    编程 2025-04-27
  • 分布式文件系统数据分布算法

    数据分布算法是分布式文件系统中的重要技术之一,它能够实现将文件分散存储于各个节点上,提高系统的可靠性和性能。在这篇文章中,我们将从多个方面对分布式文件系统数据分布算法进行详细的阐述…

    编程 2025-04-27
  • SpringBoot如何设置不输出Info日志

    本篇文章将带您了解如何在SpringBoot项目中关闭Info级别日志输出。 一、为什么要关闭Info日志 在开发中,我们经常会使用Log4j、Logback等框架来输出日志信息,…

    编程 2025-04-27
  • 神经网络代码详解

    神经网络作为一种人工智能技术,被广泛应用于语音识别、图像识别、自然语言处理等领域。而神经网络的模型编写,离不开代码。本文将从多个方面详细阐述神经网络模型编写的代码技术。 一、神经网…

    编程 2025-04-25
  • Linux sync详解

    一、sync概述 sync是Linux中一个非常重要的命令,它可以将文件系统缓存中的内容,强制写入磁盘中。在执行sync之前,所有的文件系统更新将不会立即写入磁盘,而是先缓存在内存…

    编程 2025-04-25

发表回复

登录后才能评论