php 使用redis锁限制并发访问类
1.并发访问限制问题
对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功。
例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券。
伪代码如下:
if A(可以换领)B(执行换领)C(更新为已换领) D(结束)
如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会更新为已换领(C)。因此如果用户在有一个更新为已换领之前,有多少次请求,这些请求都可以执行成功。
2.并发访问限制方法
使用文件锁可以实现并发访问限制,但对于分布式架构的环境,使用文件锁不能保证多台服务器的并发访问限制。
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
本文将使用其setnx方法实现分布式锁功能。setnx即Set it N**ot eX**ists。
当键值不存在时,插入成功(获取锁成功),如果键值已经存在,则插入失败(获取锁失败)
RedisLock.class.php
<?php /*** Redis锁操作类* Date: 2016-06-30* Author: fdipzone* Ver: 1.0** Func:* public lock 获取锁* public unlock 释放锁* private connect 连接*/ class RedisLock { // class startprivate $_config;private $_redis;/*** 初始化* @param Array $config redis连接设定*/public function __construct($config=array()){$this->_config = $config;$this->_redis = $this->connect();}/*** 获取锁* @param String $key 锁标识* @param Int $expire 锁过期时间* @return Boolean*/public function lock($key, $expire=5){$is_lock = $this->_redis->setnx($key, time()+$expire);// 不能获取锁if(!$is_lock){// 判断锁是否过期$lock_time = $this->_redis->get($key);// 锁已过期,删除锁,重新获取if(time()>$lock_time){$this->unlock($key);$is_lock = $this->_redis->setnx($key, time()+$expire);}}return $is_lock? true : false;}/*** 释放锁* @param String $key 锁标识* @return Boolean*/public function unlock($key){return $this->_redis->del($key);}/*** 创建redis连接* @return Link*/private function connect(){try{$redis = new Redis();$redis->connect($this->_config['host'],$this->_config['port'],$this->_config['timeout'],$this->_config['reserved'],$this->_config['retry_interval']);if(empty($this->_config['auth'])){$redis->auth($this->_config['auth']);}$redis->select($this->_config['index']);}catch(RedisException $e){throw new Exception($e->getMessage());return false;}return $redis;}} // class end?>
demo.php
<?php require 'RedisLock.class.php';$config = array('host' => 'localhost','port' => 6379,'index' => 0,'auth' => '','timeout' => 1,'reserved' => NULL,'retry_interval' => 100, );// 创建redislock对象 $oRedisLock = new RedisLock($config);// 定义锁标识 $key = 'mylock';// 获取锁 $is_lock = $oRedisLock->lock($key, 10);if($is_lock){echo 'get lock success<br>';echo 'do sth..<br>';sleep(5);echo 'success<br>';$oRedisLock->unlock($key);// 获取锁失败 }else{echo 'request too frequently<br>'; }?>
测试方法:
打开两个不同的浏览器,同时在A,B中访问demo.php
如果先访问的会获取到锁
输出
get lock success
do sth..
success
另一个获取锁失败则会输出request too frequently
保证同一时间只有一个访问有效,有效限制并发访问。
为了避免系统突然出错导致死锁,所以在获取锁的时候增加一个过期时间,如果已超过过期时间,即使是锁定状态都会释放锁,避免死锁导致的问题。
php 使用redis锁限制并发访问类相关推荐
- 29 | 无锁的原子操作:Redis如何应对并发访问?
文章目录 Redis核心技术与实战 实践篇 29 | 无锁的原子操作:Redis如何应对并发访问? 并发访问中需要对什么进行控制? Redis 的两种原子操作方法 Redis核心技术与实战 实践篇 2 ...
- redis锁处理并发问题
redis锁处理并发问题 redis锁处理高并发问题十分常见,使用的时候常见有几种错误,和对应的解决办法,在此进行自己的总结和整理. set方式 setnx方式 setnx+getset方式 set方 ...
- Redis如何应对并发访问
Redis如何应对并发访问 Redis如果在业务中运用那么肯定需要考虑并发问题,如多个用户对同一个商品进行扣减,这时并发执行很可能导致商品数量不对,那么Redis如何来避免这些问题呢?一般分为两种解决 ...
- 线程池,Volatile,原子性类AtomicInteger,乐观锁悲观锁,并发工具类Hashtable,ConcurrentHashMap类,Semaphore类
目录 一.线程的状态 二.线程池 1.创建线程池的方式 1.1线程池-Executors默认线程池 1.2线程池-Executors创建指定上限的线程池 1.3线程池-ThreadPoolExec ...
- 【锁】Redis锁 处理并发 原子性
[锁]Redis锁 处理并发 原子性 如果为空就set值,并返回1 如果存在(不为空)不进行操作,并返回0 很明显,比get和set要好.因为先判断get,再set的用法,有可能会重复set值. se ...
- 线程池、volatile、原子性、并发工具类
目录 线程状态 线程池-基本原理 线程池 - Executors默认线程池 线程池 - ThreadPoolExecutor 线程池参数-拒绝策略 volatile 原子性 原子性 - AtomicI ...
- [转]高并发访问下避免对象缓存失效引发Dogpile效应
避免Redis/Memcached缓存失效引发Dogpile效应 Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应). 推荐阅读:高并 ...
- 数据库锁解决并发问题
数据库锁解决并发问题 问题描述: 一个优惠券活动,用户可以领取优惠券,但是一个优惠券活动领取数量有限制,所以用户在领取的时候就需要先统计一下以领用的优惠券数量. 然后在生成这张优惠券领取记录.那么此时 ...
- 29 Redis 应对并发访问的无锁原子操作
29 Redis 应对并发访问的无锁原子操作 前言 一.并发访问中需要对什么进行控制? 二.Redis 的两种原子操作方法: 总结 前言 在使用 Redis 时,不可避免地会遇到并发访问的问题,比如说 ...
最新文章
- jQuery-1.样式篇---选择器
- [NOIP1999] 提高组 洛谷P1014 Cantor表
- 这是我的卡,去买个包吧
- 怎么修改SQL Server服务器选项,Analysis Services 实例的 SPN 注册 | Microsoft Docs
- flume消费kafka数据太慢_kafka补充01
- Opencv之使用pylibdmtx解析DataMatrix码
- Android -- Looper.prepare()和Looper.loop() —深入版
- 基于ERP与移动通信平台的商务系统设计
- 用ImDisk在Windows 10中创建内存虚拟盘
- 遇害的中国留美博士生,被追授博士学位!导师帮他完成了学业!
- 【寻找最佳小程序】02期:腾讯旅游首款小工具“旅行小账本”——创意及研发过程大起底
- Docker(五)——Docker镜像仓库
- 密码学——对称加密加密模式
- 旅游攻略应该怎么做,你做对了吗?
- Graham扫描法求解二维凸包问题
- flutter 控制iOS设备屏幕可旋转支持方向
- 6.20 C语言练习(找出1至99之间的全部同构数。同构数是这样的一组数:它出现在平方数的右边。)
- leetcode 5473-灯泡开关4
- ubuntu及shell脚本常用命令入门
- 初级SQL开发汇总指南
热门文章
- php mysql 白屏_apache+php+mysql的白屏问题
- 计算机强化课程计算机网络,大学计算机网络技术课程教学改革
- 程序语言python循环_Python语言程序设计之一--for循环
- python 预测算法_通过机器学习的线性回归算法预测股票走势(用Python实现)
- excel不能插入activex控件_办公小技巧:制作更炫酷的Excel下拉菜单
- 小程序返回上一页_智能小程序档案馆手把手教你成为小程序流量头号玩家(上)...
- mysql 多项式_多项式拟合和最小二乘问题
- (一)操作系统概论复习要点笔记
- opencv国际象棋_国际象棋是的
- 【大数据】企业级大数据技术体系概述