redis 分布式锁 PHP
redis分布式
1.redis是单线程操作
2.分布式会出现的问题,死锁
3.redis分布式(集群)。多台服务器里面都有多个单机redis。然后这些redis之间相互链接。还有查看各个单台服务器之间是否链接成功,也就是心跳检测
4.在数据方面,他们之间有个锁的问题,叫redis分布式锁
## 常规流程
$redisDb = new Redis('127.0.0.1:6379');
// 获取redis里面的数据
$res = $redisDb->LRANGE();
if(!$res) {
// 如果数据不存在,则去mysql里面获取
$mysqlDb = mysqli_connect();
$res = $mysqlDb->select('*');
// 获取玩了之后插入redis
foreach ($res as $k => $v) {
$redisDb->lPush($v);
}
}
return $res;
这里会出现一个问题,在获取redis数据的时候,出现抢锁的情况
改动后的流程
// 设置redis锁
$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期 $redisDb = new Redis('127.0.0.1:6379');
// 获取数据之前,先获取锁
$status = true;
while ($status) {
$lock = $redisDb->setnx($key,$value);
if($lock) {
// 如果锁存在且在有效期内,则循环继续获取
$value = $redisDb->get($key);
if($value < time()) {
// 如果在有效期外则删除当前锁,下次进来的时候就直接获取数据且退出循环
$redisDb->del($key);
}
}else{
$status = false;
// 获取redis里面的数据
$res = $redisDb->LRANGE();
if(!$res) {
// 如果数据不存在,则去mysql里面获取
$mysqlDb = mysqli_connect();
$res = $mysqlDb->select('*');
// 获取玩了之后插入redis
foreach ($res as $k => $v) {
$redisDb->lPush($v);
}
}
}
}
这里原本就可以是最终的版本,但是看到一些言论说。假设进程1del锁之前崩了。那锁会一直存在,进程2和进程3会同时或得到锁。
### 最终版
// 设置redis锁
$expire = 10;//有效期10秒
$key = 'lock';//key
$value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期 $redisDb = new Redis('127.0.0.1:6379');
// 获取redis里面的数据
$res = $redisDb->LRANGE();
if(!$res) {
$status = true;
while ($status) {
//设置锁值为当前时间戳 + 有效期
$lockValue = time() + $expire;
/**
* 创建锁
* 试图以$lockKey为key创建一个缓存,value值为当前时间戳
* 由于setnx()函数只有在不存在当前key的缓存时才会创建成功
* 所以,用此函数就可以判断当前执行的操作是否已经有其他进程在执行了
* @var [type]
*/
$lock = $redisDb->setnx($key, $lockValue);
/**
* 满足两个条件中的一个即可进行操作
* 1、上面一步创建锁成功;
* 2、 1)判断锁的值(时间戳)是否小于当前时间 $redis->get()
* 2)同时给锁设置新值成功 $redis->getset()
*/
/**
* ($redisDb->get($key) < time() && $redisDb->getSet($key, $lockValue) < time() )
* 这个判断的意思是
* 先判断第一个进程设定的锁是否过期。($redisDb->get($key) < time()
* 获取到的第一个进程的锁的值再给他设定一个新的值。看他的旧值是否过期 $redisDb->getSet($key, $lockValue) < time()
*/
if(!empty($lock) || ($redisDb->get($key) < time() && $redisDb->getSet($key, $lockValue) < time() )) {
//给锁设置生存时间。setnx是系统上给key第一个锁的过期时间,系统不崩,锁会删除。expire是redis自动给key的一个过期时间,系统即使崩了,锁还是会删除
$redisDb->expire($key, $expire);
//***********这里执行业务操作
// 如果数据不存在,则去mysql里面获取
$mysqlDb = mysqli_connect();
$res = $mysqlDb->select('*');
// 获取玩了之后插入redis
foreach ($res as $k => $v) {
$redisDb->lPush($v);
}
//***********并吧数据插入数据库
//以上程序走完删除锁
//检测锁是否过期,过期锁没必要删除
if($redisDb->ttl($key))
$redisDb->del($key);
$status = FALSE; } else {
// 如果锁存在,则表示有其他进程在处理,这里等待
sleep(1);
} } }
return $res;
redis 分布式锁 PHP的更多相关文章
- 利用redis分布式锁的功能来实现定时器的分布式
文章来源于我的 iteye blog http://ak478288.iteye.com/blog/1898190 以前为部门内部开发过一个定时器程序,这个定时器很简单,就是配置quartz,来实现定 ...
- Redis分布式锁
Redis分布式锁 分布式锁是许多环境中非常有用的原语,其中不同的进程必须以相互排斥的方式与共享资源一起运行. 有许多图书馆和博客文章描述了如何使用Redis实现DLM(分布式锁管理器),但是每个库都 ...
- redis分布式锁和消息队列
最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令. 分布式锁 由于目前一些编程语言,如PHP ...
- redis咋么实现分布式锁,redis分布式锁的实现方式,redis做分布式锁 积极正义的少年
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- spring boot redis分布式锁
随着现在分布式架构越来越盛行,在很多场景下需要使用到分布式锁.分布式锁的实现有很多种,比如基于数据库. zookeeper 等,本文主要介绍使用 Redis 做分布式锁的方式,并封装成spring b ...
- Redis分布式锁的正确实现方式
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- Redis分布式锁---完美实现
这几天在做项目缓存时候,因为是分布式的所以需要加锁,就用到了Redis锁,正好从网上发现两篇非常棒的文章,来和大家分享一下. 第一篇是简单完美的实现,第二篇是用到的Redisson. Redis分布式 ...
- redis分布式锁实践
分布式锁在多实例部署,分布式系统中经常会使用到,这是因为基于jvm的锁无法满足多实例中锁的需求,本篇将讲下redis如何通过Lua脚本实现分布式锁,不同于网上的redission,完全是手动实现的 我 ...
- Redis分布式锁的try-with-resources实现
Redis分布式锁的try-with-resources实现 一.简介 在当今这个时代,单体应用(standalone)已经很少了,java提供的synchronized已经不能满足需求,大家自然 而 ...
- 关于分布式锁原理的一些学习与思考-redis分布式锁,zookeeper分布式锁
首先分布式锁和我们平常讲到的锁原理基本一样,目的就是确保,在多个线程并发时,只有一个线程在同一刻操作这个业务或者说方法.变量. 在一个进程中,也就是一个jvm 或者说应用中,我们很容易去处理控制,在j ...
随机推荐
- 函数,递归以及dom简单操作
函数 函数概述 函数就是具备某个功能的一个工具.是完成某个功能的一段代码. 系统提供了很多函数,但是并不能包含所有的功能,所以有些功能需要我们自己来写----自定义函数.函数定义好以后,就可以像系统函 ...
- 高考集训讲课(To 高一)
高考集训讲课(To 高一) 主要是怕下午讲着讲着把自己讲懵了,有一定的迷糊概率 经过机房的讨论,一致认为插头\(DP\)实用性不大,所以这次不讲了,先把重要的讲一讲. 顺便吐槽一下,凭什么另外几个人都 ...
- 【原创】Magisk Root隐藏模块 Shamiko安装
本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Root隐藏模块 Shamiko安装 操 ...
- Chapter 02 - Let's Get Started(C#篇)
详细解释,书上有哈.直接上代码和结果. Xcode下的自定义类 (通过new file-> cocoa class创建,保持和书中名字一样RandomController),自定义的fields ...
- Linux 03 用户管理
参考源 https://www.bilibili.com/video/BV187411y7hF?spm_id_from=333.999.0.0 版本 本文章基于 CentOS 7.6 概述 Linux ...
- ArkUI 组件 Props
在上一篇博客文章中简单地提到了 Props . 在使用 Props 时需要注意到一个点,子组件从寄主页面传递过来的值是单向的,也就是子组件不能直接修改传递下来的值,即单向性. 以上篇文章定义的头像组件 ...
- 理解 Flutter 的基础概念:Widget
Widget 的本意是组件的意思,熟悉 Web 应用开发的人在后期必定会接触到 Vue.React 等框架,这些框架都有一个核心的概念 -- 组件.组件的目的也很简单,那就是重复率用一段代码,并且能够 ...
- Spring 10: AspectJ框架 + @Before前置通知
AspectJ框架 概述 AspectJ是一个优秀的面向切面编程的框架,他扩展了java语言,提供了强大的切面实现 本身是java语言开发的,可以对java语言面向切面编程进行无缝扩展 AOP常见术语 ...
- QT学习(三)
首先整理一下编码的方法.对于一个待解决的问题,首先应该将大问题分解成小问题,将小问题划分为小小问题... 然后再进行类的抽象,将划分成的问题和类进行对应.然后再对划分的小..问题进行具体的处理分析,划 ...
- centos7换清华源
一 删除其他源 cd /etc/yum.repos.d/ 二 创建源 vim CentOS-Base.repo # CentOS-Base.repo # # The mirror system use ...