分布式锁~

分布式锁

分布式锁是在分布式系统中用于协调多个节点之间对共享资源的访问的一种机制。个人认为实现分布式锁,需要一个中间件例如数据库,redis等等这样的存储锁即可实现分布式锁。

分布式锁实现方案

  1. 基于数据库(唯一索引)

  2. 基于内存(redis,memcache)

  3. zookeeper

数据库

使用数据库的事务特性来实现分布式锁。

通过在数据库中创建一个表,将锁状态存储在表的行中,使用数据库的事务来确保对该行的操作是原子的。当一个节点想要获取锁时,尝试插入一行记录,如果插入成功则获取到锁,否则表示锁已被其他节点持有。

创建数据库表用于存储锁的状态

CREATE TABLE distributed_lock (
    lock_name VARCHAR(255) PRIMARY KEY,
    is_locked BOOLEAN NOT NULL DEFAULT FALSE
);

Java代码实现获取和释放分布式锁

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DistributedLock {

    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/your_database";
    private static final String JDBC_USER = "your_username";
    private static final String JDBC_PASSWORD = "your_password";

    private String lockName;
    private Connection connection;

    public DistributedLock(String lockName) {
        this.lockName = lockName;
        try {
            this.connection = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
        } catch (SQLException e) {
            throw new RuntimeException("Failed to initialize database connection", e);
        }
    }

    public boolean acquireLock() {
        try {
            // Start a transaction
            connection.setAutoCommit(false);

            // Try to insert a new lock record
            try (PreparedStatement insertStatement = connection.prepareStatement(
                    "INSERT INTO distributed_lock (lock_name, is_locked) VALUES (?, TRUE)"
            )) {
                insertStatement.setString(1, lockName);
                int affectedRows = insertStatement.executeUpdate();

                // If affectedRows is 1, the lock is acquired
                if (affectedRows == 1) {
                    connection.commit();
                    return true;
                }
            }

            // If a lock record already exists, it means the lock is held by another process
            connection.rollback();
            return false;
        } catch (SQLException e) {
            try {
                connection.rollback();
            } catch (SQLException rollbackException) {
                // Handle rollback exception
            }
            throw new RuntimeException("Error while acquiring lock", e);
        } finally {
            try {
                connection.setAutoCommit(true);
            } catch (SQLException e) {
                // Handle setAutoCommit exception
            }
        }
    }

    public void releaseLock() {
        try (PreparedStatement deleteStatement = connection.prepareStatement(
                "DELETE FROM distributed_lock WHERE lock_name = ?"
        )) {
            deleteStatement.setString(1, lockName);
            deleteStatement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException("Error while releasing lock", e);
        }
    }

    public void closeConnection() {
        try {
            if (connection != null && !connection.isClosed()) {
                connection.close();
            }
        } catch (SQLException e) {
            // Handle close connection exception
        }
    }
}

基于缓存

这里主要讲基于Redis的分布式锁。

setNX + Lua脚本

在Redis中,你可以使用Lua脚本将SETNX和EXPIRE两个操作打包在一起,从而实现原子性。

local key = KEYS[1]
local value = ARGV[1]
local ttl = ARGV[2]

local lockSet = redis.call('setnx', key, value)
if lockSet == 1 then
    redis.call('expire', key, ttl)
end

return lockSet
  1. 尝试使用SETNX命令设置一个锁。如果锁已经存在,那么SETNX命令会返回0,如果锁不存在,那么SETNX命令会返回1,并且设置锁的值为value
  2. 如果上一步设置锁成功(即SETNX命令返回1),那么使用EXPIRE命令设置锁的过期时间。过期时间是ttl
  3. 最后,返回SETNX命令的结果。如果结果为1,那么表示成功获取到了锁,如果结果为0,那么表示获取锁失败。

客户端调用脚本:

EVAL <lua_script> 1 lock_key lock_value lock_ttl

Redisson + RLock可重入锁

Redisson是一个分布式协调Redis客服端,实现了大部分java环境下分布式对象。

在这里插入图片描述

代码实现:

    Config config = new Config();
	config.useSingleServer().setAddress("redis://ip:6378").setPassword("root");
	Redisson redisson = Redisson.create(config);
	
    // 使用redisson自带的分布式锁
    RLock redisLock = redissonClient.getLock("junfeng");
    if (!redisLock.tryLock()) {
        return Result.fail("禁止重复参与!");
    }
    try {
        IVoucherOrderService proxy = (IVoucherOrderService) AopContext.currentProxy();
        return proxy.createVoucherOrder(voucherId); 
    } finally {
        redisLock.unlock();
    }

redissonLock 比setnx有哪些优势

  • 实现了可重入
  • 锁续约机制
  • 实现多节点保存同一把锁,防止主从不一致问题

基于ZooKeeper

  • 使用ZooKeeper分布式协调服务。
  • 利用ZooKeeper的顺序临时节点(Sequential Ephemeral Node)创建有序节点,确保节点顺序代表获取锁的顺序。
  • 最小的节点代表获取了锁,其他节点监听前一个节点的删除事件。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CMIP6数据处理及在气候变化、水文、生态等领域中的实践技术应用

查看原文>>>最新CMIP6数据处理及在气候变化、水文、生态等领域中的实践技术应用 气候变化对农业、生态系统、社会经济以及人类的生存与发展具有深远影响&#xff0c;是当前全球关注的核心议题之一。IPCC&#xff08;Intergovernmental Panel on Climate Change&#…

太激动了!摄像头终于有画面了!

有了放弃的想法 摄像头APP在我这里好好的&#xff0c;到了老外那里就不能 用。反复试了几套源码&#xff0c;都没有画面。后来干脆把老外说通用的APK反编译后&#xff0c;新做了个APP&#xff0c;结果还是没画面。到了这个时候&#xff0c;我是真的有点沮丧&#xff0c;准备放弃…

七、Nacos和Eureka的区别

一、nacos注册中心 二、临时实例与非临时实例 三、区别 Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式&#xff0c;非临时实例采用主动检测模式临时实例心跳不正常会被剔除&#xff0c;非临时实例则不会被剔除Nacos支持服务列表变更的消息推送模式&#xff0c;服务…

软件外包开发文档需要注意的问题

编写软件开发文档时需要注意以下一些关键问题&#xff0c;以确保文档的质量、有效性和可维护性&#xff0c;通过关注这些问题&#xff0c;您可以确保软件开发文档更容易被理解、使用和维护&#xff0c;从而提高项目的成功几率。北京木奇移动技术有限公司&#xff0c;专业的软件…

3.5-构建自己的Docker镜像

首先介绍两个命令&#xff1a; 1.docker container commit&#xff0c;可以简写为&#xff1a;docker commit。这个命令是把一个修改后的container重新变成一个image。 2.docker image build&#xff0c;可以简写为&#xff1a;docker build 首先&#xff0c;演示一下docker c…

接口中的大事务,该如何进行优化?

作为后端开发的程序员&#xff0c;我们常常会的一些相对比较复杂的逻辑&#xff0c;比如我们需要给前端写一个调用的接口&#xff0c;这个接口需要进行相对比较复杂的业务逻辑操作&#xff0c;比如会进行&#xff0c;查询、远程接口或本地接口调用、更新、插入、计算等一些逻辑…

论文阅读:YOLOV: Making Still Image Object Detectors Great at Video Object Detection

发表时间&#xff1a;2023年3月5日 论文地址&#xff1a;https://arxiv.org/abs/2208.09686 项目地址&#xff1a;https://github.com/YuHengsss/YOLOV 视频物体检测&#xff08;VID&#xff09;具有挑战性&#xff0c;因为物体外观的高度变化以及一些帧的不同恶化。有利的信息…

CSS---关于font文本属性设置样式总结

目录 1、color属性 2、font-size属性 3、font-weight属性 4、font-family属性 5、text-align属性 6、line-height属性 7、text-indent属性 8、letter-spacing属性 9、word-spacing属性 10、word-break属性 11、white-space属性 12、text-transform 12、writing-mo…

Git常用操作-MD

文章目录 1. 本地创建分支&#xff0c;编写代码&#xff0c;提交本地分支到远程仓库2. 提交本地代码到本地仓库3. 提交本地代码到本地dev分支4. 提交本地dev分支到远程仓库5. 本地dev分支拉取远程master分支&#xff0c;并将master分支内容合并到本地dev6. 同义命令7. 撤销上次…

No matching version found for zr-map-ol@1.1.19.

问题描述&#xff1a; 通常情况下直接安装可能还会报错&#xff0c;因为有的依赖包是在私库里的 解决方法&#xff1a; 1.查看模块的注册信息 2. 安装 如果上面这种方式安装之后npm i还是报错&#xff0c;试试下面这种方式(我没有试下面的方式 上面的已经解决掉了) 具体可以参…

人工智能基础_机器学习038_中国人寿保费预测(EDA数据探索)_导包_数据探索_---人工智能工作笔记0078

注意 EDA是Exploratory Data Analysis(探索性数据分析)的缩写,它是一种统计分析方法,旨在了解数据的基本特征,并发现数据中的规律和模式。EDA通常是数据分析流程的开始阶段,主要使用可视化工具和统计指标来描述数据的基本特征,如数据的分布、中位数、均值、方差等。通过…

【前沿学习】美国零信任架构发展现状与趋势研究

转自&#xff1a;美国零信任架构发展现状与趋势研究 摘要 为了应对日趋严峻的网络安全威胁&#xff0c;美国不断加大对零信任架构的研究和应用。自 2022 年以来&#xff0c;美国发布了多个零信任战略和体系架构文件&#xff0c;开展了多项零信任应用项目。在介绍美国零信任战略…

C++初阶(十一)STL简介及string类初讲

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、什么是STL二、STL的版本三、STL的六大组件四、STL的重要性五、如何学习STL六、STL的缺陷七…

802.11ax-2021协议学习__$27-HE-PHY__$27.5-Parameters-for-HE-MCSs

802.11ax-2021协议学习__$27-HE-PHY__$27.5-Parameters-for-HE-MCSs 27.3.7 Modulation and coding scheme (HE-MCSs)27.3.8 HE-SIG-B modulation and coding schemes (HE-SIG-B-MCSs)27.5 Parameters for HE-MCSs27.5.1 General27.5.2 HE-MCSs for 26-tone RU27.5.3 HE-MCSs f…

Git-团队协作工作流

前言 一、工作流概述二、Git flow1.主要流程2.优缺点3.适用场景 三、Github flow1.主要流程2.优缺点3.适用场景 四、Gitlab flow1.主要流程2.优缺点3.适用场景 总结参考 一、工作流概述 开发人员通过Git可以记录和追踪代码的变化&#xff0c;包括添加、删除和修改文件。如果是…

【自动化测试】Appium环境搭建与配置-详细步骤,一篇带你打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、Node.js环境搭…

【Python大数据笔记_day09_hive函数和调优】

hive函数 函数分类标准[重点] 原生分类标准: 内置函数 和 用户定义函数(UDF,UDAF,UDTF) ​ 分类标准扩大化: 本来&#xff0c;UDF 、UDAF、UDTF这3个标准是针对用户自定义函数分类的&#xff1b; 但是&#xff0c;现在可以将这个分类标准扩大到hive中所有的函数&#xff0c;…

MyBatis CURD操作深度解析

文章目录 简单查询操作插入、更新和删除操作selectKey元素的作用结语 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;MyBatis ✨文章内容&#xff1a; CURD操作 &#x1f9…

Alibaba微服务组件Nacos注册中心

1. 什么是 Nacos 官方&#xff1a;一个更易于构建云原生应用的动态 服务发现( Nacos Discovery ) 、 服务配置( Nacos Config ) 和服务管理平台。 集 注册中心配置中心服务管理 平台 Nacos 的关键特性包括: 服务发现和服务健康监测 动态配置服务 动态 DNS 服务 服务及其…

ps5计时计费软件安装教程,佳易王电玩店计时收费系统

ps5计时计费软件安装教程&#xff0c;佳易王电玩店计时收费系统 一、佳易王电玩PS5游戏厅计时计费软件部分功能简介&#xff1a; 1、计时计费功能 &#xff1a;开台时间和所用的时长直观显示&#xff0c;每3秒即可刷新一次时间。 2、销售商品功能 &#xff1a;商品可以绑定桌…