摘要:用锁遇到过哪些问题?

一、白话分布式

什么是分布式,用最简单的话来说,就是为了较低单个服务器的压力,将功能分布在不同的机器上面;就比如:

本来一个程序员可以完成一个项目:需求->设计->编码->测试

但是项目多的时候,一个人也扛不住,这就需要不同的人进行分工合作了

这就是一个简单的分布式协同工作了;

二、分布式锁

首先看一个问题,如果说某个环节被终止或者别侵占,就会发生不可知的事情

这就会出现,设计好的或者设计的半成品会被破坏,导致后面环节出错;

这时候,我们就需要引入分布式锁的概念;

何为分布式锁?当在分布式模型下,数据只有一份(或有限制),此时需要利用锁的技术控制某一时刻修改数据的进程数。

用一个状态值表示锁,对锁的占用和释放通过状态值来标识。

分布式锁的条件:可以保证在分布式部署的应用集群中,同一个方法在同一时间只能被一台机器上的一个线程执行。

这把锁要是一把可重入锁(避免死锁)

这把锁最好是一把阻塞锁

这把锁最好是一把公平锁

有高可用的获取锁和释放锁功能

获取锁和释放锁的性能要好

分布式锁的实现:

分布式锁的实现由很多种,文件锁、数据库、redis等等,比较多,在实践中,还是redis做分布式锁性能会高一些;

三、redis实现分布式锁

首先看两个命令:

setnx:将 key 的值设为 value,当且仅当 key 不存在。 若给定的 key 已经存在,则 SETNX 不做任何动作。 SETNX 是SET if Not eXists的简写。127.0.0.1:6379> set lock "unlock"

OK

127.0.0.1:6379> setnx lock "unlock"

(integer) 0

127.0.0.1:6379> setnx lock "lock"

(integer) 0

127.0.0.1:6379>

expire: EXPIRE key seconds

为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除127.0.0.1:6379> expire lock 10

(integer) 1

127.0.0.1:6379> ttl lock

8

127.0.0.1:6379> get lock

(nil)

基于分布式锁的流程:

这就是一个简单的分布式锁的实现流程,具体代码实现也很简单,就不赘述了;

四、redis实现分布式锁问题

如果出现了这么一个问题:如果setnx是成功的,但是expire设置失败,那么后面如果出现了释放锁失败的问题,那么这个锁永远也不会被得到,业务将被锁死?

解决的办法:使用set的命令,同时设置锁和过期时间

set参数:set key value [EX seconds] [PX milliseconds] [NX|XX]

EX seconds:设置失效时长,单位秒

PX milliseconds:设置失效时长,单位毫秒

NX:key不存在时设置value,成功返回OK,失败返回(nil)

XX:key存在时设置value,成功返回OK,失败返回(nil)

实践:127.0.0.1:6379> set unlock "234" EX 100 NX

(nil)

127.0.0.1:6379>

127.0.0.1:6379> set test "111" EX 100 NX

OK

这样就完美的解决了分布式锁的原子性。

五、用锁遇到过哪些问题?又是如何解决的?

未关闭资源

由于当前线程 获取到redis 锁,处理完业务后未及时释放锁,导致其它线程会一直尝试获取锁阻塞,例如:用Jedis客户端会报如下的错误信息1redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

redis线程池已经没有空闲线程来处理客户端命令。使用原生方法记得关闭!

解决的方法也很简单,只要我们细心一点,拿到锁的线程处理完业务及时释放锁

B的锁被A给释放了

我们知道Redis实现锁的原理在于 SETNX命令。当 key不存在时将 key的值设为 value ,返回值为 1;若给定的 key已经存在,则 SETNX不做任何动作,返回值为 0 。SETNX key value

我们来设想一下这个场景:A、B两个线程来尝试给key myLock加锁,A线程先拿到锁(假如锁3秒后过期),B线程就在等待尝试获取锁,到这一点毛病没有。

那如果此时业务逻辑比较耗时,执行时间已经超过redis锁过期时间,这时A线程的锁自动释放(删除key),B线程检测到myLock这个key不存在,执行 SETNX命令也拿到了锁。

但是,此时A线程执行完业务逻辑之后,还是会去释放锁(删除key),这就导致B线程的锁被A线程给释放了。

为避免上边的情况,一般我们在每个线程加锁时要带上自己独有的value值来标识,只释放指定value的key,否则就会出现释放锁混乱的场景

一般我们可以设置value为业务前缀_当前线程ID或者uuid,只有当前value相同的才可以释放锁

锁过期了,业务还没执行完

redis分布式锁过期,而业务逻辑没执行完的场景,不过,这里换一种思路想问题,把redis锁的过期时间再弄长点不就解决了吗?

那还是有问题,我们可以在加锁的时候,手动调长redis锁的过期时间,可这个时间多长合适?业务逻辑的执行时间是不可控的,调的过长又会影响操作性能。

要是redis锁的过期时间能够自动续期就好了。

为了解决这个问题我们使用redis客户端redisson,redisson很好的解决了redis在分布式环境下的一些棘手问题,它的宗旨就是让使用者减少对Redis的关注,将更多精力用在处理业务逻辑上。

redisson对分布式锁做了很好封装,只需调用API即可。1  RLock lock = redissonClient.getLock("stockLock");

redisson在加锁成功后,会注册一个定时任务监听这个锁,每隔10秒就去查看这个锁,如果还持有锁,就对过期时间进行续期。默认过期时间30秒。这个机制也被叫做:“看门狗”

redis主从复制的坑

redis高可用最常见的方案就是主从复制(master-slave),这种模式也给redis分布式锁挖了一坑。

redis cluster集群环境下,假如现在A客户端想要加锁,它会根据路由规则选择一台master节点写入key mylock,在加锁成功后,master节点会把key异步复制给对应的slave节点。

如果此时redis master节点宕机从节点复制失败,为保证集群可用性,会进行主备切换,slave变为了redis master。B客户端在新的master节点上加锁成功,而A客户端也以为自己还是成功加了锁的。另外如果主从复制延迟同样也会造成加锁和解锁延迟的问题。

此时就会导致同一时间内多个客户端对一个分布式锁完成了加锁,导致各种脏数据的产生。

毕竟redis是保持的AP而非CP,如果要追求强一致性可以使用zookeeper分布式锁。

redis 失效时间单位是秒还是毫秒_redis分布式锁的这些坑,我怀疑你是假的开发...相关推荐

  1. redis 失效时间单位是秒还是毫秒_Redis有效时间设置及时间过期处理

    本文对redis的过期处理机制做个简单的概述,让大家有个基本的认识. Redis中有个设置时间过期的功能,即对存储在redis数据库中的值可以设置一个过期时间.作为一个缓存数据库,这是非常实用的.如我 ...

  2. redis 失效时间单位是秒还是毫秒_redis设置过期时间

    一般主要包括4种处理过期方,其中expire都是以秒为单位,pexpire都是以毫秒为单位的. 1 EXPIRE key seconds //将key的生存时间设置为ttl秒 2 PEXPIRE ke ...

  3. redis 失效时间单位是秒还是毫秒_Redis 事务与过期时间详细介绍

    Redis 事务与过期时间详细介绍 一.Redis事务: Redis中支持事务,事务即为当我们需要执行几条命令时,要么这几条命令都不执行,要么都执行: 1.开始事务写入: multi 2.然后写入命令 ...

  4. redis 失效时间单位是秒还是毫秒_redis键过期时间的应用

    expire 设置生存时间(单位/秒) pexpire设置生存时间(单位/毫秒) ttl/pttl 查看键的剩余生存时间 persist 取消生存时间 expireat [key] unix时间戳13 ...

  5. redis 失效时间单位是秒还是毫秒_经常用Redis,这些坑你知道吗?

    文章转载自二马读书,作者二马读书 作者简介:曾任职于阿里巴巴,每日优鲜等互联网公司,任技术总监,15年电商互联网经历. 近些年,Redis凭借在性能.稳定性和高可扩展性上的卓越表现,基本上已经成了互联 ...

  6. redis 失效时间单位是秒还是毫秒_【redis中键的生存时间(expire) 】

    /*** 限制网站访客访问频率(例如:1分钟最多访问10次),其中: 访客通过IP标识,即同一个IP在1分钟内仅能访问10次*/@Testpublic voidtest4(){final String ...

  7. 实际开发中使用Redis做分布式锁,躲坑指南,收藏起来

    今天我们来聊聊Redis分布式锁,曾经被Redis分布式锁的坑给坑惨了,接下来,我就进行一个完整的整理,希望大家都能避免踩坑. 在分布式系统中,由于redis分布式锁相对于更简单和高效,成为了分布式锁 ...

  8. Redis如何实现分布式锁延时队列以及限流应用丨Redis源码原理|跳表|B+树|分布式锁|中间件|主从同步|存储原理

    Redis如何实现分布式锁延时队列以及限流应用 视频讲解如下,点击观看: Redis如何实现分布式锁延时队列以及限流应用丨Redis源码原理|跳表|B+树|分布式锁|中间件|主从同步|存储原理|数据模 ...

  9. redis获取存在的键值_Redis 分布式锁、限流

    谈及分布式系统的时候,很多企业都会使用到分布式锁,分布式锁的实现方案目前主要是存在两种,redis实现和zookeeper实现. redis实现方案是多个线程相互竞争,在redis的某一个节点内创建一 ...

最新文章

  1. uboot引导kernel - 2- uboot/kernel需要放在DDR什么位置的问题
  2. SDN:软件定义网络
  3. 关于arduino和zigbee串口16进制通信问题
  4. 天云数据CEO雷涛:从软件到数件,AI生态如何建立自己的“Android”?| 量子位·视点分享回顾...
  5. php如何检测键盘按键,js键盘事件,判断按下的是哪个键
  6. [spring boot]idea中实现热部署的方法
  7. ReactNative入门之android与rn初始化参数的传递
  8. 简述java中异常_柴涛666 的日志-简述java中处理异常的两种方式。
  9. configureWebpack与chainWebpack
  10. CentOS 7.2下编译安装PHP 7
  11. nyoj_49_开心的小明_201403161133
  12. 2008-03-18 中午日出傍晚雨
  13. PHP生成条形码 之一 条形码介绍
  14. Windows10安装JDK配置环境变量
  15. 无损音乐知识收集1(转)
  16. IC卡和ID卡的区别。
  17. python求高阶导数_求导法则和高阶导数
  18. ioDraw - 免费的在线图表制作工具
  19. 适合初学Altium Designer的教学视频
  20. 【uni-app】errMsg : navigateTo:fail can not navigateTo a tabbar page报错解决方案

热门文章

  1. [myeclipse] 官方中文网站
  2. 开启Ubuntu root 远程登录
  3. SharePoint 2010中增强的错误跟踪机制
  4. ffmpeg编码视频总结
  5. Win10之选择文件右击时卡死问题(转圈圈)
  6. C语言之结构体嵌套调用(十八)
  7. Android6.0显示系统(五) SurfaceFlinger服务
  8. Android多媒体:AudioTrack
  9. 对Android蓝牙UUID的理解
  10. 树莓派---MAC下安装AndroidThings