• 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才正确
     
  • 相关阅读:
    Excel文档间的数据替换 ---电脑版APP 自动操作魔法师
    【css】zSass
    【javascript】利用 a 标签自动解析 url
    【javascript】console 让 js 调试更简单
    【规范】javascript 变量命名规则
    【规范】前端编码规范——一般规范
    【jquery】一款不错的音频播放器——Amazing Audio Player
    【分享】分享一款不错的网页视频播放器
    【分享】分享一个值得前端开发收藏的网站
    【html】button按钮的一些问题
  • 原文地址:https://www.cnblogs.com/li150dan/p/9529062.html
Copyright © 2020-2023  润新知