分布式锁,也就是在多进程情况下的锁。

多进程的锁 跟 多线程的 锁 有什么相同的地方呢?

  1. 需要有存储锁的空间,并且锁的空间是可以访问到的。
  2. 锁需要被唯一标识。
  3. 锁要有至少两种状态。

储存空间:

锁是一个抽象的概念,锁的实现,需要依存于一个可以存储锁的空间。在多线程中是内存,在多进程中是内存或者磁盘。更重要的是,这个空间是可以被访问到的。多线程中,不同的线程都可以访问到堆中的成员变量;在多进程中,不同的进程可以访问到共享内存中的数据或者存储在磁盘中的文件。但是在分布式环境中,不同的主机很难访问对方的内存或磁盘。这就需要一个都能访问到的外部空间来作为存储空间。

最普遍的外部存储空间就是数据库了,事实上也确实有基于数据库做分布式锁(行锁、version乐观锁),如quartz集群架构中就有所使用。除此以外,还有各式缓存如Redis、Tair、Memcached、Mongodb,当然还有专门的分布式协调服务Zookeeper,甚至是另一台主机。只要可以存储数据、锁在其中可以被多主机访问到,那就可以作为分布式锁的存储空间。

唯一标识:

不同的共享资源,必然需要用不同的锁进行保护,因此相应的锁必须有唯一的标识。在多线程环境中,锁可以是一个对象,那么对这个对象的引用便是这个唯一标识。多进程环境中,信号量在共享内存中也是由引用来作为唯一的标识。但是如果不在内存中,失去了对锁的引用,如何唯一标识它呢?上文提到的有名信号量,便是用硬盘中的文件名作为唯一标识。因此,在分布式环境中,只要给这个锁设定一个名称,并且保证这个名称是全局唯一的,那么就可以作为唯一标识。

至少两种状态:

为了给临界区加锁和解锁,需要存储两种不同的状态。如ReentrantLock中的status,0表示没有线程竞争,大于0表示有线程竞争;信号量大于0表示可以进入临界区,小于等于0则表示需要被阻塞。因此只要在分布式环境中,锁的状态有两种或以上:如有锁、没锁;存在、不存在等等,均可以实现。

数据库:去判断某个字段的状态 来判断是否能得到锁。

redis:根据 setnx 命令 来判断, 如果返回1 则获取到了锁,否则就是没获取到,死锁,锁的有效期的问题点:

zookeeper : 1、通过注册临时节点的方式,能注册成功会返回节点的名称,就是获取到了锁,

2、去创建最小临时有序节点,通过一系列的判断,当注册的节点是最小节点时就获取到了锁。临时节点消失也就意味着锁释放。

通过了解分布式锁 跟 普通 的锁的相同点之后,其实自己就可以实现一个简单的分布式锁,但为什么要用redis或者是 zookeeper这样复杂的中间件呢?

因为redis 跟zookeeper 会给我们解决下面这些问题:

  • 问题1:锁状态判断原子性无法保证
    从读取锁的状态,到判断该状态是否为被锁,需要经历两步操作。如果不能保证这两步的原子性,就可能导致不止一个请求获取到了锁,这显然是不行的。因此,我们需要保证锁状态判断的原子性。

  • 问题2:网络断开或主机宕机,锁状态无法清除
    假设在主机已经获取到锁的情况下,突然出现了网络断开或者主机宕机,如果不做任何处理该锁将仍然处于被锁定的状态。那么之后所有的请求都无法再成功抢占到这个锁。因此,我们需要在持有锁的主机宕机或者网络断开的时候,及时的释放掉这把锁。

  • 问题3:无法保证释放的是自己上锁的那把锁
    在解决了问题2的情况下再设想一下,假设持有锁的主机A在临界区遇到网络抖动导致网络断开,分布式锁及时的释放掉了这把锁。之后,另一个主机B占有了这把锁,但是此时主机A网络恢复,退出临界区时解锁。由于都是同一把锁,所以A就会将B的锁解开。此时如果有第三个主机尝试抢占这把锁,也将会成功获得。因此,我们需要在解锁时,确定自己解的这个锁正是自己锁上的。

在实际的情况下,还有这些问题:

  1. 可重入:线程中的可重入,指的是外层函数获得锁之后,内层也可以获得锁,ReentrantLock和synchronized都是可重入锁;衍生到分布式环境中,一般仍然指的是线程的可重入,在绝大多数分布式环境中,都要求分布式锁是可重入的。
  2. 惊群效应(Herd Effect):在分布式锁中,惊群效应指的是,在有多个请求等待获取锁的时候,一旦占有锁的线程释放之后,如果所有等待的方都同时被唤醒,尝试抢占锁。但是这样的情况会造成比较大的开销,那么在实现分布式锁的时候,应该尽量避免惊群效应的产生。
  3. 公平锁和非公平锁:不同的需求,可能需要不同的分布式锁。非公平锁普遍比公平锁开销小。但是业务需求如果必须要锁的竞争者按顺序获得锁,那么就需要实现公平锁。
  4. 阻塞锁和自旋锁:针对不同的使用场景,阻塞锁和自旋锁的效率也会有所不同。阻塞锁会有上下文切换,如果并发量比较高且临界区的操作耗时比较短,那么造成的性能开销就比较大了。但是如果临界区操作耗时比较长,一直保持自旋,也会对CPU造成更大的负荷。

分布式环境下的解决方案——分布式锁相关推荐

  1. 分布式环境下定时任务重复执行问题解决方案

    现在为了提高服务的响应时间,避免单点故障,一般项目都会做集群部署,最少两个节点.集群部署的时候就会暴露出一些单节点下不会遇到的问题,比如session问题.缓存不一致问题等.还有一种情况是,定时任务重 ...

  2. JAVA中useDrlimiter方法_今天来讲讲分布式环境下,怎么达到对象共享,以及实现原子性(atomic),以Redis中的Redisson为例(实现分布式锁、分布式限流等)...

    相信各位对redis肯定是不陌生的,一个高吞吐量的内存型结构存储数据库.可用用于很多业务场景,能够有效的解决很多复杂的并发问题,分布式问题. 下面粘一下中文官网介绍: 关于解决对象共享问题,很多方式, ...

  3. 分布式环境下,互斥性与幂等性问题,分析与解决思路

    欢迎关注方志朋的博客,回复"666"获面试宝典 随着互联网信息技术的飞速发展,数据量不断增大,业务逻辑也日趋复杂,对系统的高并发访问.海量数据处理的场景也越来越多.如何用较低成本实 ...

  4. 分布式精华问答:分布式环境下如何保持数据一致性的?| 技术头条

    分布式开发的时代实际上早已悄悄地成为了时代的主流,今天,我们就来看看关于分布式的精华问答吧! 1 Q:分布式系统中主要是用到了服务化,消息中间件,数据库拆分,便于横向扩展和维护,但分布式系统中的拆分的 ...

  5. 面试官:分布式环境下,如何实现session共享

    点击关注公众号,实用技术文章及时了解 先了解一下为什么会出现这种session共享的解决方案? 随着互联网公司的项目在微服务和分布式的环境下进行的搭建,导致一个项目可能分别部署在几个甚至很多的服务器集 ...

  6. 【分布式】分布式环境下如何保证数据库和缓存的双写一致性?看完我明白了!!

    写在前面 当今时代,互联网高速发展,已然从IT时代进入到DT时代.我们系统的架构也由原来的单体应用,转变为分布式.微服务的架构模式.从数据上来看,数据量越来越大,数据的查询性能越来越低.此时,就需要我 ...

  7. 如何设计一个分布式环境下全局唯一的发号器

    一.如何设计一个分布式环境下全局唯一的发号器 1.UUID 常见的方式.可以利用数据库也可以利用程序生成,一般来说全球唯一. 优点: 简单,代码方便. 生成ID性能非常好,基本不会有性能问题. 全球唯 ...

  8. mysql集群session_集群/分布式环境下5种session处理策略

    前言 在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处理.如果不做任何处理的话,用户将出现频繁登录的现象,比如集群中存在A.B两台服务器,用户在第一次访问网站时,Ngin ...

  9. C#session共享+redis_Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享...

    精品推荐 国内稀缺优秀Java全栈课程-Vue+SpringBoot通讯录系统全新发布! Docker快速手上视频教程(无废话版)[免费] 作者:夜月归途 转载自: https://www.cnblo ...

最新文章

  1. wamp安装多版本php,WampServer安装多个php版本
  2. wsl开nginx和php-fpm遇到的几个小问题
  3. Oracle database datafile header中记录的datafile的大小
  4. 【Python-ML】SKlearn库L1正则化特征选择
  5. Check failed: error == cudaSuccess (74 vs. 0) misaligned address的解决方法
  6. C#学习笔记——软件注册与注册机
  7. 林锐 高质量c语言编程下载,新年献礼:Go语言深度入门手册
  8. CoreTextHyperlinkView
  9. yml连接sqlserver_Mybatis-plus连接操作SQLServer数据库(基于Maven项目)
  10. Eigen 3.3.7 MatrixVector的运算
  11. 怎样做sns网站?哪里可下载这类程序?
  12. linux字符串替换命令,Linux系统字符串替换命令详细说明
  13. Chrome免安装版制作
  14. HugePages 大内存页
  15. Python应用练习题(第一期)——基本语句练习
  16. Jenkins 身份验证及授权简介
  17. 海洋cms宝塔定时linux,海洋cms设置宝塔计划任务自动采集
  18. leetcode第21天格雷编码
  19. DB2存储过程使用游标
  20. 2022-2027年(新版)中国果汁饮料行业销售渠道与营销趋势预测报告

热门文章

  1. Flink SQL:Queries(Windowing TVF)
  2. 天野学院第二期模拟班
  3. Java进阶——异常
  4. Glid加载头像闪烁的问题
  5. 手把手教你设计CPU RISC-V处理器设计
  6. PCIe系列专题之七:PCIe热插拔
  7. 黑莓来电显示程序BBIPCall1.2.0发布
  8. 传统分布式共识 VS 中本聪共识
  9. Flask 的 jsonify 理解
  10. 【附源码】Java计算机毕业设计安卓运动健康app(程序+LW+部署)