redis 缓存锁的实现方法
1. redis加锁分类
redis能用的的加锁命令分表是INCR、SETNX、SET
2. 第一种锁命令INCR
这种加锁的思路是, key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作进行加一。
然后其它用户在执行 INCR 操作进行加一时,如果返回的数大于 1 ,说明这个锁正在被使用当中。
、 客户端A请求服务器获取key的值为1表示获取了锁
、 客户端B也去请求服务器获取key的值为2表示获取锁失败
、 客户端A执行代码完成,删除锁
、 客户端B在等待一段时间后在去请求的时候获取key的值为1表示获取锁成功
、 客户端B执行代码完成,删除锁 $redis->incr($key);
$redis->expire($key, $ttl); //设置生成时间为1秒
3. 第二种锁SETNX
这种加锁的思路是,如果 key 不存在,将 key 设置为 value
如果 key 已存在,则 SETNX
不做任何动作
、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
、 客户端A执行代码完成,删除锁
、 客户端B在等待一段时间后在去请求设置key的值,设置成功
、 客户端B执行代码完成,删除锁 $redis->setNX($key, $value);
$redis->expire($key, $ttl);
4. 第三种锁SET
上面两种方法都有一个问题,会发现,都需要设置 key 过期。那么为什么要设置key过期呢?如果请求执行因为某些原因意外退出了,导致创建了锁但是没有删除锁,那么这个锁将一直存在,以至于以后缓存再也得不到更新。于是乎我们需要给锁加一个过期时间以防不测。
但是借助 Expire 来设置就不是原子性操作了。所以还可以通过事务来确保原子性,但是还是有些问题,所以官方就引用了另外一个,使用 SET
命令本身已经从版本 2.6.12 开始包含了设置过期时间的功能。
、 客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
、 客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
、 客户端A执行代码完成,删除锁
、 客户端B在等待一段时间后在去请求设置key的值,设置成功
、 客户端B执行代码完成,删除锁 $redis->set($key, $value, array('nx', 'ex' => $ttl)); //ex表示秒
5. 其它问题
虽然上面一步已经满足了我们的需求,但是还是要考虑其它问题?
1、 redis发现锁失败了要怎么办?中断请求还是循环请求?
2、 循环请求的话,如果有一个获取了锁,其它的在去获取锁的时候,是不是容易发生抢锁的可能?
3、 锁提前过期后,客户端A还没执行完,然后客户端B获取到了锁,这时候客户端A执行完了,会不会在删锁的时候把B的锁给删掉?
6. 解决办法
针对问题1:使用循环请求,循环请求去获取锁
针对问题2:针对第二个问题,在循环请求获取锁的时候,加入睡眠功能,等待几毫秒在执行循环
针对问题3:在加锁的时候存入的key是随机的。这样的话,每次在删除key的时候判断下存入的key里的value和自己存的是否一样
do { //针对问题1,使用循环
$timeout = ;
$roomid = ;
$key = 'room_lock';
$value = 'room_'.$roomid; //分配一个随机的值针对问题3
$isLock = Redis::set($key, $value, 'ex', $timeout, 'nx');//ex 秒
if ($isLock) {
if (Redis::get($key) == $value) { //防止提前过期,误删其它请求创建的锁
//执行内部代码
Redis::del($key);
continue;//执行成功删除key并跳出循环
}
} else {
usleep(); //睡眠,降低抢锁频率,缓解redis压力,针对问题2
}
} while(!$isLock);
redis 缓存锁的实现方法的更多相关文章
- redis缓存切面实现(支持缓存key的spel表达式)
1.定义注解 package com.g2.order.server.annotation; import java.lang.annotation.ElementType; import java. ...
- Redis分布式锁解决抢购问题
转:https://segmentfault.com/a/1190000011421467 废话不多说,首先分享一个业务场景-抢购.一个典型的高并发问题,所需的最关键字段就是库存,在高并发的情况下每次 ...
- Redis 分布式锁及缓存注释的使用方法
使用工具:Apache an 测压命令: ab -n 100 -c 100 http://www.baidu.com -n代表模拟100个请求,-c代表模拟100个并发,相当于100个人同时访问 ab ...
- Redis 利用锁机制来防止缓存过期产生的惊群现象-转载自 http://my.oschina.net/u/1156660/blog/360552
首先,所谓的缓存过期引起的“惊群”现象是指,在大并发情况下,我们通常会用缓存来给数据库分压,但是会有这么一种情况发生,那就是在一定时间 内生成大量的缓存,然后当缓存到期之后又有大量的缓存失效,导致后端 ...
- $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )
$.ajax()方法详解 jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...
- SpringBoot集成Redis分布式锁以及Redis缓存
https://blog.csdn.net/qq_26525215/article/details/79182687 集成Redis 首先在pom.xml中加入需要的redis依赖和缓存依赖 < ...
- Java 使用Redis缓存工具的图文详细方法
开始在 Java 中使用 Redis 前, 我们需要确保已经安装了 redis 服务及 Java redis 驱动,且你的机器上能正常使用 Java. (1)Java的安装配置可以参考我们的 Java ...
- 使用方法拦截机制在不修改原逻辑基础上为 spring MVC 工程添加 Redis 缓存
首先,相关文件:链接: https://pan.baidu.com/s/1H-D2M4RfXWnKzNLmsbqiQQ 密码: 5dzk 文件说明: redis-2.4.5-win32-win64.z ...
- AbpVnext使用分布式IDistributedCache Redis缓存(自定义扩展方法)
AbpVnext使用分布式IDistributedCache缓存from Redis(带自定义扩展方法) 我的依赖包的主要版本以及Redis依赖如下 1:添加依赖 <PackageReferen ...
随机推荐
- syslog-ng 学习
摘要:http://luyongxin88.blog.163.com/blog/static/925580720112275183903/ 因为工作的需要,涉及到了syslog-ng.现在看来,在外包 ...
- Hyperledger Fabric CA的命令行用法
介绍Hyperledger Fabric CA的命令行方式简单用法 Hyperledger Fabric CA由server和client两部分组成. 设置两个环境变量 export FABRIC_C ...
- Java 基础 面向对象修饰符和自定义数据类型
不同修饰符使用细节 常用来修饰类.方法.变量的修饰符如下: public 权限修饰符,公共访问, 类,方法,成员变量 protected 权限修饰符,受保护访问, 方法,成员变量 默认什么也不写 也是 ...
- 开发中清除css加载的缓存使用
- 从零开始一起学习SLAM | 相机成像模型
上一篇文章<从零开始一起学习SLAM | 为啥需要李群与李代数?>以小白和师兄的对话展开,受到了很多读者的好评.本文继续采用对话的方式来学习一下相机成像模型,这个是SLAM中极其重要的内容 ...
- selenium键盘操作
键盘操作需引用: from selenium.webdriver.common.keys import Keys 操作码表: NULL = '\ue000' CANCEL = '\ue001' # ^ ...
- 巧用CurrentThread.Name来统一标识日志记录(续)
▄︻┻┳═一Agenda: ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录 ▄︻┻┳═一巧用CurrentThread.Name来统一标识日志记录(续) ▄︻┻┳═一巧用Cur ...
- 30.get和post的区别
POST和GET的区别 Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE.URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个 ...
- BDD 与DSL 入门
正文: Behavior Driven Development,行为驱动开发是一种敏捷软件开发的技术,它鼓励软件项目中的开发者.QA和非技术人员或商业参与者之间的协作.在了解Behavior Driv ...
- Python底层库的函数中from __future__ import absolute_import的作用
在查看TensorFlow的底层优化器时候看到from __future__ import absolute_import 查找相关资料后发现 这个语句的意思是加入绝对引用的特征 直白的意思是,比如: ...