zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    js 数组,字符串,json互相转换
    数据库相关概念
    信号量,Event, 定时器
    解决Navicat远程连接mysql很慢的方法
    Ubuntu安装mycli,让mysql命令行可以自动提示
    Requests模块调用接口
    selenium chrome浏览器对应chrome版本
    selenium 元素定位+显示等待 方法封装
    smtplib 发送文本文件和附件文件 的类方法封装
    python 数据库的方法封装
  • 原文地址:https://www.cnblogs.com/buruainiaaaa/p/7182483.html
Copyright © 2011-2022 走看看