嗯,每当我们在本地系统中工作时,一切都像黄油一样工作。这就是为什么我们称“没有比 127.0.0.1 更好的地方了”,但醒来面对现实
生产中的事情并不总是按预期进行。大多数情况下,当您运行应用程序的多个实例时。
?正如您所看到的,如果我们的应用程序的多个实例正在运行,并且假设我们的客户端发出请求,将用户标记为数据库中的付费用户。
看起来还不错吧?到目前为止没问题吧。
嗯,是的,到目前为止没有问题。但是如果我们想编写这样的业务逻辑怎么办:-
⚡️ 众所周知(假设我们在这里使用 MySQL)MySQL 数据库符合 ACID,这意味着任何查询都将是原子的和隔离的。这意味着 MySQL 查询将以原子方式运行,要么通过,要么失败。但中间不会退出。
?但这里有一个问题。想想,想想……
如果在第 2 步,又有一个取消付款的请求,然后该查询首先运行并将用户标记为免费,然后运行第 3 步并将用户标记为已付费,将会发生什么情况。
??万岁,用户甚至无需付费即可访问我们的产品。
✅救星Locks来了
?锁是一种结构,一次只允许一个线程进入临界区(不应被多个工作线程访问的代码块)
因此,我们将在操作完成之前获取锁定并在操作完成后释放:-
现在,问题来了,如果我们使用一些内存锁数据结构或任何基于内存的锁,它将适合我们的应用程序的一个实例。其他运行相同代码并在数据库中更新的实例怎么样?
分布式锁的概念来了
这里的锁充当一种集中式服务,如果我们服务的一个实例获取了锁,那么其他实例就无法使用同一个密钥。
支付服务中可以使用什么键?
?对于进行付款的用户,密钥可以是=“PAYMENT_”+ user_id + amount
的组合这对于每个用户来说都是唯一的。并且当用户付款或取消付款时,该密钥将保持不变。因此,当一个操作发生时,其他操作无法继续,因为这两个操作将尝试获取同一键。
? Key、获取锁、释放锁到底是什么?最重要的是,redis 是如何使用的?
但是单个 Redis 实例存在以下几个问题:-
?因此,如果在主服务器上获取了锁,并且在与副本通信时,如果主服务器在与副本同步之前发生故障。副本将成为主服务器,其中同一密钥上的锁将可用于获取之前在主服务器上获取的锁。
即使有两个实例(主副本),我们服务的两个实例也将能够获取 Redis 上的锁。
获取锁:- 我们将尝试在具有锁过期时间的多个 Redis 实例上获取锁
锁验证:- 如果主要 Redis 实例为客户端获取了锁,则将被视为已获取锁
释放锁:- 释放锁时,所有实例都释放锁
是的,就是这样。
❤️ 感谢您的阅读,并订阅我们的时事通讯以获取更多此类文章:- https://www.serversidedigest.com/
欲了解更多信息:-
以上是如何使用Redis实现分布式锁的详细内容。更多信息请关注PHP中文网其他相关文章!