EF+Redis(StackExchange.Redis)實現分布式鎖,自測可行


電商平台 都會有搶購的情況,比如 1元搶購。 而搶購 最重要的 就是庫存,很多情況下  庫存處理不好,就會出現超賣現象。

本文將用redis為緩存,StackExchange 框架,消息隊列方式 實現分布式鎖的情況

一,效果

先看效果,

 

窗體下單 構建高並發情況

開多個控制台應用程序 處理訂單

二,配置Redis

  <Redis.Service>
    <DbConfig Name="Order_DBName"  Hosts="127.0.0.1:6379" dbNum="2">

    </DbConfig>
    <DbConfig Name="Product_DbName" Hosts="127.0.0.1:6379" dbNum="1">

    </DbConfig>

模擬用戶下單

      private void button1_Click(object sender, EventArgs e)
        {
            var orderCount = Convert.ToInt32(txt_OrderCount.Text);
            var productId = Convert.ToInt32(txt_ProductId.Text);

            var productCount = Convert.ToInt32(txt_ProductCount.Text);

            for (int i = 0; i < orderCount; i++)
            {
                RedisOrderModel cacheOrder = new RedisOrderModel()
                {
                    Count = productCount,
                    OrderNo = (orderNo += 1).ToString(),
                    ProductId = productId
                };
                orderRedis.Push(cacheOrder);
            }
            

        }

控制台程序 處理訂單

public void QueueList()
        {
            RedisOrderMessage redis = new RedisOrderMessage();
            while (true)
            {
                try
                {
                    var cacheOrder = redis.Pop();
                    if (cacheOrder == null)
                    {
                        Console.WriteLine("無訂單,休息100毫秒");
                        Thread.Sleep(1000);
                        continue;
                    }

                    while (ThreadCount<=0)
                    {
                        Console.WriteLine("線程已滿,休息100毫秒");
                        Thread.Sleep(100);
                    }
                    //ThreadCount--;
                    Thread thread = new Thread(new ThreadStart(cacheOrder.CreateOrder));
                    thread.Start();
                    Console.WriteLine("正在處理訂單,休息100毫秒");
                    Thread.Sleep(100);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message + "," + ex.StackTrace);
                    Thread.Sleep(1000);
                }
                finally
                {
                    ThreadCount++;
                }

            }
        }

 

使用分布式鎖,判斷庫存是否足夠

 public void LockStore(string productId, int count)
        {
            var keyInfo = AddSysCustomKey(productId);

            if (!Exists(keyInfo))
            {
                throw new Exception("商品緩存緩存不存在");
            }
            var redisConfig = ReadRedisConfig.GetRedisConfig(DB_Name);
            var lockdb = redisConfig.GetDatabase(-1);
            var db = redisConfig.GetDatabase();
            var token = Environment.MachineName;
            while (true)
            {
                //db.LockRelease(keyInfo, token);
                var con = lockdb.LockTake(keyInfo, token, TimeSpan.FromSeconds(10.0), CommandFlags.None);
                //var con = db.LockTake(keyInfo, token, TimeSpan.FromSeconds(20), CommandFlags.None);
                if (con)
                {
                    try
                    {
                        var product = ConvertObj<CacheProduct>(db.StringGet(keyInfo));
                        if (product.Count < count)
                        {
                            throw new Exception("數量不夠,下單失敗");
                        }
                        product.Count -= count;
                        var json = ConvertJson(product);
                        db.StringSet(keyInfo, json);
                        
                    }
                    finally
                    {
                        lockdb.LockRelease(keyInfo, token);
                        
                    }
                    break;
                }
            }
           
        }

源碼地址:

 

https://github.com/buruainiaaaa/CacheDemo.git

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM