/**
*在redis上实现分布式锁
*/
class RedisLock {private $redisString;private $lockedNames = [];public function __construct($param = NULL) {$this->redisString = RedisFactory::get($param)->string;}/*** 加锁* @param  [type]  $name           锁的标识名* @param  integer $timeout        循环获取锁的等待超时时间,在此时间内会一直尝试获取锁直到超时,为0表示失败后直接返回不等待* @param  integer $expire         当前锁的最大生存时间(秒),必须大于0,如果超过生存时间锁仍未被释放,则系统会自动强制释放* @param  integer $waitIntervalUs 获取锁失败后挂起再试的时间间隔(微秒)* @return [type]                  [description]*/public function lock($name, $timeout = 0, $expire = 15, $waitIntervalUs = 100000) {if ($name == null) return false;//取得当前时间$now = time();//获取锁失败时的等待超时时刻$timeoutAt = $now + $timeout;//锁的最大生存时刻$expireAt = $now + $expire;$redisKey = "Lock:{$name}";while (true) {//将rediskey的最大生存时刻存到redis里,过了这个时刻该锁会被自动释放$result = $this->redisString->setnx($redisKey, $expireAt);if ($result != false) {//设置key的失效时间$this->redisString->expire($redisKey, $expireAt);//将锁标志放到lockedNames数组里$this->lockedNames[$name] = $expireAt;return true;}//以秒为单位,返回给定key的剩余生存时间$ttl = $this->redisString->ttl($redisKey);//ttl小于0 表示key上没有设置生存时间(key是不会不存在的,因为前面setnx会自动创建)//如果出现这种状况,那就是进程的某个实例setnx成功后 crash 导致紧跟着的expire没有被调用//这时可以直接设置expire并把锁纳为己用if ($ttl < 0) {$this->redisString->set($redisKey, $expireAt);$this->lockedNames[$name] = $expireAt;return true;}/*****循环请求锁部分*****///如果没设置锁失败的等待时间 或者 已超过最大等待时间了,那就退出if ($timeout <= 0 || $timeoutAt < microtime(true)) break;//隔 $waitIntervalUs 后继续 请求
            usleep($waitIntervalUs);}return false;}/*** 解锁* @param  [type] $name [description]* @return [type]       [description]*/public function unlock($name) {//先判断是否存在此锁if ($this->isLocking($name)) {//删除锁if ($this->redisString->deleteKey("Lock:$name")) {//清掉lockedNames里的锁标志unset($this->lockedNames[$name]);return true;}}return false;}/*** 释放当前所有获得的锁* @return [type] [description]*/public function unlockAll() {//此标志是用来标志是否释放所有锁成功$allSuccess = true;foreach ($this->lockedNames as $name => $expireAt) {if (false === $this->unlock($name)) {$allSuccess = false;}}return $allSuccess;}/*** 给当前所增加指定生存时间,必须大于0* @param  [type] $name [description]* @return [type]       [description]*/public function expire($name, $expire) {//先判断是否存在该锁if ($this->isLocking($name)) {//所指定的生存时间必须大于0$expire = max($expire, 1);//增加锁生存时间if ($this->redisString->expire("Lock:$name", $expire)) {return true;}}return false;}/*** 判断当前是否拥有指定名字的所* @param  [type]  $name [description]* @return boolean       [description]*/public function isLocking($name) {//先看lonkedName[$name]是否存在该锁标志名if (isset($this->lockedNames[$name])) {//从redis返回该锁的生存时间return (string)$this->lockedNames[$name] = (string)$this->redisString->get("Lock:$name");}return false;}
}

转载于:https://www.cnblogs.com/wt645631686/p/10071867.html

在redis上实现分布式锁相关推荐

  1. Redlock——Redis集群分布式锁

    欢迎关注方志朋的博客,回复"666"获面试宝典 前言 分布式锁是一种非常有用的技术手段.实现高效的分布式锁有三个属性需要考虑: 安全属性:互斥,不管什么时候,只有一个客户端持有锁 ...

  2. redistemplate分布式锁实现_基于 Redis SETNX 实现分布式锁

    环境与配置 Redis 任意版本即可 SpringBoot 任意版本即可,但是需要依赖 spring-boot-starter-data-redis <dependency><gro ...

  3. 阿里JAVA面试题剖析:一般实现分布式锁都有哪些方式?使用 Redis 如何设计分布式锁?...

    面试原题 一般实现分布式锁都有哪些方式?使用 redis 如何设计分布式锁?使用 zk 来设计分布式锁可以吗?这两种分布式锁的实现方式哪种效率比较高? 面试官心理分析 其实一般问问题,都是这么问的,先 ...

  4. Redis 集群分布式锁与 API 网关分布式限流

    https://www.infoq.cn/article/FoQGIk*BzdQWJJ0tKqrJ Redis 集群的历史 Redis 在 3.0 前一般有两种集群方案,一是 proxy(Twempr ...

  5. Redis进阶-细说分布式锁

    文章目录 Pre 引 分布式锁演进 V1 分布式锁演进 V2 分布式锁演进 V3 分布式锁演进 V4 分布式锁演进 V5 终极版-分布式锁演进(Redisson ) V6 Code Redisson分 ...

  6. 基于 Redis 实现的分布式锁

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:我的大学到研究生自学 Java 之路,过程艰辛,不放弃,保持热情,最终发现我是这样拿到大厂 offer 的! 作 ...

  7. redis系列:分布式锁

    1 介绍 这篇博文讲介绍如何一步步构建一个基于Redis的分布式锁.会从最原始的版本开始,然后根据问题进行调整,最后完成一个较为合理的分布式锁. 本篇文章会将分布式锁的实现分为两部分,一个是单机环境, ...

  8. 小王,在 Java 中如何利用 redis 实现一个分布式锁服务呢???

    作者:杨高超 juejin.im/post/5a4984af6fb9a0450b66bc57 在现代的编程语言中,接触过多线程编程的程序员多多少少对锁有一定的了解.简单的说,多线程中的锁就是在多线程环 ...

  9. 【Redis笔记】一起学习Redis | 如何利用Redis实现一个分布式锁?

    一起学习Redis | 如何利用Redis实现一个分布式锁? 前提知识 什么是分布式锁? 为什么需要分布式锁? 分布式锁的5要素和三种实现方式 实现分布式锁 思考思考 基础方案 改进方案 保证setn ...

最新文章

  1. CVPR 2018 论文解读 | 基于GAN和CNN的图像盲去噪
  2. 续说零拷贝(Zero-Copy) - DMA技术
  3. RabbitMQ Topic交换机(结果成功)
  4. linux php版本升级_玩转Linux,介绍一个强大的Linux服务器管理面板,比宝塔更强...
  5. leetcode155|最小栈(java)题解
  6. html里面textfield属性,StyleableTextField的CSS属性htmlText
  7. 光纤带光缆的特点及应用场景
  8. 简单实现RPC/RMI框架
  9. 华硕h410m-f主板检测不到硬盘启动选项?
  10. html设置背景颜色无效,设置背景颜色无效果(第二种实现方式 背景颜色设置不起作用)...
  11. 阿里云域名购买至备案流程
  12. 四川计算机专业的二本大学排名及分数线,2019-2020四川二本大学排名及分数线(理科+文科)...
  13. 小米手机ADB删除系统应用去广告
  14. gbase 8d客户端连接注意事项
  15. tensorflow导出冻结图模型
  16. 通过出生日期计算年龄
  17. 做计算机视觉对电脑配置的要求,计算机视觉环境配置
  18. python IDLE的下载及安装
  19. arcgis更改图层坐标系_arcgis里怎么转换坐标系
  20. 今日头条优化实践: iOS 包大小二进制优化,一行代码减少 60 MB 下载大小

热门文章

  1. linux i查看o性能度量,在linux系统中I/O 调度的选择
  2. android7开发问题,Android开发问题总结(一)
  3. java怎么录入4位会员号_[Java源码]键盘输入会员卡号,对其格式、位数进行判断,不符合规则会跳转重新输入 | 学步园...
  4. 关于vertical layout不能水平居中对齐的原因
  5. non-rigid shape registration using similarity-invariant differential coordinates
  6. inline函数的好处与缺点
  7. Lesson 3 Part 2 logistic regression
  8. 目标检测综述——单阶段检测器
  9. python的read_聊一聊python 的readinto
  10. java dispose null_Java Map释放内存置null以及调用clear()的区别