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

 

posted @ 2017-07-15 13:46  疯痴傻  阅读(4811)  评论(2编辑  收藏  举报