1.并发访问限制问题

  对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功。

  例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制的情况下,用户则可以使用同一个换领码同时兑换到多张优惠券。

  伪代码如下:

    if A(可以换领)
          B(执行换领)
              C(更新为已换领)
             D(结束)

  如果用户并发提交换领码,都能通过可以换领(A)的判断,因为必须有一个执行换领(B)后,才会更新为已换领(C)。因此如果用户在有一个更新为已换领之前,有多少次请求,这些请求都可以执行成功。

2.并发访问限制方法

  使用文件锁可以实现并发访问限制,但对于分布式架构的环境,使用文件锁不能保证多台服务器的并发访问限制。

  Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

  本文将使用其setnx方法实现分布式锁功能。setnx即Set it N**ot eX**ists。

  当键值不存在时,插入成功(获取锁成功),如果键值已经存在,则插入失败(获取锁失败)

2.简单案例

  RedisLock.class.php

  

 <?php
/**
* Redis锁操作类
* Date: 2016-06-30
* Author: fdipzone
* Ver: 1.0
*
* Func:
* public lock 获取锁
* public unlock 释放锁
* private connect 连接
*/
class RedisLock { // class start private $_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=){
$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' => ,
'index' => ,
'auth' => '',
'timeout' => ,
'reserved' => NULL,
'retry_interval' => ,
); // 创建redislock对象
$oRedisLock = new RedisLock($config); // 定义锁标识
$key = 'mylock'; // 获取锁
$is_lock = $oRedisLock->lock($key, ); if($is_lock){
echo 'get lock success<br>';
echo 'do sth..<br>';
sleep();
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. php 使用redis锁限制并发访问类

    1.并发访问限制问题 对于一些需要限制同一个用户并发访问的场景,如果用户并发请求多次,而服务器处理没有加锁限制,用户则可以多次请求成功. 例如换领优惠券,如果用户同一时间并发提交换领码,在没有加锁限制 ...

  2. PHP进阶与redis锁限制并发访问功能示例

    <?php /** * Redis锁操作类 * Date: 2017-06-30 * Author: fdipzone * Ver: 1.0 * * Func: * public lock 获取 ...

  3. redis锁处理并发问题

    redis锁处理并发问题 redis锁处理高并发问题十分常见,使用的时候常见有几种错误,和对应的解决办法. set方式 setnx方式 setnx+getset方式 set方式 加锁:redis中se ...

  4. oracle的锁与并发机制

    锁是并发访问的时候用于保护不共享资源不被同时并发修改的机制.oracle锁分为DML锁,DDL锁,内部锁和latch DML锁确保一次只能只有一个人修改某一行(TX锁),而且正在处理一个表时别人不能删 ...

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

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

  6. 对象及变量的并发访问(同步方法、同步代码块、对class进行加锁、线程死锁)&内部类的基本用法

    主要学习多线程的并发访问,也就是使得线程安全. 同步的单词为synchronized,异步的单词为asynchronized 同步主要就是通过锁的方式实现,一种就是隐式锁,另一种是显示锁Lock,本节 ...

  7. 【重学Java】多线程进阶(线程池、原子性、并发工具类)

    线程池 线程状态介绍 当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态.线程对象在不同的时期有不同的状态.那么Java中的线程存在哪几种状态呢?Java中的线程 状态被定 ...

  8. 数据库选型之亿级数据量并发访问(MySQL集群)

    刘 勇  Email:lyssym@sina.com 简介 针对实际应用中并发访问MySQL的场景,本文采用多线程对MySQL进行并发读取访问,其中以返回用户所需的数据并显示在终端为测试结束节点,即将 ...

  9. go语言坑之并发访问map

    fatal error: concurrent map read and map write 并发访问map是不安全的,会出现未定义行为,导致程序退出.所以如果希望在多协程中并发访问map,必须提供某 ...

随机推荐

  1. NET Core-TagHelper实现分页标签

    这里将要和大家分享的是学习总结使用TagHelper实现分页标签,之前分享过一篇使用HtmlHelper扩展了一个分页写法地址可以点击这里http://www.cnblogs.com/wangrudo ...

  2. 微信小程序IDE(微信web开发者工具)安装、破解手册

    1.IDE下载 微信web开发者工具,本人是用的windows 10 x64系统,用到以下两个版本的IDE安装工具与一个破解工具包: wechat_web_devtools_0.7.0_x64.exe ...

  3. 神技!微信小程序(应用号)抢先入门教程(附最新案例DEMO-豆瓣电影)持续更新

    微信小程序 Demo(豆瓣电影) 由于时间的关系,没有办法写一个完整的说明,后续配合一些视频资料,请持续关注 官方文档:https://mp.weixin.qq.com/debug/wxadoc/de ...

  4. 浅谈Slick(2)- Slick101:第一个动手尝试的项目

    看完Slick官方网站上关于Slick3.1.1技术文档后决定开始动手建一个项目来尝试一下Slick功能的具体使用方法.我把这个过程中的一些了解和想法记录下来和大家一起分享.首先我用IntelliJ- ...

  5. FineBI:一个简单易用的自助BI工具

    过去,有关企业数据分析的重担都压在IT部门,传统BI分析更多面向的是具有IT背景的人员.但随着业务分析需求的增加,很多公司都希望为业务用户提供自助分析服务,将分析工作落实到业务人员手中.但同时,分析工 ...

  6. ADFS3.0与SharePoint2013安装配置(原创)

    现在越来越多的企业使用ADFS作为单点登录,我希望今天的内容能帮助大家了解如何配置ADFS和SharePoint 2013.安装配置SharePoint2013这块就不做具体描述了,今天主要讲一下怎么 ...

  7. WebStorm 2016 最新版激活(activation code方式)

    WebStorm 2016 最新版激活(activation code方式) WebStorm activation code WebStorm 最新版本激活方式: 今天下载最新版本的WebStorm ...

  8. 编写简单的Makefile文件

    makefile中的编写内容如下: www:hello.c x.h gcc hello.c -o hello clean: rm hello www:hello.c  x.h 表示生成www这个文件需 ...

  9. Web应用之LAMP源码环境部署

    一.LAMP环境的介绍 1.LAMP环境的重要性 思索许久,最终还是决定写一篇详细的LAMP的源码编译安装的实验文档,一来是为了给自己一个交代,把技术进行系统的归纳,将技术以极致的形式呈现出来,做为一 ...

  10. 基于注解的Spring多数据源配置和使用

    前一段时间研究了一下spring多数据源的配置和使用,为了后期从多个数据源拉取数据定时进行数据分析和报表统计做准备.由于之前做过的项目都是单数据源的,没有遇到这种场景,所以也一直没有去了解过如何配置多 ...