一、应用场景:

  本文应用的场景为在查询数据时,发现数据不存在此时就需要去查询数据库并且更新缓存,此时可能存在高并发的请求同时打在数据库上,而针对这种情况必须要给这些请求加锁,故而采用了分布式锁的方式。(当然分布式锁的应用场景较多,我只是针对本人工作的业务场景做了对应的处理)

二、Redis锁的工具类:

/**
* Redis分布式锁
*/
@Component
public class RedisLock { @Autowired
private RedisTemplate redisTemplate; /**
* 加锁
* @param key
* @param value 当前时间+超时时间
* @return
*/
public boolean lock(String key, String value) { if(redisTemplate.opsForValue().setIfAbsent(key, value)) {//相当于SETNX,setIfAbsent方法设置了为true,没有设置为false
return true;
}
//假设currentValue=A 接下来并发进来的两个线程的value都是B 其中一个线程拿到锁,除非从始至终所有都是在并发(实际上这中情况是不存在的),只要开始时有数据有先后顺序,则分布式锁就不会出现“多卖”的现象
String currentValue = String.valueOf(redisTemplate.opsForValue().get(key));
//如果锁过期 解决死锁
if (!StringUtils.isEmpty(currentValue)
&& Long.parseLong(currentValue) < System.currentTimeMillis()) {
//获取上一个锁的时间,锁过期后,GETSET将原来的锁替换成新锁
String oldValue = String.valueOf(redisTemplate.opsForValue().getAndSet(key, value));
if (!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)) {
return true;
}
} return false;//拿到锁的就有执行权力,拿不到的只有重新再来,重新再来只得是让用户手动继续抢单
} /**
* 解锁
* @param key
* @param value
*/
public void unlock(String key, String value) {
try {
String currentValue = String.valueOf(redisTemplate.opsForValue().get(key));
if (!StringUtils.isEmpty(currentValue) && currentValue.equals(value)) {
redisTemplate.opsForValue().getOperations().delete(key);
}
}catch (Exception e) {
e.printStackTrace();
}
} }

三、业务代码:

JSONArray allApplyForms = null;
if (this.redisActivityService.exists(RedisKeys.ApplyFormList_KEY+String.valueOf(activityId))) {
  // 如果redis缓存在有该活动的作品列表,则直接从redis中获取
Object allApplyFormsJSON = this.redisActivityService.get(RedisKeys.ApplyFormList_KEY+String.valueOf(activityId));
allApplyForms = JSONArray.fromObject(allApplyFormsJSON.toString());
} else {
long time = System.currentTimeMillis()+(20 * 1000);
if(!redisLock.lock("ApplyFormListLock", String.valueOf(time))){
return CORSUtil.getResult(0, "当前访问量大,刷新一下", null, callback);
}
allApplyForms = this.activityService.getAllApplyForms(activityId, thumbnailWidth,thumbnailHeight, contentCode, formTitle, flag,formModel);
if(allApplyForms ==null){
return CORSUtil.getResult(0, "没有对应的参选表单", null,callback);
}
this.redisActivityService.set(RedisKeys.ApplyFormList_KEY+String.valueOf(activityId), allApplyForms.toString(),Long.parseLong(systemConfigService.getConfig("redisOverTime"))+new Random().nextInt(200));
redisLock.unlock("ApplyFormListLock", String.valueOf(time));
}

1,从redis中获取对应的数据,如果获取到直接返回,如果没有就走接下来的加锁代码

2,如果加锁不成功,则说明已经有请求进入到后面的业务逻辑,这时候就直接返回给客户端,等待

3,如果加锁成功,则查询数据并更新Redis,最后再释放锁

Redis分布式锁的实现以及工具类的更多相关文章

  1. springMVC 实现redis分布式锁

    1.先配置spring-data-redis 首先是依赖 <dependency> <groupId>org.springframework.data</groupId& ...

  2. 面试官问我,Redis分布式锁如何续期?懵了。

    前言 上一篇[面试官问我,使用Dubbo有没有遇到一些坑?我笑了.]之后,又有一位粉丝和我说在面试过程中被虐了.鉴于这位粉丝是之前肥朝的粉丝,而且周一又要开启新一轮的面试,为了回馈他长期以来的支持,所 ...

  3. redis分布式锁小试

    一.场景 项目A监听mq中的其他项目的部署消息(包括push_seq, status, environment,timestamp等),然后将部署消息同步到数据库中(项目X在对应环境[environm ...

  4. SpringBoot集成Redis分布式锁以及Redis缓存

    https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...

  5. Redis分布式锁实现简单秒杀功能

    这版秒杀只是解决瞬间访问过高服务器压力过大,请求速度变慢,大大消耗服务器性能的问题. 主要就是在高并发秒杀的场景下,很多人访问时并没有拿到锁,所以直接跳过了.这样就处理了多线程并发问题的同时也保证了服 ...

  6. springboot项目:Redis分布式锁的使用(模拟秒杀系统)

    模拟秒杀系统: 第一步:编写Service package com.payease.service; /** * liuxiaoming * 2017-12-14 */ public interfac ...

  7. Redis分布式锁实战

    什么是分布式锁 在单机部署的情况下,要想保证特定业务在顺序执行,通过JDK提供的synchronized关键字.Semaphore.ReentrantLock,或者我们也可以基于AQS定制化锁.单机部 ...

  8. 面试官再问Redis分布式锁如何续期?这篇文章甩 他一脸

    一.真实案例 二.Redis分布式锁的正确姿势 据肥朝了解,很多同学在用分布式锁时,都是直接百度搜索找一个Redis分布式锁工具类就直接用了.关键是该工具类中还充斥着很多System.out.prin ...

  9. 手撕redis分布式锁,隔壁张小帅都看懂了!

    前言 上一篇老猫和小伙伴们分享了为什么要使用分布式锁以及分布式锁的实现思路原理,目前我们主要采用第三方的组件作为分布式锁的工具.上一篇运用了Mysql中的select ...for update实现了 ...

随机推荐

  1. Go语言之Go语言变量

    GO 语言变量 Go语言是静态类型语言,因此变量(variable)是有明确类型的,编译器也会检查变量类型的正确性. 标识符 在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名.常量名.函 ...

  2. 为什么 select count(*) from t,在 InnoDB 引擎中比 MyISAM 慢?

    统计一张表的总数量,是我们开发中常有的业务需求,通常情况下,我们都是使用 select count(*) from t SQL 语句来完成.随着业务数据的增加,你会发现这条语句执行的速度越来越慢,为什 ...

  3. C语言经典练习题:水仙花数

    废话不说直接进入正题:传说中的水仙花数就是一个三位数的各个位数的三次方之和就是这个数本身例如153=1*1*1+5*5*5+3*3*3. 好,开始解题:首先,题中已经说了水仙花数是一个三位数,也就是说 ...

  4. IdentityServer4源码解析_5_查询用户信息接口

    协议简析 UserInfo接口是OAuth2.0中规定的需要认证访问的接口,可以返回认证用户的声明信息.请求UserInfo接口需要使用通行令牌.响应报文通常是json数据格式,包含了一组claim键 ...

  5. 面试刷题21:java并发工具中的队列有哪些?

    ![image.png](https://img2020.cnblogs.com/other/268922/202003/268922-20200330183801141-1514127119.png ...

  6. 基础组合问题 ————从n个物品里选m个

    package test; import java.util.*; public class Main{ public static int f(int n,int k, int goal){ if( ...

  7. Python第二章-变量和数据类型

    变量和数据类型 一.什么是变量,常量 思考:程序执行指的是什么? 对数据进行存储处理和计算,最终获得结果,这是程序执行的本质. 变量的概念和在数学中的变量的概念一样的,只是在计算机程序中,变量不仅可以 ...

  8. PyTorch专栏(五):迁移学习

    专栏目录: 第一章:PyTorch之简介与下载 PyTorch简介 PyTorch环境搭建 第二章:PyTorch之60分钟入门 PyTorch入门 PyTorch自动微分 PyTorch神经网络 P ...

  9. List<Object>转List<T>

    今天遇到一个麻烦,公司有个项目用了一个封装dao的模板,他妈的不管是查一条数据的方法,还是查一个集合数据的方法,全都返回Object或List<Object> 由于对象是Object根本不 ...

  10. mac 中使用git 和pycharm提交项目

    一.安装Git 1.验证git是否安装: 终端中输入: git 如果安装过出现: 2.安装git: 进入https://git-scm.com: 点击 Download 2.23.0 for Mac ...