分布式锁实现方案对比与最佳实践

news2025/3/5 6:17:46

目录

  1. 分布式锁的应用场景
  2. 常见的锁实现方案
  3. Redisson实现分布式锁的最佳实践
  4. 方案对比与选择建议

分布式锁的应用场景

在分布式系统中,常常需要控制对共享资源的访问。典型的应用场景包括:

  1. 缓存击穿防护:防止大量请求同时查询数据库
  2. 库存扣减:确保商品库存操作的原子性
  3. 防重复提交:避免表单重复提交
  4. 定时任务互斥:确保定时任务只被一个节点执行

常见的锁实现方案

1. 本地锁 synchronized

public class LocalLockExample {
    public synchronized void doSomething() {
        // 业务逻辑
    }
}

特点:

  • 只能在单机环境下使用
  • JVM级别的锁
  • 无法解决分布式环境下的并发问题

2. 基于Redis的抢占式锁(SET NX + Lua)

public class RedisLockExample {
    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";
    
    /**
     * 尝试获取分布式锁
     */
    public boolean tryLock(String lockKey, String requestId, int expireTime) {
        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, 
                                SET_WITH_EXPIRE_TIME, expireTime);
        return LOCK_SUCCESS.equals(result);
    }
    
    /**
     * 释放分布式锁
     */
    public boolean releaseLock(String lockKey, String requestId) {
        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then " +
                       "return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), 
                                 Collections.singletonList(requestId));
        return Long.valueOf(1L).equals(result);
    }
}

特点:

  • 使用Redis的原子操作实现
  • 需要自己处理锁的超时和续期
  • 可能存在锁超时被释放的问题

3. Redisson分布式锁

public class RedissonLockExample {
    private final RedissonClient redisson;
    
    public void doWithLock() {
        RLock lock = redisson.getLock("myLock");
        try {
            // 尝试加锁,最多等待30秒,锁定后10秒自动解锁
            boolean isLocked = lock.tryLock(30, 10, TimeUnit.SECONDS);
            if (isLocked) {
                // 业务逻辑
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }
}

特点:

  • 实现了可重入锁
  • 支持自动续期(看门狗机制)
  • 提供了丰富的锁类型(公平锁、读写锁等)
  • 实现了跨平台的分布式锁

Redisson实现分布式锁的最佳实践

双重检验机制 + Redisson锁

public class OptimizedRedissonLock {
    private final RedissonClient redisson;
    private final RedisTemplate<String, String> redisTemplate;
    
    public Map<String, Object> getDataWithLock() {
        // 第一次检查缓存
        String cacheData = redisTemplate.opsForValue().get("cacheKey");
        if (!StringUtils.isEmpty(cacheData)) {
            return JSON.parseObject(cacheData);
        }

        // 获取分布式锁
        RLock lock = redisson.getLock("myLock");
        try {
            boolean isLocked = lock.tryLock(30, TimeUnit.SECONDS);
            if (!isLocked) {
                throw new RuntimeException("获取锁失败");
            }
            
            // 第二次检查缓存
            cacheData = redisTemplate.opsForValue().get("cacheKey");
            if (!StringUtils.isEmpty(cacheData)) {
                return JSON.parseObject(cacheData);
            }
            
            // 查询数据库
            Map<String, Object> dbData = queryDatabase();
            
            // 放入缓存
            redisTemplate.opsForValue().set("cacheKey", 
                JSON.toJSONString(dbData), 1, TimeUnit.DAYS);
                
            return dbData;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("获取锁被中断");
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}

看门狗机制说明

Redisson的看门狗机制是一个自动延期机制:

  1. 原理

    • 默认锁的有效期为30秒
    • 如果业务未完成,会自动延长锁的有效期
    • 每隔10秒(默认值)自动续期
  2. 配置方式

Config config = new Config();
config.setLockWatchdogTimeout(30000); // 设置看门狗超时时间,单位:毫秒

方案对比与选择建议

特性synchronizedRedis SET NXRedisson
实现难度简单中等简单
分布式支持不支持支持支持
可重入性支持需自行实现支持
自动续期不需要需自行实现支持
锁超时处理不需要需自行处理自动处理
性能中等中等
可靠性一般

选择建议

  1. 单机应用:使用synchronized即可

  2. 简单分布式场景

    • 性能要求不高
    • 锁定时间短
    • 可以使用Redis SET NX方案
  3. 复杂分布式场景

    • 需要可重入锁
    • 锁定时间不确定
    • 建议使用Redisson

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2309857.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux纯命令行界面下SVN的简单使用教程

诸神缄默不语-个人技术博文与视频目录 我用的VSCode插件是这个&#xff1a; 可以在文件中用色块显示代码修改了什么地方&#xff0c;点击色块还可以显示修改内容。 文章目录 1. SVN安装2. checkout3. update1. 将文件加入版本控制 4. commit5. 查看SVN信息&#xff1a;info6.…

python 初学攻略(上)

废话写在前面&#xff0c;后面都是干货&#xff0c;这个语言教学到处都是。我这里直接给你搞定所有要用的就好了。 环境安装&#xff08;略&#xff09; 输出函数print 转义字符 二进制与字符编码 标识符和保留字 变量的定义和使用 数据类型 整数类型 浮点类型 布尔类型 字符串…

《基于大数据的相州镇新农村商务数据分析与研究》开题报告

目录 一、选题依据 1.选题背景 2.国内外研究现状与水平 &#xff08;1&#xff09;国外研究现状 &#xff08;2&#xff09;国内研究现状 3.发展趋势 4.研究意义 二、研究内容 1.学术构思与思路 &#xff08;1&#xff09;主要研究内容 (2&#xff09;拟解决的关键问…

Linux : 环境变量

目录 一 环境变量 1.基本概念 二 常见环境变量 三 查看环境变量的方法 1.env:查看系统中所有环境变量 2. echo $NAME 四 如何不带路径也能运行的自己的程序 1.将自己的程序直接添加到PATH指定的路径下 五 环境变量与本地变量 1.本地变量 2. 环境变量 六C、C中main()…

SQL-labs13-16闯关记录

http://127.0.0.1/sqli-labs/less-13/ 基于POST单引号双注入变形 1&#xff0c;依然是一个登录框&#xff0c;POST型SQL注入 2&#xff0c;挂上burpsuite&#xff0c;然后抓取请求&#xff0c;构造请求判断漏洞类型和闭合条件 admin 发生了报错&#xff0c;根据提示闭合方式是(…

2025-03-04 学习记录--C/C++-PTA 习题5-4 使用函数求素数和

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>// 函数声明&#xff1a;判断一个数是…

Virtuose 6D TAO HF力反馈系统:加强力遥操作主手

Virtuose 6D TAO是一款搭载六主动自由度的力反馈设备&#xff0c;该产品自带被动式夹持器&#xff0c;工作空间大&#xff0c;可与EtherCAT接口通信&#xff0c;是轻松控制从机械臂的首选产品&#xff0c;特别适合工业遥操作、核工业遥操作等应用。 产品特点 ▪ 六主动自由度、…

使用AI后为什么思考会变得困难?

使用AI后为什么思考会变得困难&#xff1f; 我总结了四篇近期的研究论文&#xff0c;来展示AI是如何以及为什么侵蚀我们的批判性思维能力。 作者使用AI制作的图像 前言&#xff1a;作者在这篇文章中&#xff0c;借AI技术的崛起&#xff0c;揭示了一场悄然发生的思想博弈。表面…

【Resis实战分析】Redis问题导致页面timeout知识点分析

事故现象&#xff1a;前端页面返回timeout 事故回溯总结一句话&#xff1a; &#xff08;1&#xff09;因为大KEY调用量&#xff0c;随着白天自然流量趋势增长而增长&#xff0c;最终在业务高峰最高点期占满带宽使用100%。 &#xfeff; &#xfeff; &#xff08;2&#x…

FlashMLA(DeepSeek开源周,第一个框架):含源码分析

1. 概述 FlashMLA 是由 DeepSeek 原创开发的一种深度学习框架&#xff0c;专门用于加速多头注意力机制&#xff08;MLA&#xff09;架构的推理过程。它通过优化内存管理和计算效率&#xff0c;显著提升了模型在高性能 GPU 上的推理速度。FlashMLA 主要适用于 DeepSeek 的架构模…

点大商城V2-2.6.6.1全能版源码+最新排队免单插件功能

一.介绍 点大商城V2独立开源版本&#xff0c;版本更新至2.6.6&#xff0c;系统支持多端&#xff0c;前端为UNiapp&#xff0c;多端编译。 二.安装环境&#xff1a; Nginx 1.22PHP7.3MySQL 5.7 推荐PHP 7.3&#xff08;不得大于此版本&#xff0c;否则容易出bug&#xff09; …

行为模式---命令模式

概念 命令模式是一种行为设计模式&#xff0c;它的核心思想就是将请求封装为一个对象&#xff0c;此对象包含与请求相关的所有信息。可以用不同的请求对客户进行参数化。命令模式通过将请求的发送者和接收者解耦&#xff0c;支持请求的排队、记录、撤销等操作。 使用场景 1、…

Graph RAG 迎来记忆革命:“海马体”机制让问答更精准!

随着生成式 AI 技术的快速发展,RAG(Retrieval-Augmented Generation)和 Agent 成为企业应用大模型的最直接途径。然而,传统的 RAG 系统在准确性和动态学习能力上存在明显不足,尤其是在处理复杂上下文和关联性任务时表现不佳。近期,一篇论文提出了 HippoRAG 2,这一新型 R…

Linux——基本指令

我们今天学习Linux最基础的指令 ls 指令 语法&#xff1a; ls [选项] [⽬录或⽂件] 功能&#xff1a;对于⽬录&#xff0c;该命令列出该⽬录下的所有⼦⽬录与⽂件。对于⽂件&#xff0c;将列出⽂件名以及其他信 息。 命令中的选项&#xff0c;一次可以传递多个 &#xff0c…

【C++】模板编程入门指南:零基础掌握泛型编程核心(初阶)

文章目录 一、泛型编程二、函数模板1. 函数模板的概念和格式2. 函数模板的原理3. 函数模板的实例化隐式实例化显式实例化 三、类模板 一、泛型编程 泛型编程就是编写与类型无关的通用代码&#xff0c;是代码复用的一种手段&#xff0c;模板是泛型编程的基础&#xff0c;可能不太…

网上打印平台哪个好用?网上打印资料推荐

网上打印平台哪个好用 随着数字化办公的普及&#xff0c;网上打印平台因其便捷性和经济性而受到越来越多人的青睐。无论是学生、上班族还是个人用户&#xff0c;在需要快速打印资料时&#xff0c;一个好用的在线打印服务可以大大节省时间和成本。 那么&#xff0c;如何选择一…

Mac远程桌面软件哪个好用?

远程桌面软件能帮助我们快速的远程控制另一台电脑&#xff0c;从而提供远程帮助&#xff0c;或者进行远程办公。那么&#xff0c;对macOS系统有什么好用的Mac远程桌面软件呢&#xff1f; 远程看看是一款操作简单、界面简洁的远程桌面软件&#xff0c;支持跨平台操作&#xff0…

C#—Settings配置详解

C#—Settings配置详解 在C#项目中&#xff0c;全局配置通常指的是应用程序的设置&#xff08;settings&#xff09;&#xff0c;这些设置可以跨多个类或组件使用&#xff0c;并且通常用于存储应用程序的配置信息&#xff0c;如数据库连接字符串、用户偏好设置等。 Settings配置…

PyCharm中通过命令行执行`pip`命令下载到哪里了:虚拟环境目录下

PyCharm中通过命令行执行pip命令下载到哪里了:虚拟环境目录下 在PyCharm中通过命令行执行pip命令安装工具包,包的下载位置取决于多种因素 虚拟环境 如果项目使用了虚拟环境(通常是推荐的做法): Windows:虚拟环境通常位于项目目录下的.venv文件夹(默认情况)或你指定…

Golang的性能分析指标解读

Golang的性能分析指标解读 一、概述 语言&#xff09;是一种由Google开发的开源编程语言&#xff0c;以其并发性能和高效的编译速度而闻名。对于程序员来说&#xff0c;了解如何对Golang应用程序进行性能分析是非常重要的&#xff0c;因为这能帮助他们发现潜在的性能瓶颈并对其…