使用redis构建分布式锁
Redis使用WATCH命令来代替对数据进行加锁,因为WATCH只会在数据被其他客户端抢先修改了的情况下通知执行了这个命令的客户端,但是不会阻止其他客户端对数据进行修改,所以这个命令被称为乐观锁。
但是使用WATCH命令来监视被频繁访问的键可能会引起性能问题,所以我们需要使用锁。而且相比操作系统级别的锁和编程语言级别的锁,使用Redis构建锁如果一个客户端访问一个锁,可以让所有客户端都看得见,我们将
基于SETNX命令构建。
1.简易版的锁
SETNX命令只会在键不存在的情况下为键设置值,而锁要做的就是将一个随机生成的128位UUID设置为键的值,并使用这个值来防止锁被其他进程取得。如果程序在尝试获取锁的时候失败,那么它将不断地重试,直到成功地
取得锁或者超过给定的时限为止。
public String acquireLock(Jedis conn, String lockName, long acquireTimeout){
String identifier = UUID.randomUUID().toString();
long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end){
if (conn.setnx("lock:" + lockName, identifier) == 1){
return identifier;
}
try {
Thread.sleep(1);
}catch(InterruptedException ie){
Thread.currentThread().interrupt();
}
}
return null;
}
释放锁的代码其实就是删除锁。
public boolean releaseLock(Jedis conn, String lockName, String identifier) {
String lockKey = "lock:" + lockName;
while (true){
conn.watch(lockKey);
if (identifier.equals(conn.get(lockKey))){//检查进程是否仍然持有锁
//释放锁
Transaction trans = conn.multi();
trans.del(lockKey);
List<Object> results = trans.exec();
if (results == null){
continue;
}
return true;
}
conn.unwatch();
break;
}
return false;
}
但是这种锁在持有者崩溃的情况下不会自动释放锁,这将导致锁一直处于已被获取的状态,所以需要将锁加上超时功能。
2.带有超时特性的锁
public String acquireLockWithTimeout(
Jedis conn, String lockName, long acquireTimeout, long lockTimeout)
{
String identifier = UUID.randomUUID().toString();
String lockKey = "lock:" + lockName;
int lockExpire = (int)(lockTimeout / 1000); long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end) {
//获取锁并设置过期时间
if (conn.setnx(lockKey, identifier) == 1){
conn.expire(lockKey, lockExpire);
return identifier;
}
//检查过期时间,并在需要时对其进行更新
if (conn.ttl(lockKey) == -1) {
conn.expire(lockKey, lockExpire);
} try {
Thread.sleep(1);
}catch(InterruptedException ie){
Thread.currentThread().interrupt();
}
} // null indicates that the lock was not acquired
return null;
}
之前写的释放函数依旧可以使用。
使用redis构建分布式锁的更多相关文章
- 《Redis官方文档》用Redis构建分布式锁
用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简 ...
- Redis构建分布式锁
1.前言 为什么要构建锁呢?因为构建合适的锁可以在高并发下能够保持数据的一致性,即客户端在执行连贯的命令时上锁的数据不会被别的客户端的更改而发生错误.同时还能够保证命令执行的成功率. 看到这里你不禁要 ...
- 用Redis构建分布式锁-RedLock(真分布)
在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简单的实现其实只需采用稍微增 ...
- 用redis构建分布式锁
单实例的实现 从2.6.12版本开始,redis为SET命令增加了一系列选项: EX seconds – 设置键key的过期时间,单位时秒 PX milliseconds – 设置键key的过期时间, ...
- 基于Redis的分布式锁真的安全吗?
说明: 我前段时间写了一篇用consul实现分布式锁,感觉理解的也不是很好,直到我看到了这2篇写分布式锁的讨论,真的是很佩服作者严谨的态度, 把这种分布式锁研究的这么透彻,作者这种技术态度真的值得我好 ...
- 基于redis的分布式锁(转)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- 基于redis的分布式锁(不适合用于生产环境)
基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...
- redis系列:基于redis的分布式锁
一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...
- 基于Redis的分布式锁到底安全吗(下)?
2017-02-24 自从我写完这个话题的上半部分之后,就感觉头脑中出现了许多细小的声音,久久挥之不去.它们就像是在为了一些鸡毛蒜皮的小事而相互争吵个不停.的确,有关分布式的话题就是这样,琐碎异常,而 ...
随机推荐
- 某考试 T2 yja
2.1 Description 在平面上找 n 个点, 要求这 n 个点离原点的距离分别为 r1, r2, ..., rn. 最大化这 n 个点构成的凸包面积, 凸包上的点的顺序任意. 2.2 Inp ...
- 关于用String Calender类 计算闰年的Demo
package cn.zmh.zuoye; import java.util.Calendar; public class StringRun { public static void main(St ...
- 下载数据到Excel,工具类
使用反射将model数据下载到Excel中 package test.upload.utils; import java.lang.reflect.Method; import java.math.B ...
- window环境下搭建SVN服务器
<span style="font-family: Arial; rgb(255, 255, 255);">第一步:准备工具:</span> 1.SVN服务 ...
- Ubuntu系统U盘安装以及降内核
由于项目需要,要用U盘制作一个Linux系统,支持EFI启动,并且内核版本要求是2.6.35.6.所以在选系统的时候,就必须要选安装文件里面带有EF I目录,并且该目录下面有BOOTx64.EFI和g ...
- 【Java 虚拟机探索之路系列】:JIT编译器
作者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell 为 ...
- activiti自己定义流程之自己定义表单(二):创建表单
注:环境配置:activiti自己定义流程之自己定义表单(一):环境配置 在上一节自己定义表单环境搭建好以后,我就正式開始尝试自己创建表单,在后台的处理就比較常规,主要是针对ueditor插件的功能在 ...
- 一个Exchange 2010 的password不定期弹框的问题处理,希望对大家可以有所帮助。
前期有个客户採用exchange 2010的邮件系统作为他们的邮件平台.有个奇怪的现象就是Exchange 2010 系统会出现不定期"宕机"现象,为何打上引號,就是这个时候仅仅有 ...
- CSS多种方法实现分隔线
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8" /> <title&g ...
- 【转载】在VS2008中使用WSE 3.0过程全记录
WSE全称是Web Service Enhancement,提供了更好的安全性实现,以及大对象传输的设计. 有关WSE的一些介绍,如果不清楚,可以参考下面的链接 官方介绍:http://www.mic ...