分布式系统中如何实现临界资源的互斥访问?_华为云开发者联盟-编程思维

分布式系统中如何实现临界资源的互斥访问?_华为云开发者联盟-编程思维
摘要:一次仅允许一个进程使用的资源称为临界资源。

本文分享自华为云社区《分布式系统中如何实现临界资源的互斥访问》,作者:华为云PaaS服务小智。

网络时代,购物、社交等之前只能在线下进行的活动,如今都可以在网络上完成。为了促进消费,电商网、网络店铺经常推出商品限定数量内的“秒杀”,“抢购”活动,类似的临界资源访问还有我们生活中常见的微信多人抢红包。这种临界资源,多人访问的情况,如何保证避免一个资源被多人(一人以上)互斥访问呢?

临界资源

多道程序系统中存在许多进程,它们共享各种资源,然而有很多资源一次只能供一个进程使用。一次仅允许一个进程使用的资源称为临界资源。

上面我们提到的在抢购中对商品提交订单,微信中打开多人红包都属于这种临界资源的访问,一次只允许一个进程使用。

临界资源互斥访问

分布式互斥是随着分布式系统的出现而出现的,并随着分布式系统理论发展而发展。在分布式系统中,很多进程能够在微观上并行执行。但由于共享资源的有限性,以及全局数据要求的一致性,一些临界资源的访问需要以互斥的方式实现同步。

Java原生锁

在传统单机部署的情况下,可以使用Java并发处理相关的API(如ReentrantLock或synchronized)进行互斥控制。这种Java提供的原生锁机制可以保证在同一个Java虚拟机进程内的多个线程同步执行,避免出现无序现象。

但在互联网场景,特别是抢购活动中,随着整个系统的并发访问飙升,需要多台机器并发运行,以应对用户井喷式访问,假设此时多个用户的请求同时到来,但落在了不同的机器上,虽然这两个请求是可以同时执行,但是因为两个机器运行在两个不同的Java虚拟机里面,他们加的锁只对属于自己Java虚拟机里面的线程有效,对于其他Java虚拟机的线程是无效的。因此,Java提供的原生锁机制在多机部署场景下失效了,这是因为两台机器加的锁不是同一个锁(两个锁在不同的Java虚拟机里面),这样便会出现库存超卖的现象。

分布式锁

基于存在的现状,我们只要保证多台机器加的锁是同一个锁,用加锁的方式对某种资源进行顺序访问控制。这就需要分布式锁登场了。

分布式锁是一种解决分布式临界资源并发读写的一种技术,对分布式应用加锁,能够避免出现库存超卖及无序访问等现象。

分布式锁的思路是:在整个系统提供一个全局、唯一的获取锁的“东西”,然后每个系统在需要加锁时,都去问这个“东西”拿到一把锁,这样不同的系统拿到的就可以认为是同一把锁。

当前分布式加锁主要有三种方式:(磁盘)数据库、缓存数据库、Zookeeper。

用 Redis 实现分布式锁

使用Redis类型的缓存实例实现分布式加锁,有几大优势:

• 加锁操作简单,使用SET、GET、DEL等几条简单命令即可实现锁的获取和释放。

• 性能优越,缓存数据的读写优于磁盘数据库与Zookeeper。

如下图中所示,使用redis的set方法即可实现对临界资源加锁,点击此获取全量代码 

使用redis的del方法即可实现锁的释放。

相对于传统redis,如今各大云厂商也都推出了redis云服务,以即开即用、安全可靠、弹性扩容、便捷管理等特点受到软件开发企业和开发者的欢迎。

参考资料

李美安. 普适分布式互斥算法及应用[D]. 电子科技大学, 2006.

 

点击关注,第一时间了解华为云新鲜技术~

版权声明:本文版权归作者所有转载请注明原文链接
https://www.cnblogs.com/huaweiyun/p/16719334.html

redis和数据库数据一致性问题 - 编程思维

 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节。所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问Mysql等数据库。这样可以大大缓解数据库的压力。具体业务流程如下:        读取缓存步骤一般没有什么问题,但是一旦涉及到数据更新:数据库和缓存更新,就容易出现缓

数据库与缓存双写一致性 - 编程思维

问题你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题?分析先做一个说明,从理论上来说,有两种处理思维,一种需保证数据强一致性,这样性能肯定大打折扣;另外我们可以采用最终一致性,保证性能的基础上,允许一定时间内的数据不一致,但最终数据是一致的。一致性问

深入浅出redistimeseries-分布式数据库 - 编程思维

Part 1 - 背景Redis作为一个灵活的高性能 key-value数据结构存储,可以用来作为数据库、缓存和消息队列。Redis 对比其他 key-value缓存产品有以下特点:Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载到内存使用。Redis 支持字符串(String)、哈

lua脚本在redis事务中的应用实践_京东云开发者-编程思维

使用过Redis事务的应该清楚,Redis事务实现是通过打包多条命令,单独的隔离操作,事务中的所有命令都会按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。事务中的命令要么全部被执行,要么全部都不执行(原子操作)。但其中有命令因业务原因执行失败并不会阻断后续命令的执行,且也无法回滚已经执行过的命

redisson 分布式锁源码 01:可重入锁加锁 - 编程思维

前言相信小伙伴都是使用分布式服务,那一定绕不开分布式服务中数据并发更新问题!单系统很容易想到 Java 的各种锁,像 synchronize、ReentrantLock 等等等,那分布式系统如何处理?当然是使用分布式锁。如果小伙伴不知道什么是分布式锁,那推荐看看石杉老师的突击课或者在网上搜一搜相关资料。当使用 Redi

redisson 分布式锁源码 03:可重入锁互斥 - 编程思维

前言看过可重入锁的 Lua 脚本,已经可以知道当锁存在时,是会加锁失败的。下面看一下,加锁失败之后是如何处理的呢?加锁 Lua 脚本在 lua 脚本中,前两段 if 分别排除了两种情况:锁不存在;锁存在且是自己线程(可重入);剩下的情况就是锁存在,但是不是自己,也就意味着加锁失败。执行 pttl 命令,返回锁的剩余时间

redisson 分布式锁源码 04:可重入锁释放 - 编程思维

前言前面已经了解到了,可重入锁加锁,看门狗以及锁的互斥阻塞。当锁加锁成功之后,锁是如何释放的?主动释放源码入口:RedissonLock#unlock在解锁时会获取当前线程的id。一路往里跟,直接来到 RedissonLock#unlockInnerAsync:分析一下 lua 脚本的内容:如果锁不存在,直接返回 nu