zoukankan      html  css  js  c++  java
  • Redis分布式锁

    在分布式缓存的应用中,会遇到多个客户端同时争用的问题。这个时候,需要用到分布式锁,得到锁的客户端才有操作权限

    下面通过一个简单例子介绍:
    这里引用的是ServiceStack.Redis
    using ServiceStack.Redis;
    namespace Redis.AcquireLock
    {
        public class RedisHelper
        {
            //实例化Client
            public RedisClient client = new RedisClient("192.168.100.152", 6901);
                  
            /// <summary>
            /// 根据key存储T对象
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public bool Set<T>(string key, T value)
            {
                var result = client.Set<T>(key, value);
                return result;
            }
     
            /// <summary>
            /// 根据key存储T对象,并且设置过期时间
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public bool Set<T>(string key, T value, TimeSpan timeOut)
            {
                var result = client.Set<T>(key, value, timeOut);
                return result;
            }
     
            /// <summary>
            /// 根据key存储T对象,并且设置过期时间
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public bool Set<T>(string key, T value, DateTime timeOut)
            {
                var result = client.Set<T>(key, value, timeOut);
                return result;
            }
        
            /// <summary>
            /// 根据key设置过期时间
            /// </summary>
            /// <param name="key"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public bool ExpireTime(string key, TimeSpan timeOut)
            {
                var result = client.ExpireEntryIn(key, timeOut);
                return result;
            }
     
            /// <summary>
            /// 根据key设置过期时间
            /// </summary>
            /// <param name="key"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public bool ExpireTime(string key, DateTime timeOut)
            {
                var result = client.ExpireEntryAt(key, timeOut);
                return result;
            }
     
            /// <summary>
            /// 根据key获取对应的对象T
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <returns></returns>
            public T Get<T>(string key)
            {
                var result = client.Get<T>(key);
                return result;
            }
     
            /// <summary>
            /// 移除/删除对应key
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public bool Remove(string key)
            {
                return client.Remove(key);
            }
     
            /// <summary>
            /// 删除对应key(返回被删除 key 的数量)
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public long Delete(string key)
            {
                return client.Del(key); 
            }
     
            /// <summary>
            /// 判断key是否存在,存在返回1,不存在返回0
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public long Exists(string key)
            {
                return client.Exists(key);
            }
     
            /// <summary>
            /// 判断key是否存在,存在返回true,不存在返回false
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public bool ContainsKey(string key)
            {          
                return client.ContainsKey(key);
            }
     
            /// <summary>
            /// Redis分布式锁
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public IDisposable AcquireLock(string key)
            {
                return client.AcquireLock(key);
            }
     
            /// <summary>
            /// Redis分布式锁,并且设置过期时间
            /// </summary>
            /// <param name="key"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public IDisposable AcquireLock(string key, TimeSpan timeOut)
            {
                return client.AcquireLock(key, timeOut);
            }
        }
    }
    View Code

    控制台程序: 

    namespace Redis.AcquireLock
    {
        /// <summary>
        /// Redis分布式锁简单实例
        /// </summary>
        public class Program
        {
            public static void Main(string[] args)
            {
                RedisHelper redis = new RedisHelper();
                Console.WriteLine("线程开始前,输出" + redis.Get<int>("redisKey"));
                Console.WriteLine("线程开始前,输出" + redis.Remove("redisKey"));
                Console.WriteLine("线程开始前,输出" + redis.Delete("redisKey"));
                redis.Set<int>("redisKey", 0);
                //定义两个线程
                Thread myThread1 = new Thread(new ParameterizedThreadStart(AddVal));          
                Thread myThread2 = new Thread(AddVal);
                myThread1.Start("1");          
                myThread2.Start();
                Console.WriteLine("等待两个线程结束");         
                Console.ReadKey();         
            }
    
            public static void AddVal(object num)
            {
                RedisHelper redis = new RedisHelper();
                for (int i = 0; i < 500; i++)
                {
                    //int result = redis.Get<int>("redisKey");
                    //redis.Set<int>("redisKey", result + 1);
    
                    //返回的是IDisposable,证明我们需要手动释放资源,所以这里使用了using完事后自动释放资源
                    //如果1秒不释放锁 自动释放,避免死锁
                    using (redis.AcquireLock("redis_lock", TimeSpan.FromSeconds(1)))
                    {
                        int result = redis.Get<int>("redisKey");
                        redis.Set<int>("redisKey", result + 1);
                    }         
                }
                Console.WriteLine("线程" + num + "结束,输出" + redis.Get<int>("redisKey"));
                //设置缓存过期时间
                redis.ExpireTime("redisKey", TimeSpan.FromSeconds(10));
            }
        }
    }
    View Code

     运行结果效果图说明:

    图一是没有加分布式锁的情况下执行结果
     图二是加分布式锁的情况下执行结果,两个线程各循环500次,最终缓存值应该为1000才正确
     
  • 相关阅读:
    [LeetCode]2. Add Two Numbers链表相加
    Integration between Dynamics 365 and Dynamics 365 Finance and Operation
    向视图列添加自定义图标和提示信息 -- PowerApps / Dynamics365
    Update the Power Apps portals solution
    Migrate portal configuration
    Use variable to setup related components visible
    Loyalty management on Retail of Dynamic 365
    Modern Fluent UI controls in Power Apps
    Change screen size and orientation of a canvas app in Power App
    Communication Plan for Power Platform
  • 原文地址:https://www.cnblogs.com/li150dan/p/9529062.html
Copyright © 2011-2022 走看看