使用laravel解決庫存超出的幾個方案

一位不願意透露姓名的楊先生發表於2021-06-08

資料庫欄位

使用laravel解決庫存超出的幾個方案

1.錯誤的示範

    /**
     * 錯誤示範
     * Create by Peter Yang
     * 2021-06-08 10:57:59
     * @return string
     */
    function test1()
    {

        //商品id
        $id = request()->input('id');

        $product = Product::where('id', $id)->firstOrFail();

        if ($product->num <= 0) {

            return "賣光啦!!";
        }

        //庫存減1
        $product->decrement('num');

        return "success";

    }

使用go模擬併發

package main

import (
    "fmt"
    "github.com/PeterYangs/tools/http"
    "sync"
)

func main() {

    client := http.Client()

    wait := sync.WaitGroup{}

    for i := 0; i < 50; i++ {

        wait.Add(1)

        go func(w *sync.WaitGroup) {

            defer w.Done()

            res, _ := client.Request().GetToString("http://www.api/test1?id=1")

            fmt.Println(res)

        }(&wait)

    }

    wait.Wait()

}

在資料庫中檢視庫存

使用laravel解決庫存超出的幾個方案
庫存已超出

2.redis原子鎖

    /**
     * redis原子鎖
     * Create by Peter Yang
     * 2021-06-08 11:00:31
     */
    function test2()
    {
        //商品id
        $id = request()->input('id');

        $lock = \Cache::lock("product_" . $id, 10);

        try {

            //最多等待5秒,5秒後未獲取到鎖,則丟擲異常
            $lock->block(5);

            $product = Product::where('id', $id)->firstOrFail();

            if ($product->num <= 0) {

                return "賣光啦!!";
            }
            //庫存減1
            $product->decrement('num');

            return 'success';

        }catch (LockTimeoutException $e) {

            return '當前人數過多';

        } finally {

            optional($lock)->release();
        }
    }

庫存正常

使用laravel解決庫存超出的幾個方案

3.mysql悲觀鎖

    /**
     * mysql悲觀鎖
     * Create by Peter Yang
     * 2021-06-08 11:00:47
     */
    function test3()
    {

        //商品id
        $id = request()->input('id');

        try {
            \DB::beginTransaction();
            $product = Product::where('id', $id)->lockForUpdate()->first();

            if ($product->num <= 0) {

                return "賣光啦!!";
            }

            //庫存減1
            $product->decrement('num');

            \DB::commit();

            return "success";

        } catch (\Exception $exception) {

        }

    }

庫存正常

使用laravel解決庫存超出的幾個方案

4.mysql樂觀鎖

    /**
     * mysql樂觀鎖
     * Create by Peter Yang
     * 2021-06-08 11:00:47
     */
    function test4()
    {

        //商品id
        $id = request()->input('id');

        $product = Product::where('id', $id)->first();

        if ($product->num <= 0) {

            return "賣光啦!!";
        }

        //修改前檢查庫存和之前是否一致,不一致說明已經有變動,則放棄更改
        $res = \DB::update('UPDATE `product` SET num = num -1 WHERE id = ? AND num=?', [$id, $product->num]);

        if (!$res) {

            return '當前人數過多';

        }

        return 'success';


    }

庫存正常

使用laravel解決庫存超出的幾個方案

優化樂觀鎖

修改庫存的sql修改為

\DB::update('UPDATE `product` SET num = num -1 WHERE id = ? AND num-1 >= 0', [$id]);
本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章