一句话说清分布式锁,进程锁,线程锁

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁。线程锁,进程锁,分布式锁线程锁:大家都不陌生,主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该段代码。

在分布式集群系统的开发中,线程锁往往并不能支持全部场景的使用,必须引入新的技术方案分布式锁。

线程锁,进程锁,分布式锁

线程锁:大家都不陌生,主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有有一个线程在执行该段代码。当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段。但是,其余线程是可以访问该对象中的非加锁代码块的。

进程锁:也是为了控制同一操作系统中多个进程访问一个共享资源,只是因为程序的独立性,各个进程是无法控制其他进程对资源的访问的,但是可以使用本地系统的信号量控制(操作系统基本知识)。

分布式锁:当多个进程不在同一个系统之中时,使用分布式锁控制多个进程对资源的访问。

分布式锁到底是什么,怎么实现?

intsmaze说简单点,实现分布式锁必须要依靠第三方存储介质来存储锁的元数据等信息比如分布式集群要操作某一行数据时,这个数据的流水号是唯一的,那么我们就把这个流水号作为一把锁的id,当某进程要操作该数据时,先去第三方存储介质中看该锁id是否存在,如果不存在,则将该锁id写入,然后执对该数据的操作;当其他进程要访问这个数据时,会先到第三方存储介质中查看有没有这个数据的锁id,有的话就认为这行数据目前已经有其他进程在使用了,就会不断地轮询第三方存储介质看其他进程是否释放掉该锁;当进程操作完该数据后,该进程就到第三方存储介质中把该锁id删除掉,这样其他轮询的进程就能得到对该锁的控制。

Redis中当然不能通过get,set操作判断,get,set操作不是一个原子的,可以使用redis的jedis.set(String key, String value, String nxxx, String expx, int time)命令来保证原子性。

具体实现方案:
https://www.cnblogs.com/linjiqin/p/8003838.html

说了这么多,再补充一点,线程锁,进程锁,分布式锁的作用都是一样的,只是作用的范围大小不同范围大小:分布式锁——大于——进程锁——大于——线程锁。能用线程锁,进程锁情况下使用分布式锁也是可以的,能用线程锁的情况下使用进程锁也是可以的。只是范围越大技术复杂度就越大。

多年j2EE开发生涯从未感觉到分布式锁的痛点!!!

关于分布式锁,有过javaEE开发经验的就会说了,系统为了应对高并发,会搭建一个比如tomcat集群,集群内服务都是访问的同一台数据库,有多台服务器同时修改同一条数据库数据的操作,但是我们并没有在服务器中使用分布式锁?按照上面对分布式锁的解释,两个不同系统上的JVM进程同时访问数据库的同一个资源,这个时候我们应该使用分布式锁进行控制。

这说的没有错,但是我们忘记了数据库的特性了。如果两台服务器仅仅是直接访问(通过url)并操作某台服务器硬盘中某个文件同一行数据,这个时候我们必须用分布式锁。

但是因为这两台服务器访问的数据是存储在数据库中的(数据库本身就是一个服务程序,多线程的接收外部系统发来的请求),两台服务器的请求通过网络IO发送到数据库服务器后,然后把请求交给数据库服务的进程处理,数据库服务器是多线程接收请求并处理的,这个时候关于某表某一行数据的多线程访问控制是由数据库服务进行控制的(就是数据库服务的代码中进行了线程上的加锁处理),这就是数据库服务器的行锁等特性,因为数据库那一端已经对外部多个系统的请求进行了一个锁操作,所以不需要我们在应用服务端进行分布式锁的开发。 

那如果想同时更新数据库的多行数据,这个时候数据库的行锁就无法保证了。这个时候我们就要使用分布式锁,是的这个时候就可以使用,注意我用的是可以。为什么说可以呢?因为数据库本身就提供了这个机制,事务以及他的隔离级别。当然你也可以不用数据库提供的事务,用分布式锁。

分布式锁的设计不需要考虑业务吗?

分布式锁的设计并不是完全美好的,只能针对某些业务场景下使用,如果要对所有业务使用,必须充分理解业务需求合理的设计,至于原因就和各位j2ee开发时mybatis的二级缓存以命名空间为单位所要注意的业务问题时一样的。  

intsmaze使用分布式锁,我们会把某表的第二第三行作为id来锁住,如果有相同的操作时更新该表第二第三行,我们才不让他修改,必须让他拿到锁才可以。但是如果有个操作仅仅是修改第二行,这个时候他就获得了对该行的操作,而且等数据库释放掉之前操作对该行的锁后。所以分布式锁并不是随处可用的,只是在某些场景下可以使用。比如业务系统不会存在单独修改第二行的操作。

分布式锁用于hbase存储系统

实际开发场景中,我们会对hbase操作进行分布式锁,hbase作为一款优秀的非内存数据库,传统数据库一样提供了事务的概念,只是HBase的事务是行级事务,可以保证行级数据的原子性、一致性、隔离性以及持久性,即通常所说的ACID特为了实现事务特性,HBase采用了各种并发控制策略,包括各种锁机制、MVCC机制等。因为hbase只支持行级事物,当业务需要并发操作两行甚至多行记录时,hbase本身就无法提供ACID的支持了。

数据库访问量过大除了主从还能如何负载压力?

数据库会为客户端的每一个请求创建一个线程,这些线程针对特定行数据修改必须获得该行的行锁,而其他客户端线程要想修改该数据的话,必须等待前面的线程释放锁后才被允许。如果客户端很多线程都要修改某行数据的话,没有拿到锁的线程都会在数据库端机器上不断轮询,增大数据库端的压力。

我们可以使用分布式锁,把对数据库行锁的等待获取的轮询放到每一个客户端机器上去实现,这样可以避免数据库端线程的不断轮询。比如,客户端在要发送对数据库的某行数据的操作请求前,在客户端机器上进行锁的争抢,没有获取到锁,就不会像数据库端发送操作请求,这样数据库端就没有了轮询的压力。当然分布式锁的引入一定要结合业务的需求来进行设计,不然会出现锁id的命名不全导致读取的数据不一致,数据过期失效等问题。

使用那种第三方介质存放分布式锁?

目前流行的是zookeeper和redis,两者各有好处,redis流行的内存缓存,且能进行水平扩容同时还能提高请求负载,面对高并分布式锁数据的读写请求能高速响应,同时有aof,哨兵机制可以防止某台宕机分布式锁数据丢失带来的问题。

zookeeper我是比较喜欢,因为他是分布式一致性算法paxos算法的实现,面对高负载请求毫无压力,同时某一台宕机毫不影响分布式锁数据一致性,且附带了监听机制,当某一程序释放某一个锁后,其他程序可以及时得到通知来获得对该分布式锁的控制权,这里的轮询实现不需要我们去开发了。

关于分布式锁与线程锁的介绍从一年前就在编辑中,一直没有时间以一种通俗明了的方式介绍给大家。本人在很多论坛中发现很多刚入大数据领域的新人都会提到分布式锁,但是并没有深刻明白分布式锁和线程锁的场景,以至于很多情况下明明线程锁就可以搞定的却引入了分布式锁,让整个系统设计的更加复杂了。

另外要说的,zookeeper笔者认为是很棒的技术,虽然在大数据领域只是作为某一个框架的一个协调者出现,导致很多开发者忽视了他的伟大性。但是我想说的,在当前火热的微服务中,其实会借助zookeeper实现很多功能,比如分布式锁,配置中心。

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
  相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情: https://cn.aliyun.com/product/hbase   ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
30天前
|
消息中间件 并行计算 安全
进程、线程、协程
【10月更文挑战第16天】进程、线程和协程是计算机程序执行的三种基本形式。进程是操作系统资源分配和调度的基本单位,具有独立的内存空间,稳定性高但资源消耗大。线程是进程内的执行单元,共享内存,轻量级且并发性好,但同步复杂。协程是用户态的轻量级调度单位,适用于高并发和IO密集型任务,资源消耗最小,但不支持多核并行。
43 1
|
9天前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
14天前
|
Linux 调度 C语言
深入理解操作系统:进程和线程的管理
【10月更文挑战第32天】本文旨在通过浅显易懂的语言和实际代码示例,带领读者探索操作系统中进程与线程的奥秘。我们将从基础知识出发,逐步深入到它们在操作系统中的实现和管理机制,最终通过实践加深对这一核心概念的理解。无论你是编程新手还是希望复习相关知识的资深开发者,这篇文章都将为你提供有价值的见解。
|
11天前
|
Java
java小知识—进程和线程
进程 进程是程序的一次执行过程,是系统运行的基本单位,因此进程是动态的。系统运行一个程序即是一个进程从创建,运行到消亡的过程。简单来说,一个进程就是一个执行中的程序,它在计算机中一个指令接着一个指令地执行着,同时,每个进程还占有某些系统资源如CPU时间,内存空间,文件,文件,输入输出设备的使用权等等。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程 线程,与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间做切换工作时,负担要比
22 1
|
16天前
深入理解操作系统:进程与线程的管理
【10月更文挑战第30天】操作系统是计算机系统的核心,它负责管理计算机硬件资源,为应用程序提供基础服务。本文将深入探讨操作系统中进程和线程的概念、区别以及它们在资源管理中的作用。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程和线程的管理技巧。
33 2
|
18天前
|
调度 Python
深入浅出操作系统:进程与线程的奥秘
【10月更文挑战第28天】在数字世界的幕后,操作系统悄无声息地扮演着关键角色。本文将拨开迷雾,深入探讨操作系统中的两个基本概念——进程和线程。我们将通过生动的比喻和直观的解释,揭示它们之间的差异与联系,并展示如何在实际应用中灵活运用这些知识。准备好了吗?让我们开始这段揭秘之旅!
|
1月前
|
存储 消息中间件 人工智能
进程,线程,协程 - 你了解多少?
本故事采用简洁明了的对话方式,尽洪荒之力让你在轻松无负担的氛围中,稍微深入地理解进程、线程和协程的相关原理知识
41 2
进程,线程,协程 - 你了解多少?
|
28天前
|
Python
Python中的多线程与多进程
本文将探讨Python中多线程和多进程的基本概念、使用场景以及实现方式。通过对比分析,我们将了解何时使用多线程或多进程更为合适,并提供一些实用的代码示例来帮助读者更好地理解这两种并发编程技术。
|
1月前
|
消息中间件 并行计算 安全
进程、线程、协程
【10月更文挑战第15天】进程、线程和协程是操作系统中三种不同的执行单元。进程是资源分配和调度的基本单位,每个进程有独立的内存空间;线程是进程内的执行路径,共享进程资源,切换成本较低;协程则更轻量,由用户态调度,适合处理高并发和IO密集型任务。进程提供高隔离性和安全性,线程支持高并发,协程则在资源消耗和调度灵活性方面表现优异。
45 2
|
1月前
|
算法 安全 调度
深入理解操作系统:进程与线程的管理
【10月更文挑战第9天】在数字世界的心脏跳动着的,不是别的,正是操作系统。它如同一位无形的指挥家,协调着硬件与软件的和谐合作。本文将揭开操作系统中进程与线程管理的神秘面纱,通过浅显易懂的语言和生动的比喻,带你走进这一复杂而又精妙的世界。我们将从进程的诞生讲起,探索线程的微妙关系,直至深入内核,理解调度算法的智慧。让我们一起跟随代码的脚步,解锁操作系统的更多秘密。
37 1