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才正确
 

 

转载于:https://www.cnblogs.com/li150dan/p/9529062.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值