我想防止账户余额同时提取。 例如,当用户账户余额为500美元时不允许。两个提取 300 美元的并发请求会将用户余额更改为 -100 美元
用户表:
身份证 | 名字 |
---|---|
1 | 约翰 |
2 | 大卫 |
3 | 新浪 |
我有一个名为 transactions 的表,如下所示:
身份证 | 用户 | 金额 | 平衡 |
---|---|---|---|
1 | 约翰 | +350 | 350 |
2 | 约翰 | +250 | 600 |
3 | 约翰 | -100 | 500 |
4 | 约翰 | +400 | 900 |
通过查看上表,我们可以看到用户 John 的账户余额(通过添加金额列的值)为 $900
我创建了一个 API 将库存从一个用户转移到另一个用户
http://127.0.0.1:8000/api/v1/deposit/transfer/FromUser/ToUser/amount
如果我按如下方式运行 api 一次。交易表将会发生变化,如您所见
http://127.0.0.1:8000/api/v1/deposit/transfer/John/David/500
身份证 | 用户 | 金额 | 平衡 |
---|---|---|---|
4 | 约翰 | -500 | 400 |
5 | 大卫 | +500 | 500 |
到目前为止我们没有问题。但是如果上面的api被两个用户同时执行,John的账户余额就会为负数
假设该api被两个用户同时调用。发生以下情况
身份证 | 用户 | 金额 | 平衡 |
---|---|---|---|
1 | 约翰 | +350 | 350 |
2 | 约翰 | +250 | 600 |
3 | 约翰 | -100 | 500 |
4 | 约翰 | +400 | 900 |
5 | 约翰 | -500 | 400 |
6 | 大卫 | +500 | 500 |
7 | 约翰 | -600 | 300 |
8 | 新浪 | +600 | 600 |
现在约翰的总金额栏是多少? -100 美元,这是灾难的开始!
我想在 Laravel 中防止这种情况发生。我可以使用的最佳方法是什么? (我的数据库是mysql)
我个人觉得明显的
MySql
锁定解决方案可能很难做你真正想做的事情。
Laravel
对于这个确切的问题有原子锁。它需要某些缓存驱动程序才能工作,并且您必须弄清楚应该锁定的密钥应该是什么。据我了解,您可能必须锁定约翰和大卫等等。与数据库锁定相比,此解决方案提供了更多控制。
Cache::lock('john', 30)->block(28, function () {
Cache::lock('david', 30)->block(28, function () {
// do account operation
});
});
在此示例中,它将保持锁定 30 秒或直到关闭完成后释放。等待 28 秒直到锁被释放。这里的问题也与负载有关,因为依赖于流量,您将不得不削弱您的解决方案。