• Memcache分布式锁


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

    下面通过一个简单例子介绍:
    这里引用的是Memcached.ClientLibrary.dll
    //引用
    using Memcached.ClientLibrary;
    namespace Memcache.AddLock
    {
        public class MemcacheHelper
        {
            //实例化Client
            public MemcachedClient MClient;
    
            public MemcacheHelper()
            {
                //参数设置
                string SockIOPoolName = "demo";     
                string[] MemcacheServiceList = { "127.0.0.1:11211" };
    
                //设置连接池
                SockIOPool SPool = SockIOPool.GetInstance(SockIOPoolName);
                SPool.SetServers(MemcacheServiceList);
                SPool.Initialize();
    
                MClient = new MemcachedClient();
                MClient.PoolName = SockIOPoolName;
                //是否启用压缩数据:如果启用了压缩,数据压缩长于门槛的数据将被储存在压缩的形式
                MClient.EnableCompression = false;
                ////压缩设置,超过指定大小的都压缩 
                //MClient.CompressionThreshold = 1024 * 1024;           
            }
                 
            /// <summary>
            /// 根据key存储对象
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public bool Set(string key, object value)
            {
                var result = MClient.Set(key, value);
                return result;
            }
                 
            /// <summary>
            /// 根据key存储对象,并且设置过期时间
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public bool Set(string key, object value, DateTime timeOut)
            {
                var result = MClient.Set(key, value, timeOut);
                return result;
            }      
         
            /// <summary>
            /// 根据key获取对应的对象
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public object Get(string key)
            {
                var result = MClient.Get(key);
                return result;
            }
    
            /// <summary>
            /// 替换对应key的value
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <returns></returns>
            public bool Replace(string key, object value)
            {
                var result = MClient.Replace(key, value);
                return result;
            }
    
            /// <summary>
            /// 删除对应key
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public bool Delete(string key)
            {
                return MClient.Delete(key);
            }
    
            /// <summary>
            /// 删除对应key,并设置从内存中移除的时间点
            /// </summary>
            /// <param name="key"></param>
            /// <param name="timeOut"></param>
            /// <returns></returns>
            public bool Delete(string key, DateTime timeOut)
            {
                return MClient.Delete(key, timeOut);
            }
    
            /// <summary>
            /// 判断key是否存在,存在返回true,不存在返回false
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public bool KeyExists(string key)
            {
                return MClient.KeyExists(key);
            }
                  
            /// <summary>
            /// Memcache分布式锁
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <returns>当key存在返回false,当key不存在返回true</returns>
            public bool Add(string key, object value)
            {
                return MClient.Add(key, value);
            }
    
            /// <summary>
            /// Memcache分布式锁,并且设置过期时间
            /// Memcached分布式锁可以使用 Add 命令,该命令只有KEY不存在时,才进行添加,否则不会处理。Memcached 所有命令都是原子性的,并发下add 同一个KEY,只会一个会成功。
            /// 利用这个原理,可以先定义一个锁 LockKEY,Add 成功的认为是得到锁。并且设置[过期超时] 时间,保证宕机后,也不会死锁。
            /// 在完成具体操作后,判断锁 LockKEY 是否已超时。如果超时则不删除锁,如果不超时则 Delete 删除锁。
            /// </summary>
            /// <param name="key"></param>
            /// <param name="value"></param>
            /// <param name="timeOut"></param>
            /// <returns>当key存在返回false,当key不存在返回true</returns>
            public bool Add(string key, object value, DateTime timeOut)
            {
                return MClient.Add(key, value, timeOut);
            }
        }
    }
    View Code

    控制台程序:

    //引用
    using Memcached.ClientLibrary;
    namespace Memcache.AddLock
    {
        /// <summary>
        /// Memcache分布式锁简单实例
        /// </summary>
        public class Program
        {
            //创建一个公共类
            public static MemcacheHelper memcache;
    
            public static void Main(string[] args)
            {                   
                memcache = new MemcacheHelper();
                Console.WriteLine("线程开始前,输出" + memcache.Get("demoKey"));        
                var result = memcache.Delete("demoKey");
                Console.WriteLine("线程开始前,输出" + memcache.Get("demoKey") + ",删除对应key返回:" + result);
                Console.WriteLine("线程开始前,输出" + memcache.Delete("LockKey"));                 
                memcache.Set("demoKey", "0");
                //定义三个线程
                Thread myThread1 = new Thread(new ParameterizedThreadStart(AddVal));
                Thread myThread2 = new Thread(new ParameterizedThreadStart(AddVal));
                Thread myThread3 = new Thread(AddVal);
                myThread1.Start("1");
                myThread2.Start("2");           
                myThread3.Start();
                Console.WriteLine("等待两个线程结束");
                Console.ReadKey();            
            }
                  
            public static void AddVal(object num)
            {                          
                for (int i = 0; i < 500; i++)
                {
                    //int result = int.Parse(memcache.Get("demoKey").ToString());
                    //memcache.Set("demoKey", (result + 1).ToString());
    
                    //如果0.5秒不释放锁 自动释放,避免死锁
                    if (memcache.Add("LockKey", "Hello World", DateTime.Now.AddSeconds(0.5)))
                    {
                        //得到锁
                        try
                        {
                            int result = int.Parse(memcache.Get("demoKey").ToString());
                            memcache.Set("demoKey", (result + 1).ToString());
    
                            //注意:这里最好加上主动去删除锁
                            //检查锁是否超时(直接去删除就可以)                       
                            memcache.Delete("LockKey");
                        }
                        catch (Exception ex)
                        {
                            //发生异常时也直接删除锁
                            memcache.Delete("LockKey");
                        }
                    }
                    else
                    {
                        i = i - 1; //没有得到锁时等待
                    }
                }
                Console.WriteLine("线程" + num + "结束,输出" + memcache.Get("demoKey"));          
            }
        }
    }
    View Code

    运行结果效果图说明:

    图一是没有加分布式锁的情况下执行结果
     
    图二是加分布式锁的情况下执行结果,三个线程各循环500次,最终缓存值应该为1500才正确
     
  • 相关阅读:
    u3d Mecanim动画
    四元数的共轭和逆
    c++ 单例模式
    GVIM、VIM
    Linux磁盘管理——虚拟文件系统
    Linux磁盘管理——MBR 与 GPT
    Link monitoring
    Linux高级网络设置——将多个网卡设置成一个网卡
    Linux高级网络设置——给网卡绑定多个IP
    DNS原理极限剖析
  • 原文地址:https://www.cnblogs.com/li150dan/p/9529090.html
Copyright © 2020-2023  润新知