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锁限制并发访问类相关推荐

  1. 29 | 无锁的原子操作:Redis如何应对并发访问?

    文章目录 Redis核心技术与实战 实践篇 29 | 无锁的原子操作:Redis如何应对并发访问? 并发访问中需要对什么进行控制? Redis 的两种原子操作方法 Redis核心技术与实战 实践篇 2 ...

  2. redis锁处理并发问题

    redis锁处理并发问题 redis锁处理高并发问题十分常见,使用的时候常见有几种错误,和对应的解决办法,在此进行自己的总结和整理. set方式 setnx方式 setnx+getset方式 set方 ...

  3. Redis如何应对并发访问

    Redis如何应对并发访问 Redis如果在业务中运用那么肯定需要考虑并发问题,如多个用户对同一个商品进行扣减,这时并发执行很可能导致商品数量不对,那么Redis如何来避免这些问题呢?一般分为两种解决 ...

  4. 线程池,Volatile,原子性类AtomicInteger,乐观锁悲观锁,并发工具类Hashtable,ConcurrentHashMap类,Semaphore类

      目录 一.线程的状态 二.线程池 1.创建线程池的方式 1.1线程池-Executors默认线程池 1.2线程池-Executors创建指定上限的线程池 1.3线程池-ThreadPoolExec ...

  5. 【锁】Redis锁 处理并发 原子性

    [锁]Redis锁 处理并发 原子性 如果为空就set值,并返回1 如果存在(不为空)不进行操作,并返回0 很明显,比get和set要好.因为先判断get,再set的用法,有可能会重复set值. se ...

  6. 线程池、volatile、原子性、并发工具类

    目录 线程状态 线程池-基本原理 线程池 - Executors默认线程池 线程池 - ThreadPoolExecutor 线程池参数-拒绝策略 volatile 原子性 原子性 - AtomicI ...

  7. [转]高并发访问下避免对象缓存失效引发Dogpile效应

    避免Redis/Memcached缓存失效引发Dogpile效应 Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应). 推荐阅读:高并 ...

  8. 数据库锁解决并发问题

    数据库锁解决并发问题 问题描述: 一个优惠券活动,用户可以领取优惠券,但是一个优惠券活动领取数量有限制,所以用户在领取的时候就需要先统计一下以领用的优惠券数量. 然后在生成这张优惠券领取记录.那么此时 ...

  9. 29 Redis 应对并发访问的无锁原子操作

    29 Redis 应对并发访问的无锁原子操作 前言 一.并发访问中需要对什么进行控制? 二.Redis 的两种原子操作方法: 总结 前言 在使用 Redis 时,不可避免地会遇到并发访问的问题,比如说 ...

最新文章

  1. jQuery-1.样式篇---选择器
  2. [NOIP1999] 提高组 洛谷P1014 Cantor表
  3. 这是我的卡,去买个包吧
  4. 怎么修改SQL Server服务器选项,Analysis Services 实例的 SPN 注册 | Microsoft Docs
  5. flume消费kafka数据太慢_kafka补充01
  6. Opencv之使用pylibdmtx解析DataMatrix码
  7. Android -- Looper.prepare()和Looper.loop() —深入版
  8. 基于ERP与移动通信平台的商务系统设计
  9. 用ImDisk在Windows 10中创建内存虚拟盘
  10. 遇害的中国留美博士生,被追授博士学位!导师帮他完成了学业!
  11. 【寻找最佳小程序】02期:腾讯旅游首款小工具“旅行小账本”——创意及研发过程大起底
  12. Docker(五)——Docker镜像仓库
  13. 密码学——对称加密加密模式
  14. 旅游攻略应该怎么做,你做对了吗?
  15. Graham扫描法求解二维凸包问题
  16. flutter 控制iOS设备屏幕可旋转支持方向
  17. 6.20 C语言练习(找出1至99之间的全部同构数。同构数是这样的一组数:它出现在平方数的右边。)
  18. leetcode 5473-灯泡开关4
  19. ubuntu及shell脚本常用命令入门
  20. 初级SQL开发汇总指南

热门文章

  1. php mysql 白屏_apache+php+mysql的白屏问题
  2. 计算机强化课程计算机网络,大学计算机网络技术课程教学改革
  3. 程序语言python循环_Python语言程序设计之一--for循环
  4. python 预测算法_通过机器学习的线性回归算法预测股票走势(用Python实现)
  5. excel不能插入activex控件_办公小技巧:制作更炫酷的Excel下拉菜单
  6. 小程序返回上一页_智能小程序档案馆手把手教你成为小程序流量头号玩家(上)...
  7. mysql 多项式_多项式拟合和最小二乘问题
  8. (一)操作系统概论复习要点笔记
  9. opencv国际象棋_国际象棋是的
  10. 【大数据】企业级大数据技术体系概述