Blogger Information
Blog 10
fans 0
comment 0
visits 7000
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
laravel解决超卖的几个方法
礼物粑粑
Original
621 people have browsed it

数据库字段

1 错误的示范

  1. function test1()
  2. {
  3. $id = request()->input('id');
  4. $product = Product::where('id', $id)->firstOrFail();
  5. if ($product->num <= 0) return "卖光啦!!";
  6. $product->decrement('num'); //库存减1
  7. return "success";
  8. }
使用 go 模拟并发
  1. package main
  2. import (
  3. "fmt"
  4. "github.com/PeterYangs/tools/http"
  5. "sync"
  6. )
  7. func main() {
  8. client := http.Client()
  9. wait := sync.WaitGroup{}
  10. for i := 0; i < 50; i++ {
  11. wait.Add(1)
  12. go func(w *sync.WaitGroup) {
  13. defer w.Done()
  14. res, _ := client.Request().GetToString("http://www.api/test1?id=1")
  15. fmt.Println(res)
  16. }(&wait)
  17. }
  18. wait.Wait()
  19. }

2 方案1 redis 原子锁

  1. function test2()
  2. {
  3. $id = request()->input('id');
  4. $lock = \Cache::lock("product_" . $id, 10);
  5. try {
  6. //最多等待5秒,5秒后未获取到锁,则抛出异常
  7. $lock->block(5);
  8. $product = Product::where('id', $id)->firstOrFail();
  9. if ($product->num <= 0) {
  10. return "卖光啦!!";
  11. }
  12. $product->decrement('num');
  13. return 'success';
  14. }catch (LockTimeoutException $e) {
  15. return '当前人数过多';
  16. } finally {
  17. optional($lock)->release();
  18. }
  19. }

3 方案2 mysql 悲观锁

  1. function test3()
  2. {
  3. $id = request()->input('id');
  4. try {
  5. \DB::beginTransaction();
  6. $product = Product::where('id', $id)->lockForUpdate()->first();
  7. if ($product->num <= 0) {
  8. return "卖光啦!!";
  9. }
  10. $product->decrement('num');
  11. \DB::commit();
  12. return "success";
  13. } catch (\Exception $exception) {
  14. }
  15. }

库存正常

4 方案3 mysql 乐观锁

  1. function test4()
  2. {
  3. $id = request()->input('id');
  4. $product = Product::where('id', $id)->first();
  5. if ($product->num <= 0) {
  6. return "卖光啦!!";
  7. }
  8. //修改前检查库存和之前是否一致,不一致说明已经有变动,则放弃更改
  9. $res = \DB::update('UPDATE `product` SET num = num -1 WHERE id = ? AND num=?', [$id, $product->num]);
  10. if (!$res) {
  11. return '当前人数过多';
  12. }
  13. return 'success';
  14. }

库存正常
优化乐观锁
修改库存的 sql 修改为
\DB::update(‘UPDATE product SET num = num -1 WHERE id = ? AND num-1 >= 0’, [$id]);

5 方案4 redis 存储库存

  1. function test5()
  2. {
  3. $id = request()->input('id');
  4. $num = Redis::command('get', ['product_' . $id]);
  5. if ($num <= 0) {
  6. return "卖完啦!";
  7. }
  8. $re = Redis::command('decrby', ['product_' . $id, 1]);
  9. //减多了回滚
  10. if ($re < 0) {
  11. Redis::command('incrby', ['product_' . $id, 1]);
  12. return "卖完啦!";
  13. }
  14. return 'success';
  15. }

库存正常
原文链接:https://blog.csdn.net/weixin_41882200/article/details/119249367
欢迎补充

Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post