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构建分布式锁的更多相关文章

  1. 《Redis官方文档》用Redis构建分布式锁

    用Redis构建分布式锁 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简 ...

  2. Redis构建分布式锁

    1.前言 为什么要构建锁呢?因为构建合适的锁可以在高并发下能够保持数据的一致性,即客户端在执行连贯的命令时上锁的数据不会被别的客户端的更改而发生错误.同时还能够保证命令执行的成功率. 看到这里你不禁要 ...

  3. 用Redis构建分布式锁-RedLock(真分布)

    在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但是这些库实现的方式差别很大,而且很多简单的实现其实只需采用稍微增 ...

  4. 用redis构建分布式锁

    单实例的实现 从2.6.12版本开始,redis为SET命令增加了一系列选项: EX seconds – 设置键key的过期时间,单位时秒 PX milliseconds – 设置键key的过期时间, ...

  5. 基于Redis的分布式锁真的安全吗?

    说明: 我前段时间写了一篇用consul实现分布式锁,感觉理解的也不是很好,直到我看到了这2篇写分布式锁的讨论,真的是很佩服作者严谨的态度, 把这种分布式锁研究的这么透彻,作者这种技术态度真的值得我好 ...

  6. 基于redis的分布式锁(转)

    基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  7. 基于redis的分布式锁(不适合用于生产环境)

    基于redis的分布式锁 1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分 ...

  8. redis系列:基于redis的分布式锁

    一.介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...

  9. 基于Redis的分布式锁到底安全吗(下)?

    2017-02-24 自从我写完这个话题的上半部分之后,就感觉头脑中出现了许多细小的声音,久久挥之不去.它们就像是在为了一些鸡毛蒜皮的小事而相互争吵个不停.的确,有关分布式的话题就是这样,琐碎异常,而 ...

随机推荐

  1. GPIO简介

    GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平. GPIO口一是 ...

  2. 图解TCP/IP第五版 -- 文件夹

    非常多年前买过<TCP/IP具体解释>3卷,当时可能根本没看,也可能是看了又忘了,没有留下什么印象,当时的书也当做废品卖了. 卖书时的感觉貌似是.买了太多的书,基本都没看,搬家搬来搬去的麻 ...

  3. Deepin-安装和卸载软件

    一般默认厂商源安装软件 安装软件: 示例:sudo apt-get install xx 实例:sudo apt-get install nodejs 卸载软件: 示例:sudo apt-get -- ...

  4. 成员函数指针 C++ FAQ LITE — Frequently Asked Questions

    http://www.sunistudio.com/cppfaq/pointers-to-members.html C++ FAQ LITE — Frequently Asked Questions ...

  5. protobuf 之 MessageLite 接口摘录

    class LIBPROTOBUF_EXPORT MessageLite { public: inline MessageLite() {} virtual ~MessageLite(); // Ba ...

  6. 深入浅出 - Android系统移植与平台开发(十二)- Android JNI机制

    第五章.JNI机制 4.1 JNI概述 由前面基础知识可知,Android的应用层由Java语言编写,Framework框架层则是由Java代码与C/C++语言实现,之所以由两种不同的语言组合开发框架 ...

  7. swift语言初见

    下面是swift得基础语法部分内容 //  main.swift //  helloSwift // //  Created by cyteven on 14-7-23. //  Copyright ...

  8. HTML5_路径

    <!DOCTYPE html> <hmtl> <html  lang="zh-cn"> <head> <meta charse ...

  9. IntelliJ Idea 工具

     IntelliJ Idea 优化: 1.如何取消文件自动保存 File->Settings -> Appearance&Behavior -> System Setting ...

  10. HDU2819 Swap —— 二分图最大匹配

    题目链接:https://vjudge.net/problem/HDU-2819 Swap Time Limit: 2000/1000 MS (Java/Others)    Memory Limit ...