分布式锁的实现(基于Redis)

参考:http://www.jb51.net/article/75439.htm

http://www.linuxidc.com/Linux/2015-01/111827.htm

http://www.tuicool.com/articles/6juqmm7

方式一: 基于第三方类库 redssion

1.安装redis

安装redssion的锁服务队redis的版本有要求,要求必须高于2.6版本。关于redis的安装,请参考redis安装。

2.redssion库

redssion的库添加的pom文件中去。

<dependency>   <groupId>org.redisson</groupId>   <artifactId>redisson</artifactId>   <version>2.1.0</version></dependency>

3.测试例子

 Config config = new Config();        config.useSingleServer().setAddress("ipaddress:6379");        Redisson redisson = Redisson.create(config);

        for(int i=0;i<5;i++){         RLock lock = redisson.getLock("testLock");         lock.lock(10, TimeUnit.SECONDS);//10s超时         logger.info("the lock client id is client{}",i);         Thread.sleep(1000);         logger.info("client{} unlock",i);         lock.unlock();        }

4.参考

redisson

方式二: 自定义代码实现

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import redis.clients.jedis.Jedis;

/** * redis实现的分布式锁 */public final class Lock {

private static final String LOCK = "redis:lock:%s";    private static final int EXPIRE = 20 * 60;//20分钟    private static final Logger logger = LoggerFactory.getLogger(Lock.class);

    private Lock() {    }

public static Lock getLock() {return new Lock();    }

/**     * 获得锁,超时退出     * @param id     * @param timeout 超时时间(ms)     * @return     */    public boolean lock(String id, int timeout) {

//这里的Jedis实际上是个代理。代理类JedisCallback,JedisFactoryBean        Jedis jedisProxy = JedisProxy.create();

        long lock = 0;

        long start = System.currentTimeMillis();

        while (lock != 1) {long now = System.currentTimeMillis();            //判断超时            if (timeout > 0 && now > start + timeout) {return false;            }long timestamp = now + EXPIRE * 1000 + 1;

            try {                String key = String.format(LOCK, id);                lock = jedisProxy.setnx(key, String.valueOf(timestamp));                if (lock == 1) {logger.info("设置redis锁key成功,lock key=" + key);                    jedisProxy.expire(key, EXPIRE);                    logger.info("设置redis锁key过期时间成功,lock key=" + key);                } else {                    String s = jedisProxy.get(key);                    Long lastLockTime = Long.parseLong(s);

                    //一个项目部署多个服务,锁可能已经被相同定时任务的其他进程获得,则直接返回false                    if (jedisProxy.ttl(key)!=-1&&lastLockTime > System.currentTimeMillis()){logger.info("redis锁已经被其他服务获得,lock key=" + key);                        return false;                    }/**                     * 如果上次锁定的时间已经过期,则清除key锁,以便定时任务能够启动                     * 造成未能释放的原因主要是jedis.expire(key, EXPIRE);失败                     * 或者是获取锁之后,由于程序错误或网络错误,unlock未被成功调用                     */                    if (jedisProxy.ttl(key)==-1||lastLockTime < System.currentTimeMillis()) {                        jedisProxy.del(key);                        continue;                    }//                    this.wait(100);                    Thread.sleep(100);                }            } catch (Exception e) {logger.error("从redis获取定时任务锁错误,key="+String.format(LOCK, id), e);                return false;            }        }return true;    }

/**     * 释放锁     * @param id     */    public void unLock(String id) {

//这里的Jedis实际上是个代理。代理类JedisCallback,JedisFactoryBean        Jedis jedisProxy = JedisProxy.create();        String key = String.format(LOCK, id);        jedisProxy.del(key);    }}

JedisProxy类

/** * Jedis代理 */@Componentpublic class JedisProxy implements ApplicationContextAware {

private static volatile ApplicationContext ac;

    /**     * 创建Jedis 代理     *     * @return     */    public static Jedis create() {return ac.getBean(Jedis.class);    }

@Override    public void setApplicationContext(ApplicationContext applicationContext) {if (ac != null) {return;        }synchronized (JedisProxy.class) {if (ac != null) {return;            }ac = applicationContext;        }    }}

转载于:https://www.cnblogs.com/wangdaijun/p/5301858.html

分布式锁 基于Redis相关推荐

  1. redis 分布式锁 看门狗_漫谈分布式锁之Redis实现

    笔耕墨耘,深研术道. 01写在前面Redis是一个高性能的内存数据库,常用于数据库.缓存和消息中间件.它提供了丰富的数据结构,更适合各种业务场景:基于AP模型,Redis保证了其高可用和高性能. 本文 ...

  2. Redis核心数据结构List应用场景-商品列表、缓存击穿、PV阅读量、抢红包、推送帖子、普通分布式锁、Redis可重入锁与红锁

    List应用场景 Redis之List 一. Redis list命令实战 二.商品列表 高并发的淘宝聚划算实现技术方案 SpringBoot+Redis实现商品列表功能 二.缓存击穿 什么是缓存击穿 ...

  3. 分布式锁用 Redis 还是 Zookeeper?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:jianfeng 来源:石杉的架构笔记 为什么用分布式锁? ...

  4. 什么是分布式锁?redis、zookeeper、etcd实现分布式锁有什么不同之处?

    目录 分布式锁定义 目的 基于redis分布式锁 基于zookeeper实现的分布式锁 edis.zookeeper.etcd实现分布式锁的比较 建议选择etcd实现分布式锁 分布式锁定义 分布式环境 ...

  5. 分布式锁用Redis还是Zookeeper?

    为什么用分布式锁?在讨论这个问题之前,我们先来看一个业务场景. 作者:jianfeng来源:石杉的架构笔记|2019-07-16 09:22 为什么用分布式锁?在讨论这个问题之前,我们先来看一个业务场 ...

  6. java如何保证redis设置过期时间的原子性_分布式锁用 Redis 还是 Zookeeper

    在讨论这个问题之前,我们先来看一个业务场景: 系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会给用户下单. 由于系统有 ...

  7. 分布式锁用Redis坚决不用Zookeeper?

    墨墨导读:为什么用分布式锁?在讨论这个问题之前,我们先来看一个业务场景. 为什么用分布式锁? 系统 A 是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查 ...

  8. redis中有key但是删不掉_分布式锁用 Redis 还是 Zookeeper

    为什么用分布式锁? 在讨论这个问题之前,我们先来看一个业务场景:系统A是一个电商系统,目前是一台机器部署,系统中有一个用户下订单的接口,但是用户下订单之前一定要去检查一下库存,确保库存足够了才会给用户 ...

  9. Redis 作者 Antirez 讲如何实现分布式锁?Redis 实现分布式锁天然的缺陷分析Redis分布式锁的正确使用姿势!...

    Redis分布式锁基本原理 采用 redis 实现分布式锁,主要是利用其单线程命令执行的特性,一般是 setnx, 只会有一个线程会执行成功,也就是只有一个线程能成功获取锁:看着很完美. 然而-- 看 ...

最新文章

  1. linux下jdk简单配置记录
  2. 项目使用mysql接收emoji表情
  3. 表变量是什么_为什么要使用二级指针?
  4. 关于捕获键盘信息的processDialogkey方法2--具体应用
  5. 【九省联考2018】秘密袭击【树形dp】【生成函数】【线段树合并】【多项式插值】
  6. php 403 nginx,403nginx是什么
  7. SQL Server 2005中的SQLCMD工具使用
  8. ifound Android wifi,方正新品记录仪iFound V1号称黑夜变白天,真的假的?
  9. Java不支持创建范型数组分析
  10. draw9patch做一个中心不变形的图片
  11. AC9560网卡linux驱动安装
  12. 计算机组成原理第五章考试题,计算机组成原理第五章部分课后题答案(唐朔飞版).doc...
  13. 你想要的宏基因组-微生物组知识全在这(2021.3)
  14. RubyOnRails杂记
  15. google广告推广提示有恶意软件链接的处理方案
  16. [分析力学]解题思路 - 拉格朗日方程
  17. GIS应用技巧之环形地图制作
  18. [unity] build项目报错:Currently selected scripting backend (.NET)is not installed
  19. 爬取沪江网考研词汇并按要求存为txt
  20. ESP8266(ESP模块)Arduino开发环境快速搭建方法--含网盘离线文件

热门文章

  1. 【Hihocoder - 1723】子树统计(线性基合并)
  2. 【POJ - 1661】Help Jimmy(记忆化搜索,dp)
  3. priority_queue(优先队列)的简单构造与用法
  4. 视觉SLAM十四讲(1):预备知识
  5. 遍历这些字符串,如果字符串没有包含数字的, * 就将字符串中的小写字母转成大写字母并打印字符串
  6. Linux简单命令收录(cal,passwd,clear)【下】
  7. Redis:18---常用功能之(Lua脚本)
  8. GCC在C语言中内嵌汇编 asm __volatile__
  9. nginx python webpy 配置安装
  10. openssl里面AES算法主要函数的参数的介绍