zoukankan      html  css  js  c++  java
  • 利用Redis实现分布式锁最佳解决方案

    一、缘起

    在分布式业务中,涉及到同一份数据的增删改时,很容易出现并发问题,导致最终结果出现异常,为了解决此类问题,我们引入了分布式锁的概念。

    二、设计

    由于网上教程实现逻辑冗余复杂(至今没看懂),这里我就按照自己的思路设计了一下,非常的简单实用,非常的银杏化。

    1、采用Redis实现分布式锁存储

    2、采用多线程多实例模拟分布式程序并发访问场景

    3、采用Redis模拟分布式业务数据存储

    三、代码

    入口函数

    class Program
        {
            static void Main(string[] args)
            {
                //利用多线程,多实例,模拟分布式并发请求
                for (var i = 0; i < 10; i++)
                {
                    Task.Run(() =>
                    {
                        new TestService().Run();
                    });
                }
    
                Console.ReadKey();
            }
        }

    业务函数

     public class TestService
        {
            private readonly RedisCacheService _cacheService;
            private readonly RedisLockService _lockService;
    
            public TestService()
            {
                //创建Redis服务,这里的Redis用于存储业务数据
                _cacheService = new RedisCacheService(new RedisCacheOptions
                {
                    Configuration = "Redis连接字符串"
                });
                //创建Redis锁服务,用于锁创建
                _lockService = new RedisLockService();
            }
    
            public void Run()
            {
                //创建锁
                _lockService.Create("test");
    
                //设置数量
                SetCount();
                //显示数量
                ShowCount();
    
                //释放锁
                _lockService.Clear("test");
            }
    
            public void SetCount()
            {
                _cacheService.Set("count", _cacheService.Get<int>("count") + 1);
            }
    
            public void ShowCount()
            {
                Console.WriteLine($"当前数量:{_cacheService.Get<int>("count")}");
            }
        }

    锁函数

    public class RedisLockService
        {
            private readonly RedisCacheService _cacheService;
    
            public RedisLockService()
            {
                //创建Redis服务,这里的Redis用于存储锁数据
                _cacheService = new RedisCacheService(new RedisCacheOptions
                {
                    Configuration = "Redis连接字符串"
                });
            }
    
            /// <summary>
            /// 创建锁
            /// </summary>
            /// <param name="name">锁名</param>
            public void Create(string name)
            {
                //锁标识,证明是当前程序创建的锁
                var flag = CommonUtil.NewGuid();
    
                while (!Get(name, flag)) //锁验证,若未获取到自己创建的锁,则进入循环,反之跳出循环执行后续代码
                {
                    //锁检测,若发现锁已被占用,则进入循环等待50ms,反之跳出循环执行后续代码
                    while (Check(name))
                    {
                        Thread.Sleep(50);
                    }
    
                    //锁设置,设置属于自己的锁,由于存在并发问题,锁有可能被其他程序覆盖,因此才需要循环进行锁验证
                    Set(name, flag);
                }
    
            }
    
            /// <summary>
            /// 释放锁
            /// </summary>
            /// <param name="name">锁名</param>
            public void Clear(string name)
            {
                _cacheService.Remove($"lock-{name}");
            }
    private bool Check(string name) { return _cacheService.IsExist($"lock-{name}"); } private bool Get(string name, string flag) { return _cacheService.Get<string>($"lock-{name}") == flag; } private void Set(string name, string flag) { //这里设置的Redis过期时间为30秒,防止出现死锁,具体业务具体设置 _cacheService.Set($"lock-{name}", flag, 30); } }

    四、效果

    加锁前

     加锁后

     

  • 相关阅读:
    数据类型
    一些骚操作
    re
    多任务
    监听按钮点击事件
    监听按钮点击事件
    监听按钮点击事件
    将博客搬至博客园
    将博客搬至博客园
    将博客搬至博客园
  • 原文地址:https://www.cnblogs.com/rhyheart/p/15246605.html
Copyright © 2011-2022 走看看