一起唠唠分布式锁

(1)分布式锁和分布式事务的区别

1.分布式锁是在集群环境下,用来控制不同机器对全局共享资源的访问。
2.分布式事务是在集群环境下,用来保证全局事务的一致性,保证多个数据库的数据整体上能正确的从一个一致性状态转到另一个一致性状态。

(2)分布式锁应用场景

在我们的某个jvm应用程序中,如果需要对某个共享变量进行多线程同步访问,可以使用java多线程的同步工具,例如ReentrantLock、Synchronized等等。但是当我们的系统由单机部署演化成为分布式集群系统后,在不同机器上原来单机的并发控制锁策略就会失效了,这时就需要引入分布式锁。
举个简单的例子,比如某个外卖骑士每天需要购买一份保险,某天在购买保险时,这个骑士多次点击了买保险的按钮,前端没有做控制,导致同时向服务器发送了多个买保险请求,那这个时候就会导致骑士多次购买保险,为了解决这个问题,我们可以使用分布式锁,保证在某个时间段内,只能有一台机器执行买保险操作,这时就能保障骑士不会多次购买保险。分布式锁主要有三种实现方式:

  1. 基于数据库实现
  2. 基于redis实现
  3. 基于ZooKeeper实现

(3)分布式锁实现方式

1.基于数据库实现

我们可以通过数据库表来实现分布式锁,表结构如下:在这里插入图片描述
表中的每一条记录就代表一个锁,当我们需要获取锁时就去数据库中查询是否有该共享资源的记录。
(1)如果有则获取其中的node_info,与自己的机器信息进行比较,如果发现是自己已经获取过的锁,那直接使用共享资源,将count数加1,在使用完数据后将count数减1,当count数为0时将记录删除掉。否则就返回错误信息,提示已经有人获取了锁。
(2)如果获取不到就建立一条记录,那就自己建立一条记录,并记录下自己的机器信息,然后使用共享资源。
在这里插入图片描述
上面其实就是利用数据库实现锁的简单方式。这种方式存在比较严重的问题:1.数据库机器可能存在单点、2.没有超时时间,数据库宕掉后可能导致无法获取锁、3.数据库是磁盘文件,获取锁的时间和性能并不好。

2.基于redis实现

基于redis的分布式锁,主要依赖于redis的几个命令:

  1. setnx():set if not exists,其主要有两个参数 setnx(key, value)。该方法是原子的,如果 key 不存在,则设置当前 key 成功,返回 1;如果当前 key 已经存在,则设置当前 key 失败,返回 0。
  2. expire():expire 设置过期时间,要注意的是 setnx 命令不能设置 key 的超时时间,只能通过 expire() 来对 key 设置。

使用步骤:
1、setnx(lockkey, 1) 如果返回 0,则获取锁失败;如果返回 1,则说明获取锁成功。
2、expire() 命令对 lockkey 设置超时时间,为的是避免死锁。
3、执行完业务代码后,可以通过 delete 命令删除 key。

使用问题:
上面的使用方式是能满足我们大部分的业务需求的,但是在某些极端的情况下,还是会存在问题。

  1. 问题: 当节点A执行完setnx后,节点A就宕掉了,还没来得及执行expire,那么会导致其他节点一直无法获取锁。
    在这里插入图片描述
    解决方案: 使用set命令代替setnx和expire。
// NX表示:key不存在就返回true,存在就返回false
// PX表示:指定的过期时间
SET lockName value NX PX
  1. 问题: 节点A获取了锁,并设置了30秒的过期时间,但是由于某些原因业务代码执行了很久(超过了30秒),delete操作还没执行。这时因为节点A获取的锁过期了,节点B获取了锁,而节点A执行了delete操作,释放了节点B的锁。
    在这里插入图片描述
    解决方案: 在通过delete操作释放锁之前判断当前的锁是不是自己加的。

当然我们也可以使用RedLock,RedLock是redis实现的分布式锁算法(RedLock),可以有效防止单点故障 。另外还有基于Zookeeper的实现,对于Zookeeper我不咋懂,所以这里就不写了。
在这里插入图片描述

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

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

相关文章

DCT(离散余弦变换(DiscreteCosineTransform))

离散余弦变换(Discrete Cosine Transform,简称DCT变换)是一种与傅立叶变换紧密相关的数学运算。在傅立叶级数展开式中,如果被展开的函数是实偶函数,那么其傅立叶级数中只包含余弦项,再将其离散化可导出余弦…

从源码看ConcurrentHashMap

简介 ConcurrentHashMap是线程安全的HashMap实现,这里主要研究JDK8后的ConcurrentHashMap,下面是ConcurrentHashMap的简单结构: ConcurrentHashMap基于HashMap的基本逻辑,通过CAS synchronized 来保证并发安全性。ConcurrentHas…

Spring Boot 整合Mybatis (一)

2019独角兽企业重金招聘Python工程师标准>>> 新建spring-boot项目&#xff0c;相关依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><de…

x264 的 cache详解

在这里和下一级别的分析中有必要先讲一下这个h->mb.cache&#xff08;没法讲&#xff0c;就是cache!&#xff09;。 x264_macroblock_cache_load将参考帧中某位置的&#xff08;重建后&#xff09;数据保存进cache&#xff0c;供参考和反复使用。 x264_macroblock_cache_s…

Repeater的使用

1.页面代码 如果要分页&#xff0c;那么页面开头必须写&#xff08;<% Register Src"~/Controls/Page.ascx" TagName"Page" TagPrefix"uc1" %>&#xff09; 并且分页&#xff0c;页脚<uc1:Page ID"Page2" runat"server&…

Android NDK MediaCodec在ijkplayer中的实践

https://www.jianshu.com/p/41d3147a5e07 从API 21&#xff08;Android 5.0&#xff09;开始Android提供C层的NDK MediaCodec的接口。 Java MediaCodec是对NDK MediaCodec的封装&#xff0c;ijkplayer硬解通路一直使用的是Java MediaCodec接Surface的方式。 本文的主要内容是&a…

leetcode-49-字母异位词分组(神奇的哈希)

题目描述&#xff1a; 给定一个字符串数组&#xff0c;将字母异位词组合在一起。字母异位词指字母相同&#xff0c;但排列不同的字符串。 示例: 输入: ["eat", "tea", "tan", "ate", "nat", "bat"], 输出: [[&quo…

【精心总结】java内存模型和多线程必会知识

内存模型 &#xff08;1&#xff09;java内存模型到底是个啥子东西&#xff1f; java内存模型是java虚拟机规范定义的一种特定模型&#xff0c;用以屏蔽不同硬件和操作系统的内存访问差异&#xff0c;让java在不同平台中能达到一致的内存访问效果&#xff0c;是在特定的协议下…

快速解决 GRADLE 项目下载 gradle-*-all.zip 慢的问题

1、首先根据项目中 gradle\wrapper\gradle-wrapper.properties 文件的 distributionUrl 属性的值 #Tue Feb 06 12:27:20 CET 2018 distributionBaseGRADLE_USER_HOME distributionPathwrapper/dists zipStoreBaseGRADLE_USER_HOME zipStorePathwrapper/dists distributionUrlht…

mysql查询流程解析及重要知识总结

时光荏苒啊&#xff01;在过两个月我就工作满三年了&#xff0c;大学毕业的情景还历历在目&#xff0c;而我已经默默的向油腻中年大叔进发了。作为一名苦逼的后端工程师&#xff0c;我搞过一段时间python&#xff0c;现在靠java糊口&#xff0c;但后来才发现&#xff0c;始终不…

保守官僚 诺基亚就这样迷失在智能机时代?

7月19日&#xff0c;诺基亚发布了二季度财报&#xff0c;净亏损达到了17亿美元&#xff0c;其中智能手机份额和销售量进一步下滑&#xff0c;这个智能手机的领导者&#xff0c;正在因智能手机而急速坠落。诺记亚领先业界近十年就把握住了智能手机的趋势&#xff0c;并推出了首款…

django集成ansibe实现自动化

动态生成主机列表和相关参数 def create_admin_domain(admin_node):workpath BASE_DIR /tools/ansible/scripthosts_file BASE_DIR /tools/ansible/host/ createhostfile()yml_file BASE_DIR /tools/ansible/yml/ create_admin_domain.ymldomain_path admin_node.doma…

【spring容器启动】之bean的实例化和初始化(文末附:spring循环依赖原理)

本次我们通过源码介绍ApplicationContext容器初始化流程&#xff0c;主要介绍容器内bean的实例化和初始化过程。ApplicationContext是Spring推出的先进Ioc容器&#xff0c;它继承了旧版本Ioc容器BeanFactory&#xff0c;并进一步扩展了容器的功能&#xff0c;增加了bean的自动识…

如何将自己的Java项目部署到外网

见&#xff1a;http://jingyan.baidu.com/article/90bc8fc864699af653640cf7.html 做b/s模式的web开发不同于c/s模式的客户端开发&#xff0c;c/s模式我们只要做好生成可执行文件发送给其他人&#xff0c;其他人就可以用了。但是c/s模式不同&#xff0c;在同一局域网下&#xf…

java后端必会【基础知识点】

&#xff08;一&#xff09;java集合类&#xff08;done&#xff09; 在java集合类中最常用的是Collection和Map的接口实现类。Collection又分为List和Set两类接口&#xff0c;List的实现类有ArrayList、LinkedList、Vector、Stack&#xff0c;Set接口的实现类有HashSet、Tree…

48_并发编程-线程-资源共享/锁

一、数据共享多个线程内部有自己的数据栈&#xff0c;数据不共享&#xff1b;全局变量在多个线程之间是共享的。1 # 线程数据共享不安全加锁2 3 import time4 from threading import Thread, Lock5 6 7 num 1008 9 def func(t_lock): 10 global num 11 t_lock.acquire…

移动硬盘提示无法访问设备硬件出现致命错误,导致请求失败的资料寻回方案

J盘打不开设备硬件出现致命错误,导致请求失败&#xff0c;是因为这个I盘的文件系统内部结构损坏导致的。要恢复里面的数据就必须要注意&#xff0c;这个盘不能格式化&#xff0c;否则数据会进一步损坏。具体的恢复方法看正文 工具/软件&#xff1a;星空数据恢复软件 步骤1&…

VMware10上新建虚拟机步骤图解

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 第一种 : 自定义方式&#xff1a; 安装虚拟机的过程步骤&#xff0c;基本上过程的每一步都有截图&#xff0c;跟着过程就可以很容易的创…

怎么理解 IaaS、SaaS 和 PaaS 的区别?

原文链接&#xff1a;怎么理解 IaaS、SaaS 和 PaaS 的区别&#xff1f; 一、定义层面的区别 SaaS、PaaS、IaaS简单的说都属于云计算服务&#xff0c;也就是云计算服务。我们对于云计算的概念&#xff0c;维基百科有以下定义&#xff1a; Cloud computing is a new form of In…

如何删除虚拟机上的操作系统、删除新建的虚拟机

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 打开VMware&#xff0c;我安装了三个虚拟系统&#xff0c;要对win98进行删除&#xff0c;从磁盘上删除~~ 2、双击你要删除的系统&#xf…