redis分布式锁:setNx自定义锁

redis分布式锁原理:视频教程:【免费】redis高可用分布式锁精讲-1-jvm锁与分布式锁对比-谭亮的在线视频教程-CSDN程序员研修院

  • SET key value命令:

如果 key 已经持有其他值, SET 就覆写旧值,无视类型

  • SETEX key seconds value命令:

将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)

如果 key 已经存在, SETEX 命令将覆写旧值,设置成功时返回 OK,当 seconds 参数不合法时,返回一个错误

  • SETNX key value命令:

将 key 的值设为 value ,当且仅当 key 不存在,若给定的 key 已经存在,则 SETNX 不做任何动作

成功返回1,失败返回0

流程

流程说明:

  • A、B线程同时通过setEX,setNX命令用同一个key去添加redis,由于redis是单线程的,只能有一个线程成功返回ok, A成功去处理业务逻辑,B失败但是一直在循环添加redis
  • A执行业务逻辑完成后删除redis的key,B就可以添加redis成功,去处理相应的业务逻辑
  • redis锁一定要设置过期时间,防止A拿到锁,当时还没释放程序中途出了异常,导致B一直拿不到锁,程序卡死

自定义锁代码实现:(以下为只用setNX实现方式)

  • lockkey可以是你的请求系统+请求流水等字段拼接的唯一的标识,过期时间比执行业务逻辑时间往上加一些就可以(一定要确保大于业务逻辑执行时间,否则A线程执行del时会因为自己的锁已经自动删除,而去把B线程的锁给删掉)
  • 每个线程的key对应的value都不一样,在删除时可以根据value判断是否是自己的redis,避免把其他线程的key删除
  • 如果A线程做删除操作时,通过value发现锁是B线程的,这时A线程应该回滚并抛出异常,防止业务重复执行

代码示例:基于redis组成的分布式锁解决方案为:

1、setNx一个锁key,相应的value为当前时间加上过期时间的时钟;
2、如果setNx成功,或者当前时钟大于此时key对应的时钟则加锁成功,否则加锁失败退出;
3、加锁成功执行相应的业务操作(处理共享数据源);
4、释放锁时判断当前时钟是否小于锁key的value,如果当前时钟小于锁key对应的value则执行删除锁key的操作

public boolean getLock(String lockKey, long timeout) {boolean success; // 默认获取锁失败 falselong value = System.currentTimeMillis() + timeout; // 设置锁值success = setnx(lockKey,value);if (!success) {Long keyValue = queryObjectByKey(lockKey, Long.class);long oldValue = keyValue == null ? 0L : keyValue.longValue();// 锁已经超时if (oldValue < System.currentTimeMillis()) {long getValue = getSet(lockKey, value, Long.class);// 获取锁成功if (getValue == oldValue) {success = true;} else {// 已被其他进程捷足先登了success = false;}} else {// 未超时,则直接返回失败success = false;}}return success;}

业务代码使用自定义锁

// 生成redisKey:根据自己业务去拼接一个不唯一的字符串作为Key
String lockKey = RedisKeyConstant.REDIS_SENTINEL_PREFIX + KeysGeneratorUtil.createRedisKey(InfoBO.getRequestSystem(), InfoBO.getEquityNo());
try {// 获取锁boolean lockResult = redisUtil.getLock(lockKey, 5000L);if (!lockResult) {log.error("获取锁失败,redisKey:{}",lockKey);throw new EquityServiceException("错误码");}
} catch (Exception e) {log.error("获取锁异常,redisKey:{}",lockKey);throw new ServiceException("错误码");
}// 加锁成功,处理业务代码try {// 加锁成功,处理业务代码} catch (Exception e ) {// 执行业务代码异常} finally {// 根据锁Key释放redis锁:实际上是删除的setNx中的keyredisUtil.deleteKey(lockKey);}

redis分布式锁(乐观锁)相关推荐

  1. Redis数据库系列(四)、Redis事务、乐观锁和分布式锁

    第四章.Redis事务.乐观锁和分布式锁 什么是事务机制? 4.1.关系型数据库中的事务机制遵循ACID规则 关系型数据库例如MySql.Oracle: 事务的英文是transaction,以现实中的 ...

  2. Java锁详解:“独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁+线程锁”

    在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 线程锁 乐观锁 VS 悲 ...

  3. java 对变量加锁_Java最全锁剖析:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁...

    乐观锁 VS 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用. 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会 ...

  4. 【Java 并发编程】线程锁机制 ( 悲观锁 | 乐观锁 | CAS 三大问题 | ABA 问题 | 循环时间长问题 | 多个共享变量原子性问题 )

    文章目录 一.悲观锁 二.乐观锁 三.乐观锁 CAS 三大问题 一.悲观锁 假设有 222 个线程 , 线程 A 和 线程 B ; 线程 A 访问共享资源 , 线程 B 等待 , 一旦线程 A 访问结 ...

  5. Hibernate悲观锁/乐观锁

    如果需要保证数据访问的排它性,则需对目标数据加"锁",使其无法被其它程序修改 一,悲观锁 对数据被外界(包括本系统当前的其它事务和来自外部系统的事务处理)修改持保守态度,通过数据库 ...

  6. innodb 悲观锁 乐观锁_mysql乐观锁、悲观锁、共享锁、排它锁、行锁、表锁

    mysql乐观锁.悲观锁.共享锁.排它锁.行锁.表锁 乐观锁 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使 ...

  7. 最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

    在Java并发场景中,会涉及到各种各样的锁,比如:高并发编程系列:4种常用Java线程锁的特点,性能比较.使用场景,这些锁有对应的种类:公平锁,乐观锁,悲观锁等等,这篇文章来详细介绍各种锁的分类: 公 ...

  8. MySQL - 行锁 表锁 乐观锁 悲观锁 读锁 写锁

    MySQL - 行锁 表锁 乐观锁 悲观锁 读锁 写锁 锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足.在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(I ...

  9. 理解悲观锁乐观锁、同步锁、读锁、写锁

    ava 锁分类 Java 中的锁有很多,可以按照不同的功能.种类进行分类,下面是我对 Java 中一些常用锁的分类,包括一些基本的概述 从线程是否需要对资源加锁可以分为 悲观锁 和 乐观锁 从资源已被 ...

  10. Redis中的乐观锁和悲观锁

    一.定义: 悲观锁(Pessimistic Lock):   顾名思义,就是很悲观.每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改 ...

最新文章

  1. Android Splash界面支持用户点击 直接进入主界面
  2. PNAS:微生物组互作塑造宿主适应度
  3. [数据库]简单SQL语句总结
  4. Docker环境下报错:unknown group ‘mlocate‘ in statoverride file E: Sub-process /usr/bin/dpkg
  5. python数据结构算法 北京大学_北京大学公开课《数据结构与算法Python版》
  6. string、stringbuilder、stringbuffer区别
  7. Ubuntu 16.04启用 TCP 拥塞控制之 BBR
  8. 新手必学的Mac使用技巧
  9. com.mysql.jdbc.jdbc2.optional.MysqlXADataSource 找不到
  10. 为了实现搜索引擎功能,将正则进行到底!
  11. json字符串转对象数组
  12. java mysql字符串拼接_Oracle与MySQL字符串拼接
  13. Racket 学习笔记
  14. Web前端开发十日谈
  15. matlab提取电压基波分量,有源电力滤波器三种基波提取方法的对比分析
  16. 国际:十种学习新技术的方法
  17. 读知乎《美国为什么不能通过印制美元来偿还中国购买的美国国债?》有感
  18. 北京房价当日报20141013
  19. poj入门水题整理1--按刷题顺序解释
  20. 潇洒郎: windows、centos学习Influxdb下载安装 重置用户、密码 influx语法 数据写入与读取、查询 修改默认启动端口

热门文章

  1. 如何构建基于岗位的员工职业发展体系
  2. 基于esp32/8266语音门铃对讲机系统设计语音传输实时udp,espnow传输图像
  3. win10插入耳机时SmartAudio老是弹出怎么办?
  4. 吊打面试官系列之---吃透MySQL mvcc机制--锁模块
  5. PlaneMVS: 3D Plane Reconstruction from Multi-View Stereo介绍
  6. [FAQ18419][audio speech]通话免提模式如何使用副mic
  7. 聊聊字符集(一)——ASCII字符集和GB2312字符集
  8. jupyter安装库-plotly
  9. java类与对象之实验三
  10. 记录:不允许1130连接mysql_解决Navicat 报错:1130-host ... is not allowed to connect to this MySql server