最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

redis使用Lua腳本解決多線程下的超賣(mài)問(wèn)題及原因解析

 更新時(shí)間:2023年05月08日 09:23:05   作者:David.Meng  
這篇文章主要介紹了redis使用Lua腳本解決多線程下的超賣(mài)問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一.多線程下引起的超賣(mài)問(wèn)題呈現(xiàn)

1.1.我先初始化庫(kù)存數(shù)量為1、訂單數(shù)量為0

1.2.開(kāi)啟3個(gè)線程去執(zhí)行業(yè)務(wù)

業(yè)務(wù)為:判斷如果說(shuō)庫(kù)存數(shù)量大于0,則庫(kù)存減1,訂單數(shù)量加1

結(jié)果為:庫(kù)存為-2,訂單數(shù)量為3

原因:如下圖所示,這是因?yàn)榉謩e有6個(gè)指令(3個(gè)庫(kù)存減1指令,3個(gè)訂單數(shù)量加1指令)在redis服務(wù)端執(zhí)行導(dǎo)致的。

namespace MengLin.Shopping.Redis.LuaScript
{
    public class SecKillOriginal
    {
        static SecKillOriginal()
        {
            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                //刪除當(dāng)前數(shù)據(jù)庫(kù)中的所有Key, 默認(rèn)刪除的是db0
                client.FlushDb();
                //刪除所有數(shù)據(jù)庫(kù)中的key 
                client.FlushAll();
                //初始化庫(kù)存數(shù)量為1和訂單數(shù)量為0
                client.Set("inventoryNum", 1);
                client.Set("orderNum", 0);
            }
        }
        public static void Show()
        {
            for (int i = 0; i < 3; i++)
            {
                Task.Run(() =>
                {
                    using (RedisClient client = new RedisClient("127.0.0.1", 6379))
                    {
                        int inventoryNum = client.Get<int>("inventoryNum");
                        //如果庫(kù)存數(shù)量大于0
                        if (inventoryNum > 0)
                        {
                            //給庫(kù)存數(shù)量-1
                            var inventoryNum2 = client.Decr("inventoryNum");
                            Console.WriteLine($"給庫(kù)存數(shù)量-1后的數(shù)量-inventoryNum: {inventoryNum2}");
                            //給訂單數(shù)量+1
                            var orderNum = client.Incr("orderNum");
                            Console.WriteLine($"給訂單數(shù)量+1后的數(shù)量-orderNum: {orderNum}");
                        }
                        else
                        {
                            Console.WriteLine($"搶購(gòu)失敗: 原因是因?yàn)闆](méi)有庫(kù)存");
                        }
                    }
                });
            }
        }
    }
}

二.使用Lua腳本解決多線程下超賣(mài)的問(wèn)題以及為什么

2.1.修改后的代碼如下

結(jié)果為:如下圖所示,庫(kù)存為0、訂單數(shù)量為1,并沒(méi)有出現(xiàn)超賣(mài)的問(wèn)題且有2個(gè)線程搶不到。

namespace MengLin.Shopping.Redis.LuaScript
{
    public class SecKillLua
    {
        /// <summary>
        /// 使用Lua腳本解決多線程下變賣(mài)的問(wèn)題
        /// </summary>
        static SecKillLua()
        {
            using (RedisClient client = new RedisClient("127.0.0.1", 6379))
            {
                //刪除當(dāng)前數(shù)據(jù)庫(kù)中的所有Key, 默認(rèn)刪除的是db0
                client.FlushDb();
                //刪除所有數(shù)據(jù)庫(kù)中的key 
                client.FlushAll();
                //初始化庫(kù)存數(shù)量為1和訂單數(shù)量為0
                client.Set("inventoryNum", 1);
                client.Set("orderNum", 0);
            }
        }
        public static void Show()
        {
            for (int i = 0; i < 3; i++)
            {
                Task.Run(() =>
                {
                    using (RedisClient client = new RedisClient("127.0.0.1", 6379))
                    {
                        //如果庫(kù)存數(shù)量大于0,則給庫(kù)存數(shù)量-1,給訂單數(shù)量+1
                        var lua = @"local count = redis.call('get',KEYS[1])
                                        if(tonumber(count)>0)
                                        then
                                            --return count
                                            redis.call('INCR',ARGV[1])
                                            return redis.call('DECR',KEYS[1])
                                        else
                                            return -99
                                        end";
                        Console.WriteLine(client.ExecLuaAsString(lua, keys: new[] { "inventoryNum" }, args: new[] { "orderNum" }));
                    }
                });
            }
        }
    }
}

三.為什么使用Lua腳本就能解決多線程下的超賣(mài)問(wèn)題呢?

是因?yàn)長(zhǎng)ua腳本把3個(gè)指令,分別是:判斷庫(kù)存數(shù)量是否大于0、庫(kù)存減1、訂單數(shù)量加1,這3個(gè)指令打包放在一起執(zhí)行了且不能分割,相當(dāng)于組裝成了原子指令,所以避免了超賣(mài)問(wèn)題。

在redis中我們盡量使用原子指令從而避免一些并發(fā)的問(wèn)題。

到此這篇關(guān)于redis使用Lua腳本解決多線程下的超賣(mài)問(wèn)題以及為什么的文章就介紹到這了,更多相關(guān)redis多線程超賣(mài)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用redis實(shí)現(xiàn)聊天記錄轉(zhuǎn)存功能的全過(guò)程

    利用redis實(shí)現(xiàn)聊天記錄轉(zhuǎn)存功能的全過(guò)程

    社交類(lèi)軟件聊天功能必不可少,聊天記錄存儲(chǔ)的方式也比較多,比如文本,數(shù)據(jù)庫(kù),云等等,但是最好的選擇還是redis進(jìn)行存儲(chǔ),這篇文章主要給大家介紹了關(guān)于如何利用redis實(shí)現(xiàn)聊天記錄轉(zhuǎn)存功能的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • redis實(shí)現(xiàn)簡(jiǎn)單分布式鎖

    redis實(shí)現(xiàn)簡(jiǎn)單分布式鎖

    這篇文章主要介紹了redis實(shí)現(xiàn)簡(jiǎn)單分布式鎖,文中通過(guò)代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2013-09-09
  • RabbitMQ+redis+Redisson分布式鎖+seata實(shí)現(xiàn)訂單服務(wù)的流程分析

    RabbitMQ+redis+Redisson分布式鎖+seata實(shí)現(xiàn)訂單服務(wù)的流程分析

    訂單服務(wù)涉及許多方面,分布式事務(wù),分布式鎖,例如訂單超時(shí)未支付要取消訂單,訂單如何防止重復(fù)提交,如何防止超賣(mài)、這里都會(huì)使用到,這篇文章主要介紹了RabbitMQ+redis+Redisson分布式鎖+seata實(shí)現(xiàn)訂單服務(wù)的流程分析,需要的朋友可以參考下
    2024-07-07
  • Redis本地/遠(yuǎn)程(外部)連接失敗問(wèn)題及解決

    Redis本地/遠(yuǎn)程(外部)連接失敗問(wèn)題及解決

    這篇文章主要介紹了Redis本地/遠(yuǎn)程(外部)連接失敗問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Redis源碼分析之set?和?sorted?set?使用

    Redis源碼分析之set?和?sorted?set?使用

    本文介紹了Redis?中的?set?和?sorted?set?使用源碼實(shí)現(xiàn)分析,Redis?的?Set?是?String?類(lèi)型的無(wú)序集合,集合成員是唯一的,sorted?set有序集合和集合一樣也是?string?類(lèi)型元素的集合,對(duì)Redis?set?和?sorted?set使用相關(guān)知識(shí)感興趣的朋友一起看看吧
    2022-03-03
  • Redis 分片集群的實(shí)現(xiàn)

    Redis 分片集群的實(shí)現(xiàn)

    本文主要介紹了Redis 分片集群的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • 使用SpringBoot集成redis的方法

    使用SpringBoot集成redis的方法

    這篇文章主要介紹了SpringBoot集成redis的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • Redis 命令的詳解及簡(jiǎn)單實(shí)例

    Redis 命令的詳解及簡(jiǎn)單實(shí)例

    這篇文章主要介紹了Redis 命令的詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,這里提供基礎(chǔ)語(yǔ)法及使用實(shí)例,需要的朋友可以參考下
    2017-08-08
  • Redis簡(jiǎn)易延時(shí)隊(duì)列的實(shí)現(xiàn)示例

    Redis簡(jiǎn)易延時(shí)隊(duì)列的實(shí)現(xiàn)示例

    在實(shí)際的業(yè)務(wù)場(chǎng)景中,經(jīng)常會(huì)遇到需要延時(shí)處理的業(yè)務(wù),本文就來(lái)介紹有下Redis簡(jiǎn)易延時(shí)隊(duì)列的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • redis發(fā)布訂閱_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    redis發(fā)布訂閱_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了redis發(fā)布訂閱,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08

最新評(píng)論

华蓥市| 南安市| 塘沽区| 井陉县| 成都市| 天气| 买车| 清丰县| 彝良县| 和政县| 阜南县| 福清市| 嵊州市| 扎鲁特旗| 凤台县| 博兴县| 蚌埠市| 盱眙县| 东乌| 健康| 扎赉特旗| 定安县| 鄄城县| 衡阳市| 澜沧| 新蔡县| 乌海市| 汶川县| 德钦县| 长汀县| 稻城县| 德江县| 鲁山县| 客服| 上虞市| 宁蒗| 英山县| 安平县| 霍邱县| 元朗区| 中阳县|