Memcache分布式锁
在分布式缓存的应用中,会遇到多个客户端同时争用的问题。这个时候,需要用到分布式锁,得到锁的客户端才有操作权限
//引用
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);
}
}
}
控制台程序:
//引用
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", "");
//定义三个线程
Thread myThread1 = new Thread(new ParameterizedThreadStart(AddVal));
Thread myThread2 = new Thread(new ParameterizedThreadStart(AddVal));
Thread myThread3 = new Thread(AddVal);
myThread1.Start("");
myThread2.Start("");
myThread3.Start();
Console.WriteLine("等待两个线程结束");
Console.ReadKey();
} public static void AddVal(object num)
{
for (int i = ; i < ; 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 + ).ToString()); //注意:这里最好加上主动去删除锁
//检查锁是否超时(直接去删除就可以)
memcache.Delete("LockKey");
}
catch (Exception ex)
{
//发生异常时也直接删除锁
memcache.Delete("LockKey");
}
}
else
{
i = i - ; //没有得到锁时等待
}
}
Console.WriteLine("线程" + num + "结束,输出" + memcache.Get("demoKey"));
}
}
}
运行结果效果图说明:


Memcache分布式锁的更多相关文章
- Memcache分布式锁 转发 https://www.cnblogs.com/li150dan/p/9529090.html
在分布式缓存的应用中,会遇到多个客户端同时争用的问题.这个时候,需要用到分布式锁,得到锁的客户端才有操作权限 下面通过一个简单例子介绍: 这里引用的是Memcached.ClientLibrary.d ...
- RedissonLock分布式锁源码分析
最近碰到的一个问题,Java代码中写了一个定时器,分布式部署的时候,多台同时执行的话就会出现重复的数据,为了避免这种情况,之前是通过在配置文件里写上可以执行这段代码的IP,代码中判断如果跟这个IP相等 ...
- Java分布式锁看这篇就够了
### 什么是锁? 在单进程的系统中,当存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量. 而同步的本质是通过锁来实现的 ...
- RedLock.Net - 基于Redis分布式锁的开源实现
工作中,经常会遇到分布式环境中资源访问冲突问题,比如商城的库存数量处理,或者某个事件的原子性操作,都需要确保某个时间段内只有一个线程在访问或处理资源. 因此现在网上也有很多的分布式锁的解决方案,有数据 ...
- 使用Redis作为分布式锁的一些注意点
Redis实现分布式锁 最近看分布式锁的过程中看到一篇不错的文章,特地的加工一番自己的理解: Redis分布式锁实现的三个核心要素: 1.加锁 最简单的方法是使用setnx命令.key是锁的唯一标识, ...
- .Net分布式锁
项目中一般使用lock作为锁,以便于多线程操作确保库内数据统一.但是如果分布式部署项目,则这种锁就是去了意义,这时可以使用redis或memcache的add方法作为分布式锁. 栗子
- c# 基于redis分布式锁
在单进程的系统中,当存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步,使其在修改这种变量时能够线性执行消除并发修改变量. 而同步的本质是通过锁来实现的.为了实现多个线程在 ...
- 分布式锁--Redis小试牛刀
参考文章: Redis分布式锁的正确实现方式 分布式锁看这篇就够了 在这两篇文章的指引下亲测 Redis分布式锁 引言 分布式系统一定会存在CAP权衡问题,所以才会出现分布式锁 什么是CAP理论? 为 ...
- Elasticsearch系列---实现分布式锁
概要 Elasticsearch在文档更新时默认使用的是乐观锁方案,而Elasticsearch利用文档的一些create限制条件,也能达到悲观锁的效果,我们一起来看一看. 乐观锁与悲观锁 乐观锁 E ...
随机推荐
- C# 任务、线程、同步(二)
取消架构 1.Parallel.For()方法的取消 static void CancelParallelLoop() { var cts = new CancellationTokenSource( ...
- BZOJ 2039 / Luogu P1791 [2009国家集训队]employ人员雇佣 (最小割)
题面 BZOJ传送门 Luogu传送门 分析 考虑如何最小割建图,因为这仍然是二元关系,我们可以通过解方程来确定怎么建图,具体参考论文 <<浅析一类最小割问题 湖南师大附中 彭天翼> ...
- resize([[data],fn]) 当调整浏览器窗口的大小时,发生 resize 事件。
resize([[data],fn]) 概述 当调整浏览器窗口的大小时,发生 resize 事件. 参数 fnFunctionV1.0 在每一个匹配元素的resize事件中绑定的处理函数.直线电机 ...
- SpringMVC指定webapp的首页
webapp的首页指的是http://localhost:8080/ 方法一 追加一个[/]URI的请求方法 @Controller public class WelcomeController { ...
- Ubuntu 14.04 用户操作
新建用户sudo adduser linuxidc 修改hosts文件sudo gedit /etc/hosts ubuntu修改主机名sudo gedit /etc/hostname 删除用户在ro ...
- Codeforces 1276C/1277F/1259F Beautiful Rectangle (构造)
题目链接 http://codeforces.com/contest/1276/problem/C 题解 嗯,比赛结束前3min想到做法然后rush不出来了--比赛结束后又写了15min才过-- 以下 ...
- exposed beyond app through ClipData.Item.getUri()
Android7.0调用相机时出现新的错误: android.os.FileUriExposedException: file:///storage/emulated/0/photo.jpeg exp ...
- 高并发实时弹幕系统 并发数一定是可以进行控制的 每个需要异步处理开启的 Goroutine(Go 协程)都必须预先创建好固定的个数,如果不提前进行控制,那么 Goroutine 就随时存在爆发的可能。
小结: 1.内存优化1.一个消息一定只有一块内存使用 Job 聚合消息,Comet 指针引用. 2.一个用户的内存尽量放到栈上内存创建在对应的用户 Goroutine(Go 程)中. 3.内存由自己控 ...
- Mac Mysql 5.6.4修改初始化密码
Mac Mysql 修改初始化密码 第一步: 点击系统偏好设置->最下边点MySQL,在弹出页面中,关闭服务 第二步:进入终端输入:cd /usr/local/mysql/bin/回车后 登 ...
- UML期末复习题——2.8:UML Design Class Diagram(DCD)
第八题:设计类图 重要概念: 1. 类图(Class Diagram): 类图是面向对象系统建模中最常用和最重要的图,是定义其它图的基础.类图主要是用来显示系统中的类.接口以及它们之间的静态结构和关系 ...