深度解析分布式锁及实现方案

news2024/9/17 6:58:10

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

深度解析分布式锁及实现方案

  • 引言
  • 什么是分布式锁?
  • 分布式锁的应用场景
  • 分布式锁的设计原则
  • 分布式锁的实现方案
      • 基于数据库的实现
      • 基于缓存的实现
      • 基于ZooKeeper的实现
  • 分布式锁的注意事项
  • 结语

引言

在分布式系统中,分布式锁是协调多个节点对共享资源进行互斥访问的关键技术。本文将深入研究分布式锁的概念、应用场景,并详细介绍三种常见的实现方案,包括基于数据库、基于缓存(以Redis为例)和基于ZooKeeper的实现。

什么是分布式锁?

分布式锁是一种在分布式系统中实现协同访问共享资源的机制,目的是确保在分布式环境中对共享资源的互斥访问,避免数据不一致性、并发冲突等问题。

分布式锁的应用场景

  • 避免重复任务: 确保在分布式系统中某个任务只被执行一次,防止重复执行。

  • 资源竞争控制: 协调多个节点对共享资源的访问,保证资源访问的互斥性。

  • 分布式事务: 在分布式事务中,用于协调多个参与者对资源的访问,确保事务的一致性。

分布式锁的设计原则

Redis的官网在新窗口打开上对使用分布式锁提出至少需要满足如下三个要求:

  • 互斥(属于安全性):在任何给定时刻,只有一个客户端可以持有锁。
  • 无死锁(属于有效性):即使锁定资源的客户端崩溃或被分区,也总是可以获得锁;通常通过超时机制实现。
  • 容错性(属于有效性):只要大多数 Redis 节点都启动,客户端就可以获取和释放锁。

除此之外,分布式锁的设计中还可以/需要考虑:

加锁解锁的同源性:A加的锁,不能被B解锁
获取锁是非阻塞的:如果获取不到锁,不能无限期等待;
高性能:加锁解锁是高性能的

分布式锁的实现方案

下面介绍几种我们日常工作中常见的分布式锁的实现方案

1、基于数据库实现分布式锁

  • 基于数据库表(锁表,很少使用)
  • 乐观锁(基于版本号)
  • 悲观锁(基于排它锁)

2、基于 redis 实现分布式锁

  • 单个Redis实例:setnx(key,当前时间+过期时间) + Lua
  • Redis集群模式:Redlock

3、基于 zookeeper实现分布式锁

  • 临时有序节点来实现的分布式锁,Curator

基于数据库的实现

通过数据库的事务特性来实现分布式锁,使用数据库行级锁或唯一索引。

详细代码示例(使用PostgreSQL):

// 加锁
public boolean tryLock(String lockKey, String clientId, int expireTime) {
    try (Connection connection = dataSource.getConnection()) {
        connection.setAutoCommit(false);
        try (PreparedStatement preparedStatement = connection.prepareStatement(
                "INSERT INTO distributed_lock (lock_key, client_id, expire_time) VALUES (?, ?, ?) ON CONFLICT (lock_key) DO NOTHING")) {
            preparedStatement.setString(1, lockKey);
            preparedStatement.setString(2, clientId);
            preparedStatement.setTimestamp(3, new Timestamp(System.currentTimeMillis() + expireTime));
            int affectedRows = preparedStatement.executeUpdate();
            if (affectedRows > 0) {
                connection.commit();
                return true;
            } else {
                connection.rollback();
                return false;
            }
        }
    } catch (SQLException e) {
        // 处理异常
        return false;
    }
}

// 解锁
public void unlock(String lockKey, String clientId) {
    try (Connection connection = dataSource.getConnection()) {
        try (PreparedStatement preparedStatement = connection.prepareStatement(
                "DELETE FROM distributed_lock WHERE lock_key = ? AND client_id = ?")) {
            preparedStatement.setString(1, lockKey);
            preparedStatement.setString(2, clientId);
            preparedStatement.executeUpdate();
        }
    } catch (SQLException e) {
        // 处理异常
    }
}

基于缓存的实现

利用分布式缓存系统(以Redis为例),通过其原子性操作来实现分布式锁。

详细代码示例(使用Redis):

// 加锁
public boolean tryLock(String lockKey, String clientId, int expireTime) {
    try (Jedis jedis = jedisPool.getResource()) {
        String result = jedis.set(lockKey, clientId, "NX", "PX", expireTime);
        return "OK".equals(result);
    }
}

// 解锁
public void unlock(String lockKey, String clientId) {
    try (Jedis jedis = jedisPool.getResource()) {
        jedis.del(lockKey);
    }
}

基于ZooKeeper的实现

利用ZooKeeper的临时有序节点特性,实现分布式锁。

public boolean tryLock(String lockKey, String clientId, int expireTime) {
    try {
        String lockPath = zooKeeper.create(lockKey + "/", clientId.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        List<String> children = zooKeeper.getChildren(lockKey, false);
        Collections.sort(children);
        if (clientId.equals(children.get(0))) {
            return true;
        } else {
            zooKeeper.delete(lockPath, -1);
            return false;
        }
    } catch (Exception e) {
        // 处理异常
        return false;
    }
}

public void unlock(String lockKey, String clientId) {
    try {
        List<String> children = zooKeeper.getChildren(lockKey, false);
        for (String child : children) {
            if (child.startsWith(clientId)) {
                zooKeeper.delete(lockKey + "/" + child, -1);
            }
        }
    } catch (Exception e) {
        // 处理异常
    }
}

分布式锁的注意事项

死锁和宕机

考虑在获取锁的过程中可能发生的节点宕机和死锁情况,确保系统的可用性。

锁的释放

确保锁在适当的时候被释放,防止出现死锁或者长时间占用锁的情况。

锁粒度

合理选择锁的粒度,过大的粒度可能导致性能问题,而过小的粒度可能导致锁争用。

结语

分布式锁是分布式系统中常用的同步机制,通过对共享资源的互斥访问,确保系统的一致性。在选择实现方案时,需要根据实际场景和系统要求综合考虑,保证分布式锁的性能、可靠性和可维护性。在实际应用中,可以根据业务需求选择适当的实现方案。

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

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

相关文章

告别内存容量焦虑,光威龙武系列DDR5内存条48GB才799

新年很多朋友又准备新装机或者升级内存了&#xff0c;我比较推荐直接用DDR5大容量的内容&#xff0c;像是光威龙武系列DDR5内存条性价比就非常高&#xff0c;能够满足专业玩家、创作者和高性能计算机用户的需求。这款涵盖多种存储规格&#xff0c;包括6400MHZ 242和6800MHZ 162…

【Vue3】2-5 : 指令系统与事件方法及传参处理

本书目录&#xff1a;点击进入 一、标签属性中的使用 - 指令系统 1.1 那么模板语法是否可以在标签属性中进行使用呢? ▶ 当然可以&#xff1a;使用 指令系统 二、指令系统 2.1 v-bind 2.2 v-on 三、实战 3.1 methods 选项 3.2 $event语法 一、标签属性中的使用 - 指令…

vue+springboot项目上传部署tomcat

下载及安装Tomcat 进入tomcat官网&#xff0c;Tomcat官网 选择需要下载的版本&#xff0c;点击下载下载路径一定要记住&#xff0c;并且路径中尽量不要有中文 下载后是压缩包 .zip&#xff0c;解压后 tomcat系统各个文件夹目录是什么意义&#xff1a; bin&#xff1a;放置的是…

有趣的前端知识(二)

推荐阅读 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;一&#xff09; 智能化校园&#xff1a;深入探讨云端管理系统设计与实现&#xff08;二&#xff09; 文章目录 推荐阅读HTML元素元素属性头部元素列表元素区块元素表单元素 颜色字符实体 HTML元素 …

即时设计:设计稿与PPT完美结合,让您的创意作品更具影响力

PPT助手 更多内容 在设计领域&#xff0c;将设计稿与PPT结合起来&#xff0c;可以让您的作品更具吸引力和影响力。为了满足这一需求&#xff0c;我们向您推荐一款强大的设计工具&#xff0c;它可以将设计稿导出为PPT文件&#xff0c;支持线上预览和编辑&#xff0c;让您的创意…

Spring学习 Spring AOP

4.Spring AOP 4.1.为什么要学习AOP? 案例&#xff1a;有一个接口Service有一个addUser方法&#xff0c;在调用addUser(被调用时打印调用前的毫秒数与调用后的毫秒数&#xff09;&#xff0c;其实现为&#xff1a; Service public class UserServiceImpl implements UserServi…

环信IM Demo登录方式如何修改为自己项目的?

在环信即时通讯云IM 官网下载Demo&#xff0c;本地运行只有手机验证码的方式登录&#xff1f;怎么更改为自己项目的Appkey和用户去进行登录呢&#xff1f; &#x1f447;&#x1f447;&#x1f447;本文以Web端为例&#xff0c;教大家如何更改代码来实现 1、 VUE2 Demo vue2…

2023十大最具商业影响力量子公司 | 光子盒年度系列

量子技术以其广泛的应用范围和对多个领域的深远影响&#xff0c;是当之无愧的“通用底座”技术&#xff0c;其潜在的产业变革力正在展现&#xff0c;尽管当前量子技术与人工智能或虚拟现实等技术领域相比&#xff0c;量子对大多数人来说还有些“看不透”。 2023年&#xff0c;量…

C#实现个人账本管理系统

git地址&#xff1a;https://gitee.com/myshort-term/personal-ledger-management-system 1.系统简介 LedgerManagementSystem是一个小型的个人账本管理系统&#xff0c;可对收支项目进行增加、删除、修改、查询以及导入和导出。可对每日的各类收支项目进行汇总并查看和修改收…

作业--day42

界面设计 MyProWin::MyProWin(QWidget *parent): QMainWindow(parent) {/**********窗口主体**********///窗口大小this->setFixedSize(644, 493);this->setWindowTitle("QQ");this->setWindowIcon(QIcon("C:/Users/10988/Downloads/pictrue/pictrue/…

计算机毕业设计 | SpringBoot+vue移动端音乐网站 音乐播放器(附源码)

1&#xff0c;项目背景 随着计算机技术的发展&#xff0c;网络技术对我们生活和工作显得越来越重要&#xff0c;特别是现在信息高度发达的今天&#xff0c;人们对最新信息的需求和发布迫切的需要及时性。为了满足不同人们对网络需求&#xff0c;各种特色&#xff0c;各种主题的…

函数战争(栈帧)之创建与销毁(c语言)(vs2022)

首先&#xff0c;什么是函数栈帧&#xff1f; C语言中&#xff0c;每个栈帧对应着一个未运行完的函数。栈帧中保存了该函数的返回地址和局部变量。栈帧也叫过程活动记录&#xff0c;是编译器用来实现过程函数调用的一种数据结构。 以问答的方式解释编译器与解释器-CSDN博客htt…

【C++入门】函数模板类模板(泛型编程)

目录 前言 1. 泛型编程 2. 函数模板 2.1 概念 2.2 语法格式 2.3 原理 2.4 函数模板的实例化 隐式实例化 显示实例化 2.5 思考 2.6 模板参数的匹配原则 3. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 总结 前言 函数模板和类模板是C中的两种重要的模板形式&#xff0c;…

day11 有效的括号 删除字符串中的所有相邻重复项 逆波兰表达式求值

题目1&#xff1a;20 有效的括号 题目链接&#xff1a;20 有效的括号 题意 判断字符串是否有效&#xff0c;若有效&#xff1a; 1&#xff09;左括号必须用相应的右括号 2&#xff09;左括号的闭合顺序正确 ({)}顺序不正确&#xff0c;应该是&#xff08;{}&#xff09; …

深度解析Nginx负载均衡算法及配置实例

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

Python3从零基础到入门(1)

目录 一、环境搭建 1.检测Python环境 2.下载安装Python环境 3.VSCode中配置Python环境 二、第一个程序 1.编码 2.输出 3.标识符 4.import 5.保留字 6.注释 7.缩进 三、变量和赋值 1.Python 中的变量 2.变量的赋值 3.多个变量赋值 四、基础数据类型 1.类型查看…

智能音箱喇叭杂音问题

智能音箱喇叭杂音问题 智能音箱生厂或出货过程会遇到多种喇叭播放有杂音的问题&#xff0e; 螺丝不匹配 智能音箱设备在生产过程&#xff0c;会有SPL测试喇叭失真&#xff0c;发现不良率8%的杂音问题&#xff0e; 分析原因是来料导入了新螺丝&#xff0c; 使用过程进入异物…

harmonyOS 时间选择组件(TimePicker)

本文 我们来说 TimePicker 时间组件 首先 我们搭一个最基本的组件骨架 Entry Component struct Index {build() {Row() {Column() {}.width(100%)}.height(100%)} }然后 在 Column 组件内 放一个 TimePicker进去 这里 我们就可以看到 一个时间的选择器了 DatePicker 捕获当前…

EPQ艾森克人格测试 49题(免费版)

艾森克人格提出人格的三个基本因素&#xff1a;性格内外向E、神经质N&#xff08;也叫情绪性&#xff09;和精神质P。这三个维度的不同程度组合&#xff0c;形成了独立的个体人格特征。 其中性格内外向维度是目前评估性格内向和外向的成熟量表&#xff0c;神经质和精神质为人格…

机器人技能学习-robosuite-0-入门介绍

文章目录 前言模块介绍实战案例1&#xff1a;从 demo 中创建自己的 env案例2&#xff1a;更换属于自己的物体 前言 资料太少、资料太少、资料太少&#xff0c;重要的事说三边&#xff0c;想根据自己实际场景自定义下机器人&#xff0c;结果发现无路可走&#xff0c;鉴于缺少参…