Redis分佈式鎖

在分佈式緩存的應用中,會遇到多個客戶端同時爭用的問題。這個時候,須要用到分佈式鎖,獲得鎖的客戶端纔有操做權限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才正確
 
相關文章
相關標籤/搜索