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才正确
     
  • 相关阅读:
    在Windows10上安装Linux子系统
    《ln--软连接》--linux命令
    【转】最详细的Log4J使用教程
    7 str字符串的内置函数
    6.1 range创建数值序列
    6 int数值类型的内置函数
    linux shell 字符串操作(长度,查找,截取,替换)详解
    awk 字符串处理函数
    Shell字符串截取
    5 python基本数据类型
  • 原文地址:https://www.cnblogs.com/li150dan/p/9529062.html
Copyright © 2011-2022 走看看