springboot基于redis的分布式锁代码
时间:2019-01-11
本文章向大家介绍springboot基于redis的分布式锁代码,主要包括springboot基于redis的分布式锁代码使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
分布式锁,当前代码中, 会循环尝试执行获取锁对象,每一秒一次。
如果锁没有释放而退出,会导致死锁的现象, 在看官的场合中,可以对while做调整 退出循环。 例如尝试5次失败则退出。
import com.kakacl.product_service.config.Constant;
import com.kakacl.product_service.config.Constants;
import com.kakacl.product_service.controller.BaseController;
import com.kakacl.product_service.service.BackCardService;
import com.kakacl.product_service.utils.ErrorCode;
import com.kakacl.product_service.utils.Resp;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
/**
* @author wangwei
* @version v1.0.0
* @description 我的收入控制器
* @date 2019-01-11
*/
@RestController
@RequestMapping("/api/rest/{version}/myincome")
public class MyInComeController extends BaseController {
@Autowired
private BackCardService backCardService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
// 添加银行卡的同步锁
private final static String countKey="redis:lock:add_back_num";
@RequestMapping(value = "addBackCard", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Resp addBackCard(HttpServletRequest request,
@RequestParam(name = "time", required = true)String time,
String token,
@RequestParam(name = "cardNum", required = true) String cardNum,
String name,
String phoneNum,
String idCard,
String opanCardBack) {
Map params = new HashMap<>();
String userId = getUserid(request);
System.out.println(userId);
// TODO 只有当当前key不存在的时候,SETNX 会成功 – 此时相当于获取到可以对这个资源进行操作的同步锁
final String key=String.format("redis:add_card_num:id:%s", userId +"");
Boolean res = true;
while(res){
String value = UUID.randomUUID().toString()+System.nanoTime();
res = stringRedisTemplate.opsForValue().setIfAbsent(key,value);
if (res) {
stringRedisTemplate.opsForValue().increment(countKey, 1L);
try {
// 执行业务
res = false;
// 1.查询用户是否已经绑定过相同的银行卡,根据银行卡判断
params.put("card_num", cardNum);
List<Map> result = backCardService.selectBackCarcdExist(params);
if(result != null && result.size() > Constants.CONSTANT_0) {
// 已经有绑定过
log.info("基于redis实战分布式锁-成功:stock={} 这个银行卡已经有账户绑定过 ",cardNum);
return Resp.fail(ErrorCode.CODE_6010);
} else {
// 继续执行
log.info("继续执行:stock={} ",cardNum);
return Resp.success();
}
} catch (Exception e) {
return Resp.fail();
} finally {
//TODO:释放锁-释放当时自己获取到的锁-value
String redisValue = stringRedisTemplate.opsForValue().get(key);
if (StringUtils.isNotBlank(redisValue) && redisValue.equals(value)){
stringRedisTemplate.delete(key);
}
}
} else{
res=true;
try{
Thread.sleep(1000L);
} catch (Exception e) {}
}
}
return Resp.fail(ErrorCode.CODE_9999);
}
}
- 十分钟搞定酷炫动画,Android自定义 View 入门
- 基础篇章:关于 React Native 之 Switch 和 ProgressBarAndroid 组件的讲解
- Android 实现视屏播放器、边播边缓存功能、外加铲屎(IJKPlayer)
- 基础篇章:关于 React Native 之 ToolbarAndroid 组件的讲解
- Android M 权限最佳实践
- Android自定义ViewGroup神器-ViewDragHelper
- Android 中常见的内存泄漏
- Android 高级自定义Toast及源码解析
- 环境配置:React Native 开发环境配置 For Android
- 美团多渠道打包方案详解,速度快到白驹过隙
- 下一代Android渠道打包工具
- 01 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之业务分析与DAO层
- 通俗易懂的分析如何用Python实现一只小爬虫,爬取拉勾网的职位信息
- 我的第一个小程序(Discuz! + 微信小程序)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Swift 数组dropFirst方法
- Swift 类方法和实例方法
- 我从未见过的牛逼解说方式!Redis五种数据结构,看一遍就懂了
- Swift 动态创建ViewController
- Office 文档解析 文档格式和协议
- 查看centos 7里敏感信息的常用命令(未完)
- C# dotnet 使用 FileStream 随机文件读写
- datables之加载数据时显示进度条
- 这几种常见的“分布式锁”写法,搞懂再也不怕面试官,安排
- C# 8.0 文件长度 Bytes 字节转 KB 等单位字符串
- LeetCode---两数之和
- 通过 cmd 批处理文件将 16 进制转 10 进制数字
- HTML5-JS操作页面滚动条(禁止、隐藏、显示、不显示)
- 追根溯源MySQL,“你的表情”插入对了吗?
- 推荐官方开源 PInvoke 库 包含大量 win32 封装