在分布式系统中,经常会出现需要竞争同一资源的情况,使用redis可以实现分布式锁。

前提:redis集群已经整合项目,并且可以直接注入JedisCluster使用:

    @Autowired
private JedisCluster jedisCluster;

1. 新建RedisLockManger分布式锁管理器,并且如上注入 JedisCluster :

package com.jarfk.util.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisCluster; import javax.annotation.PostConstruct;
import java.util.concurrent.TimeUnit; /**
* redis集群分布式锁管理器,支持对单个资源加锁解锁,或给一批资源的批量加锁及解锁
* Created by Administrator on 2017/10/12 0012.
*/
@Component
public class RedisLockManger {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockManger.class); //设置3秒过期
private static final int DEFAULT_SINGLE_EXPIRE_TIME = 3; // private static final int DEFAULT_BATCH_EXPIRE_TIME = 6; //static的变量无法注解
@Autowired
private JedisCluster jc; private static RedisLockManger lockManger; public RedisLockManger() {
} @PostConstruct
private void init() {
lockManger = this;
lockManger.jc = this.jc;
}
/**
* 获取锁 如果锁可用 立即返回true, 否则立即返回false,作为非阻塞式锁使用
* @param key
* @return
*/
public boolean tryLock(String key/* , String value*/) {
try {
return tryLock(key, key, 0L, null);
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
} /**
* 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false,作为阻塞式锁使用
* @param key 锁键
* @param value 被谁锁定
* @param timeout 尝试获取锁时长,建议传递500,结合实践单位,则可表示500毫秒
* @param unit,建议传递TimeUnit.MILLISECONDS
* @return
* @throws InterruptedException
*/
public boolean tryLock(String key , String value , long timeout , TimeUnit unit) throws InterruptedException {
//纳秒
long begin = System.nanoTime();
do {
//LOGGER.debug("{}尝试获得{}的锁.", value, key);
Long i = lockManger.jc.setnx(key, value);
if (i == 1) {
lockManger.jc.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);
LOGGER.debug(value + "-成功获取{}的锁,设置锁过期时间为{}秒 ", key, DEFAULT_SINGLE_EXPIRE_TIME);
return true;
} else {
// 存在锁 ,但可能获取不到,原因是获取的一刹那间
// String desc = lockManger.jc.get(key);
// LOGGER.error("{}正被{}锁定.", key, desc);
} if (timeout == 0) {
break;
}
//在其睡眠的期间,锁可能被解,也可能又被他人占用,但会尝试继续获取锁直到指定的时间
Thread.sleep(100);
} while ((System.nanoTime() - begin) < unit.toNanos(timeout));
//因超时没有获得锁
return false;
} /**
* 释放单个锁
* @param key 锁键
*/
public void unLock(String key/*, String value*/) {
lockManger.jc.del(key);
LOGGER.debug("{}锁被{}释放 .", key, key);
}
}

2. 使用示例:

首先在需要加锁的地方注入分布式锁管理器:

    @Autowired
private RedisLockManger redisLock;

然后调用即可,如:

        if (redisLock.tryLock("statusCheck")) { //此处代码是锁上的
logger.debug("-----------------------:10秒执行一次!每次只有一个程序运行");
//释放锁,正常情况下,此处代码要注释掉,以免锁被释放,需要释放时可以根据自己逻辑的需要
//redisLock.unLock("statusCheck");
}

首先注入需要的

基于redis集群实现的分布式锁,可用于秒杀,定时器。的更多相关文章

  1. 基于redis集群实现的分布式锁,可用于秒杀商品的库存数量管理,有測试代码(何志雄)

    转载请标明出处. 在分布式系统中,常常会出现须要竞争同一资源的情况,本代码基于redis3.0.1+jedis2.7.1实现了分布式锁. redis集群的搭建,请见我的另外一篇文章:<>& ...

  2. 分布式ID系列(4)——Redis集群实现的分布式ID适合做分布式ID吗

    首先是项目地址: https://github.com/maqiankun/distributed-id-redis-generator 关于Redis集群生成分布式ID,这里要先了解redis使用l ...

  3. springcloud微服务基于redis集群的单点登录

    springcloud微服务基于redis集群的单点登录 yls 2019-9-23 简介 本文介绍微服务架构中如何实现单点登录功能 创建三个服务: 操作redis集群的服务,用于多个服务之间共享数据 ...

  4. 【spring boot】【redis】spring boot基于redis的LUA脚本 实现分布式锁

    spring boot基于redis的LUA脚本 实现分布式锁[都是基于redis单点下] 一.spring boot 1.5.X 基于redis 的 lua脚本实现分布式锁 1.pom.xml &l ...

  5. 集群多JVM分布式锁实现

    基于数据库表乐观锁 (基本废弃) 要实现分布式锁,最简单的⽅方式可能就是直接创建⼀一张锁表,然后通过操作该表中的数据来实现了了. 当我们要锁住某个⽅法或资源时,我们就在该表中增加一条记录,想要释放锁的 ...

  6. Redis集群模式之分布式集群模式

    前言 Redis集群模式主要有2种: 主从集群 分布式集群. 前者主要是为了高可用或是读写分离,后者为了更好的存储数据,负载均衡. 本文主要讲解主从集群.本章主要讲解后一半部分,Redis集群. 与本 ...

  7. 【连载】redis库存操作,分布式锁的四种实现方式[四]--基于Redis lua脚本机制实现分布式锁

    一.redis lua介绍 Redis 提供了非常丰富的指令集,但是用户依然不满足,希望可以自定义扩充若干指令来完成一些特定领域的问题.Redis 为这样的用户场景提供了 lua 脚本支持,用户可以向 ...

  8. java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购

    此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...

  9. Couchbase集群和Redis集群解析

    Couchbase集群和Redis集群解析 首先,关于一些数据库或者是缓存的集群有两种结构,一种是Cluster;一种是master-salve. 关于缓存系统一般使用的就是Redis,Redis是开 ...

随机推荐

  1. 【Java】异常类处理层次

    异常处理简介 异常在java的开发中可能没有那么被重视.一般遇到异常,直接上抛,或者随便catch一下处理之后对于程序整体运行也没有什么大的影响.不过在企业级设计开发中,异常的设计与处理的好坏,往往就 ...

  2. 通过Fiddler肆意修改接口返回数据进行测试

    [本文出自天外归云的博客园] 方法介绍与比对 在测试的过程中,有的需求是这样的,它需要你修改接口返回的数据,从而检查在客户端手机app内是否显示正确,这也算是一种接口容错测试,接口容错测试属于app性 ...

  3. nginx动态配置及服务发现那些事

    Reference: http://xiaorui.cc/2016/10/16/nginx%E5%8A%A8%E6%80%81%E9%85%8D%E7%BD%AE%E5%8F%8A%E6%9C%8D% ...

  4. PHP 图片处理类 错误处理方法:

    call an undefined function exif_imagetype() 打开扩展php.ini 将 ; 去掉: extension=php_exif.dll 并将extension=p ...

  5. busybox tar 命令支持 tar.gz

    原始的 busybox 里面的 tar 命令不支持 tar.gz 解压 在 busybox-menuconfig 里面加入 下面的选项即可

  6. PopupWindow 常用方法学习笔记

    PopupWindow可以实现浮层效果,而且可以自定义显示位置,出现和退出时的动画. 首先解析一个View LayoutInflater inflater = getLayoutInflater(); ...

  7. Java通过JDBC进行简单的增删改查(以MySQL为例)

    Java通过JDBC进行简单的增删改查(以MySQL为例) 目录: 前言:什么是JDBC 一.准备工作(一):MySQL安装配置和基础学习 二.准备工作(二):下载数据库对应的jar包并导入 三.JD ...

  8. Class类文件结构

    平台无关性 Java是与平台无关的语言,这得益于Java源代码编译后生成的存储字节码的文件,即Class文件,以及Java虚拟机的实现.不仅使用Java编译器可以把Java代码编译成存储字节码的Cla ...

  9. js统计输入文字的字节数(byte)

    这里主要考虑的是日文,日文中包含了半角和全角文字,半角算1,全角算2. <html> <head> <script language="javascript&q ...

  10. c# 自定义类型的DataBindings

    自定义类型TextBoxEx,扩展了TextBox,增加了一个属性KeyText来保存后台的值(Tag已另作它用). 程序里面需要将KeyText和DataTable的某个列绑定起来. 如果是Text ...