• Redis用作分布式锁


    Redis用作分布式锁使用的业务逻辑

    。。。

    。。。

    简单的使用案例如下(商品秒杀应用场景)

    准备工作:

    下面商品秒杀应用场景案例演示的前提是Redis已经安装,并可以使用。

    本作者从下载地址:https://download.csdn.net/download/LongtengGensSupreme/12157626下载redis包解压到本地文件目录:E:Source edisfileRedis-x64-3.2.100,如下图所示

    为了方便启动,我们在该目录下新建一个 startredis.bat 的文件,

    然后将以下内容写入文件:redis-server redis.windows.conf

    这个命令其实就是在调用 redis-server.exe 命令来读取 redis.window.conf 的内容,

    双击刚才创建好的 startredis.bat 文件,就能成功的看到 Redis 启动,如下图所示:

    redis-server启动之后放着就可以了

    Redis 自带的一个客户端工具,它可以用来连接到我们当前的 Redis 服务器,点击同一个文件夹下的 redis-cli.exe 文件,启动客户端,如下图

    redis-cli客户端启动成功,如下图所示

    我们做以下测试:在客户端dos界面输入 set key1 value1,回车,可以看到客户端显示:

    在输入 get key1 回车,客户端显示:

     

    通过上述工作,我们便在 Windows 的环境下安装好了Redis,我们的准备工作已完成。下面添加简单的使用案例(商品秒杀应用场景) 如下:

    1、使用Visual studio 2019 Enterprise 创建一个控制台项目 ConsoleTestRedis,选择项目右键,点击NuGet包管理器 ,搜索并添加 StackExchange.Redis

    2、添加客户端请求类 Client,商品秒杀 ProductKill ,Redis分布式锁 RedisLock 类

    客户端请求类 Client代码如下:

    using System.Threading;
    
    namespace ConsoleTestRedis
    {
        /// <summary>
        /// 客户端请求
        /// </summary>
        public class Client
        {
            public void CleitRequest()
            {
                ProductKill productKill = new ProductKill();
    
                for (int i = 0; i < 20; i++)
                {
                    new Thread(() => { productKill.KillProduct(); }).Start();
                }
            }
    
        }
    }

    商品秒杀 ProductKill代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleTestRedis
    {
        /// <summary>
        /// 商品秒杀
        /// </summary>
        public class ProductKill
        {
            /// <summary>
            /// 库存数量
            /// </summary>
            public int repositoryNumber = 10;
    
            /// <summary>
            /// 获取库存的数量
            /// </summary>
            /// <returns></returns>
            public int GetRepositoryNumber()
            {
                return repositoryNumber;
            }
    
            /// <summary>
            /// 扣减库存数量
            /// </summary>
            public void SetRepositoryNumber()
            {
                repositoryNumber--; ;
            }
    
            /// <summary>
            /// 商品秒杀
            /// </summary>
            public void KillProduct()
            {
                //使用Redis分布式锁RedisLock
                RedisLock redisLock = new RedisLock();
                redisLock.Lock();
                var restory = GetRepositoryNumber();
                if (restory == 0)
                {
                    Console.WriteLine($" {Thread.CurrentThread.ManagedThreadId} 不好意思获取失败!商品库存数量:{repositoryNumber}");
                    redisLock.UnLock();
                    return;
                }
                Console.WriteLine($"恭喜 {Thread.CurrentThread.ManagedThreadId} 获取秒杀商品成功!商品库存数量:{repositoryNumber}");
                SetRepositoryNumber();
                redisLock.UnLock();
            }
        }
    }

    Redis分布式锁 RedisLock 类代码如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using StackExchange.Redis;
    
    namespace ConsoleTestRedis
    {
        /// <summary>
        /// Redis分布式锁
        /// </summary>
        public class RedisLock
        {
            /// <summary>
            /// redis分布式连接管理器
            /// </summary>
            public ConnectionMultiplexer _connectionMultiplexer { get; set; }
            /// <summary>
            /// 数据库
            /// </summary>
            public IDatabase _database { get; set; }
    
            public RedisLock()
            {
                //使用的redis api 前提1、安装redis 2、NuGet包管理器添加 StackExchange.Redis
                _connectionMultiplexer = ConnectionMultiplexer.Connect("localhost:6379");
                _database = _connectionMultiplexer.GetDatabase(0);
            }
    
            /// <summary>
            /// 锁住
            /// </summary>
            public void Lock()
            {
                while (true)
                {
                    //LockTake 参数说明 (锁名称,获取所得对象,过期时间)
                    bool isLocked = _database.LockTake("redis_key", Thread.CurrentThread.ManagedThreadId, TimeSpan.FromSeconds(200));
                    if (isLocked)
                    {
                        break;
                    }
                    Thread.Sleep(200);
                }
            }
    
            /// <summary>
            /// 释放
            /// </summary>
            public void UnLock()
            {
                //LockRelease 参数说明 (锁名称,获取所得对象)
                _database.LockRelease("redis_key", Thread.CurrentThread.ManagedThreadId);
                _connectionMultiplexer.Close();
            }
        }
    }

    Program.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleTestRedis
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("。。。。。商品秒杀开始。。。。。。");
                Client client = new Client();
                client.CleitRequest();
                Console.ReadKey();
            }
        }
    }

    注意

    运行的时候要先启动redis服务器(如果未启动redis服务器,则使用RedisLock锁时会报连接错误)

    效果如下:

    对比效果(第一次使用RedisLock锁时候会启动慢一些,以后会很快

    1、未在ProductKill的秒杀方法KillProduct()添加RedisLock分布式锁的时候,

    /// <summary>
            /// 商品秒杀
            /// </summary>
            public void KillProduct()
            {
                ////使用Redis分布式锁RedisLock
                //RedisLock redisLock = new RedisLock();
                //redisLock.Lock();
                var restory = GetRepositoryNumber();
                if (restory == 0)
                {
                    Console.WriteLine($" {Thread.CurrentThread.ManagedThreadId} 不好意思获取失败!商品库存数量:{repositoryNumber}");
                    //redisLock.UnLock();
                    return;
                }
                Console.WriteLine($"恭喜 {Thread.CurrentThread.ManagedThreadId} 获取秒杀商品成功!商品库存数量:{repositoryNumber}");
                SetRepositoryNumber();
                //redisLock.UnLock();
            }

    效果如下:

    2、在ProductKill的秒杀方法KillProduct()添加RedisLock分布式锁的时候,

     /// <summary>
            /// 商品秒杀
            /// </summary>
            public void KillProduct()
            {
                //使用Redis分布式锁RedisLock
                RedisLock redisLock = new RedisLock();//Redis分布式锁RedisLock
                redisLock.Lock();
                var restory = GetRepositoryNumber();
                if (restory == 0)
                {
                    Console.WriteLine($" {Thread.CurrentThread.ManagedThreadId} 不好意思获取失败!商品库存数量:{repositoryNumber}");
                    redisLock.UnLock();//解锁,获取失败时候,解锁
                    return;
                }
                Console.WriteLine($"恭喜 {Thread.CurrentThread.ManagedThreadId} 获取秒杀商品成功!商品库存数量:{repositoryNumber}");
                SetRepositoryNumber();
                redisLock.UnLock();//解锁,获取成功,完成秒杀,也要解锁
            }

    效果如下:

     

  • 相关阅读:
    cocos2d-x JS 定时器暂停方法
    cocos2d-x JS 本地玩家位置跟服务器玩家位置转换相关
    cocos creator 背景音乐音量和音效音量百分比设置
    iPhoneX快速适配,简单到你想哭。
    Cocos Creator Slider(进度条)的三种实现
    图片的本地存储和读取问题
    Creator仿超级玛丽小游戏源码分享
    cocos2d-x 贡献一个oss上传脚本
    Cocos Creator
    Cocos Creator cc.Node.点击事件
  • 原文地址:https://www.cnblogs.com/1175429393wljblog/p/12310417.html
Copyright © 2020-2023  润新知