redis setnx 分布式锁_Redis 分布式锁PHP
Redis 分布式锁的作用
在单机环境下,有个秒杀商品的活动,在短时间内,服务器压力和流量会陡然上升。这个就会存在并发的问题。想要解决并发需要解决一下问题
1、提高系统吞吐率也就是qps 每秒处理的请求书
解决问题一:采用内存型数据库提高系统的qps
解决问题二:就要用到经常会遇到的锁,例如MySQL 有读锁、写锁、排他锁、悲观锁、乐观锁。不过这里只讨论redis来实现锁
简单版设置锁
$redis = new Redis();$redis->connect('127.0.0.1', 6379); //连接Redis$expire = 10;//有效期10秒$key = 'lock';//key$value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期$lock = $redis->setnx($key, $value);//判断是否上锁成功,成功则执行下步操作if(!empty($lock)){//下步操作...}
如果以这样的简单版设置锁就能解决所有问题,未免也太小看 锁 在程序中应用了。
按正常的操作示例基本上都是这样写的。但是这样写有一些问题
1、假如有10000 个请求访问了redis 不存在的键,这样请求就是指接到了MySQL数据,造成CPU短时间内达到100%甚至宕机。这样场景俗称缓存击穿造成的缓存雪崩。
解决问题:引用reids setnx 方法的作用是,当设置的key 不存在时,设置新的值。这样就避免了缓存击穿的问题。检测键的过期时间,避免产生死锁
解决死锁问题
$expire = 10;//有效期10秒 $key = 'lock';//key $value = time() + $expire;//锁的值 = Unix时间戳 + 锁的有效期 $status = true; while($status) { $lock = $redis->setnx($key, $value); if(empty($lock)) { $value = $redis->get($key); if($value < time()) { $redis->del($key); } }else{ $status = false; //下步操作.... } }
2、分布式集群业务业务场景下,每台服务器是独立存在的。多台服务器怎么通过一个标识来相互竞争锁呢。这里就用到了分布式锁
这里简单介绍一下,以MYSQL 的事务机制来延生。事务四个特性ACID,有四种隔离级别:为提交读、已提交读、可重复读、串行化。这些特性都只在单台服务器上生效。到了分布式集群了,数据在不同的服务器上,紧靠事务很难保持数据的一致性及隔离性,事务的作用就意义不大了。Redis也是如此。
正确的分布式锁的打开方式
/** * 实现Redis分布锁 */ $key = 'demo'; //要更新信息的缓存KEY $lockKey = 'lock:'.$key; //设置锁KEY $lockExpire = 10; //设置锁的有效期为10秒 //获取缓存信息 $result = $redis->get($key); //判断缓存中是否有数据 if(empty($result)) { $status = TRUE; while ($status) { //设置锁值为当前时间戳 + 有效期 $lockValue = time() + $lockExpire; /** * 创建锁 * 试图以$lockKey为key创建一个缓存,value值为当前时间戳 * 由于setnx()函数只有在不存在当前key的缓存时才会创建成功 * 所以,用此函数就可以判断当前执行的操作是否已经有其他进程在执行了 * @var [type] */ $lock = $redis->setnx($lockKey, $lockValue); /** * 满足两个条件中的一个即可进行操作 * 1、上面一步创建锁成功; * 2、 1)判断锁的值(时间戳)是否小于当前时间 $redis->get() * 2)同时给锁设置新值成功 $redis->getset() */ if(!empty($lock) || ($redis->get($lockKey) < time() && $redis->getSet($lockKey, $lockValue) < time() )) { //给锁设置生存时间 $redis->expire($lockKey, $lockExpire); //****************************** //此处执行插入、更新缓存操作... //****************************** //以上程序走完删除锁 //检测锁是否过期,过期锁没必要删除 if($redis->ttl($lockKey)) $redis->del($lockKey); $status = FALSE; }else{ /** * 如果存在有效锁这里做相应处理 * 等待当前操作完成再执行此次请求 * 直接返回 */ sleep(2);//等待2秒后再尝试执行操作 } } }
结尾
文章从知识面的广度(mysql)、示例代码优缺点的简介及应用的场景,区别于其他博客文章。嘿嘿~
更多精彩
敬请关注“PHP技术大全”微信公众号
redis setnx 分布式锁_Redis 分布式锁PHP相关推荐
- java redis set 过期时间_redis分布式锁自动延长过期时间
分布式系统概念与设计(原书第5版) 93.8元 包邮 (需用券) 去购买 > 背景项目组已经有个分布式锁注解(参考前文<记一次分布式锁注解化>),但是在设置锁过期时间时,需要去预估业 ...
- redis 集群搭建_Redis分布式缓存分布式集群搭建
当你试图解决一个你不理解的问题时,复杂化就产成了.-Andy Boothe Redis集群安装部署 Redis是一个运行在内存的非关系型数据库,因为其速度快(效率高),支持数据的持久化(安全),事务操 ...
- redis setnx 原子性_Redis从入门到深入-分布式锁(26)
1. 分布式锁 1.1 简介 锁 是一种用来解决多个执行线程 访问共享资源 错误或数据不一致问题的工具 如果 把一台服务器比作一个房子,那么 线程就好比里面的住户,当他们想要共同访问一个共享资源,例如 ...
- redistemplate分布式锁实现_基于 Redis SETNX 实现分布式锁
环境与配置 Redis 任意版本即可 SpringBoot 任意版本即可,但是需要依赖 spring-boot-starter-data-redis <dependency><gro ...
- redis mysql 解决超卖_Redis 分布式锁解决超卖问题
Redis 分布式锁解决超卖问题 1,Redis 事物介绍 1. Redis 事物是可以一次执行多个命令, 本质是一组命令的集合. 2. 一个事务中的所有命令都会序列化, 按顺序串行化的执行而不会被其 ...
- redis 分布式锁 看门狗_redis分布式锁原理及实现
一.写在前面 现在面试,一般都会聊聊分布式系统这块的东西.通常面试官都会从服务框架(Spring Cloud.Dubbo)聊起,一路聊到分布式事务.分布式锁.ZooKeeper等知识. 所以咱们这篇文 ...
- redis 失效时间单位是秒还是毫秒_redis分布式锁的这些坑,我怀疑你是假的开发...
摘要:用锁遇到过哪些问题? 一.白话分布式 什么是分布式,用最简单的话来说,就是为了较低单个服务器的压力,将功能分布在不同的机器上面:就比如: 本来一个程序员可以完成一个项目:需求->设计-&g ...
- redis实现setnx,setex连用实现分布式锁
redis实现分布式锁 1.主要命令: setnx setex 2.主要问题: 使用redis实现分布式锁,利用上面两个命令的特性.但是最重要的是锁要有过期时间,不然万一服务器宕机或者redis宕机, ...
- redis分布式锁实现原理_redis分布式锁实现分析与实践
前言: 在分布式环境中, 我们有些情况下需要使用到锁进行并发控制, 可供基于的 redis, zookeeper,mysql类数据库 基于数据库类的实现是乐观锁, 基于redis,zookeeper的 ...
最新文章
- 漫画 | 如果程序员的妈是产品经理,她会如何逼你结婚?
- linux mysql 1366_Linux MySQl 5.7.17 MySQL ERROR 1366(HY000):Incorrect string value 解决方法
- 完整的Ubuntu18.04深度学习GPU环境配置,英伟达显卡驱动安装、cuda9.0安装、cudnn的安装、anaconda安装
- mysql中用HEX和UNHEX函数处理二进制数据的导入导出
- [渝粤教育] 西南科技大学 线性代数 在线考试复习资料
- 执行shell出现bad interpreter
- C#中 ??、 ?、 ?: 、?.、?[ ]、:
- WebSocket实战之————GatewayWorker使用笔记例子
- LeetCode 788. Rotated Digits
- Windows学习总结(20)——Win10 子系统Linux(Ubuntu 18.04)的安装与卸载
- Android 8.1 频频被曝 Bug,是要赶超苹果吗?
- 鸿蒙的下一个时期叫什么,华为鸿蒙,一个本属于2025年的产品
- 黄淮学院计算机专业录取分数线2019,黄淮学院2020年录取分数线(附2017-2020年分数线)...
- Vue 动态组件component
- 数据加密 ---- SHA 加密
- 目标检测--轻量级网络(截至2022-04-21)
- k8s执行init时出现 Initial timeout of 40s passed
- Burpsuit2.0系列的破解 与jdk 1.80在ubuntu下运行成功.以及代理设置ok,且burp证书导入ok,却不能访问外网的问题.
- python_获取两个数,打印中间值
- php-fpm的重启方法
热门文章
- java授查 非授查异常_java检查异常与非检查异常
- 利用SQL语句对数据进行操作:插入、更新与删除数据行
- 利用python进行数据分析之准备工作(1)
- 标记三维点_便携式3D扫描仪全自动三坐标测量机三维扫描设计扫描测量摄影
- 浅析python类继承(一)
- 定义一个类:实现功能可以返回随机的10个数字,随机的10个字母, 随机的10个字母和数字的组合;字母和数字的范围可以指定,类似(1~100)(A~z)...
- Oracle特殊恢复原理与实战(DSI系列)
- Android 中.aar文件生成方法与用法
- centos7.4安装nginx1.8.1 php7.7.11 安装 MySQL5.7.20
- 8.String、StringBuffer、enum枚举