原文链接
:https://blog.csdn.net/tim_phper/article/details/54949404

概述:

项目当中经常要考虑数据高并发的情况,为了避免并发导致出现一些资源重复请求的问题,可以使用缓存加锁机制。 
例如取微信access_token不加锁可能会导致非常严重的后果。

准备:

缓存锁,顾名思义,当然离不开缓存,这篇文章用到的redis缓存,可以根据自己的需要要选择合适缓存。 
缓存锁的原理是在进行操作A之前,先在缓存中存放一个唯一的key,然后就进行对应操作A,而如果同时有其他一样的操作B并发时,因为操作B也需要存放key才能进行操作,而key是唯一的,所以操作B是无法进行存放一样key,也就是说操作B还没开始就被中断了。而当操作A完成之后,或者报错之后就进行释放锁,也就是从缓存当中删除对应的key。除此之外,当操作A操作时间过长时,我们也应该释放锁。具体流程如下图: 

分析:

我这里用的是CI的框架,并不是原生的,但CI的框架也很容易看懂。

//缓存锁class
class Locker { private $_CI; public function __construct() {
$this->_CI = & get_instance();
} /**
* 取锁
* @param type $key
* @param type $timeout 默认锁能锁10秒,10秒后锁自动解除
* @return type
*/
public function lock($key, $timeout = 10) {
$now = time();
$cache_key = $this->_get_key($key); // 如果redis中没有$cache_key,则加锁成功
if ($this->_CI->cache->setnx($cache_key, $now) === true) {
return true;
} // 如果加锁时间超过最大锁时间,则自动解锁,并将锁赋予新的进程
// 特别注意:并发情况下,使用getset方法可以保证只有一个进程获取到锁
// 只有当$last_set_time == $_last_set_time时才是保证当前进程获取到锁
$last_set_time = $this->_CI->cache->get($cache_key);
if ($now - $last_set_time > $timeout) {
$_last_set_time = $this->_CI->cache->getset($cache_key, $now);
if ($last_set_time == $_last_set_time) {
return true;
}
} return false;
} /**
* 释放锁
* @param string $key
* @return boolean
*/
public function release($key) {
$this->_CI->cache->delete($this->_get_key($key));
} private $_lock_key_prefix = 'lock_';
private function _get_key($key) {
return $this->_lock_key_prefix . $key;
} }
  //缓存锁利用过程
////////////////////////////// 加锁进行拿奖 开始 加锁 ////////////////////////
$lock_key = 'get_prize_lock_' . $user->id; //创建唯一key
if ( ! $this->locker->lock($lock_key)) { //判断缓存中是否已经存在唯一key
return $this->send_json(false, '系统繁忙,请稍后重试...','',2);
} // 检查是否已领取过
$where = array(
'act_uuid' => $act_uuid,
'openid' => $user->wx_user_open_id,
'share_from_result_id < ' => 1,
);
$count = $this->data_result_model->count_by($where);
if ( $count > 0 ){
$this->locker->release($lock_key); //每次操作出错都释放锁
return $this->send_json(true, '您已领取过卡券礼包了噢.');
}
//进行数据操作
foreach ($coupon_pkg as $code => $coupon) {
$dateTime = date('Y-m-d H:i:s');
$record = array(
'user_id' => $user->user_id,
'act_uuid' => $act_uuid, ); $this->eggs_data_result_model->add($record);
}
////////////////////////////// 加锁进行拿奖 结束 释放锁 ////////////////////////
$this->locker->release($lock_key); //操作完成释放锁 return $this->send_json(true, '卡券礼包已成功发放。',$act_uuid); //操作完成

总结:

PHP处理数据时,并发情况经常出现,缓存锁机制真的是好处理方法,不过值得注意是经常检查缓存的运行状况,因为一旦缓存挂了,那么整个系统都会出错,无法正常运行的。

PHP缓存锁原理及利用的更多相关文章

  1. 利用多写Redis实现分布式锁原理与实现分析(转)

    利用多写Redis实现分布式锁原理与实现分析   一.关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到. 我举二个例子:场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能 ...

  2. Java进阶专题(二十五) 分布式锁原理与实现

    前言 ​ 现如今很多系统都会基于分布式或微服务思想完成对系统的架构设计.那么在这一个系统中,就会存在若干个微服务,而且服务间也会产生相互通信调用.那么既然产生了服务调用,就必然会存在服务调用延迟或失败 ...

  3. zookeeper 分布式锁原理

    zookeeper 分布式锁原理: 1 大家也许都很熟悉了多个线程或者多个进程间的共享锁的实现方式了,但是在分布式场景中我们会面临多个Server之间的锁的问题,实现的复杂度比较高.利用基于googl ...

  4. MySql 缓存查询原理与缓存监控 和 索引监控

    MySql缓存查询原理与缓存监控 And 索引监控 by:授客 QQ:1033553122 查询缓存 1.查询缓存操作原理 mysql执行查询语句之前,把查询语句同查询缓存中的语句进行比较,且是按字节 ...

  5. MIP缓存加速原理 MIP不仅仅只是CDN

    什么是MIP?我想我们现在都知道.可是你真的了解MIP吗?MIP加速原理是什么?MIP 是用 CDN 做加速的么?准确答案是:是,但不只是. 很多人并认为MIP百度排名会靠前,甚至权重会提高?作为一个 ...

  6. Redis分布式锁原理

    1. Redis分布式锁原理 1.1. Redisson 现在最流行的redis分布式锁就是Redisson了,来看看它的底层原理就了解redis是如何使用分布式锁的了 1.2. 原理分析 分布式锁要 ...

  7. AQS学习(二) AQS互斥模式与ReenterLock可重入锁原理解析

    1. MyAQS介绍    在这个系列博客中,我们会参考着jdk的AbstractQueuedLongSynchronizer,从零开始自己动手实现一个AQS(MyAQS).通过模仿,自己造轮子来学习 ...

  8. Redisson 实现分布式锁原理分析

    Redisson 实现分布式锁原理分析   写在前面 在了解分布式锁具体实现方案之前,我们应该先思考一下使用分布式锁必须要考虑的一些问题.​ 互斥性:在任意时刻,只能有一个进程持有锁. 防死锁:即使有 ...

  9. 【Android - 进阶】之图片三级缓存的原理及实现

    在Android开发中,如果图片过多,而我们又没有对图片进行有效的缓存,就很容易导致OOM(Out Of Memory)错误.因此,图片的缓存是非常重要的,尤其是对图片非常多的应用.现在很多框架都做了 ...

随机推荐

  1. [android] 优酷环形菜单-旋转动画

    获取房子,菜单图标ImageView对象,获取三个圆环RelativeLayout对象 给菜单图标(icon_menu)设置点击事件 定义一个成员变量isLevel3Show来存储第三级菜单是否显示 ...

  2. 模版方法模式(Template Method)

    1.概念 在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行.这种类型的设计模式属于行为型 ...

  3. 一个挺好用的生成GIF格式图片的小程序

    import os import re import imageio pic_list = os.listdir() pic_type = ['png', 'jpg', 'jpeg', 'bmp'] ...

  4. JS--我发现,原来你是这样的JS(引用类型不简单[上篇],且听我娓娓道来)

    一.介绍 没错,这是第五篇,到了引用类型,这次要分成两次博文了,太多内容了,这是前篇,篇幅很长也很多代码,主要讲引用类型和常用的引用类型,代码试验过的,老铁没毛病. 坚持看坚持写,不容易不容易,希望大 ...

  5. MySQL数据库图文安装详解及相关问题

    (尊重劳动成果,转载请注明出处: http://blog.csdn.net/qq_25827845/article/details/53366444冷血之心的博客) 首先说明:安装目录中不能有中文和空 ...

  6. FineReport中如何安装移动端H5插件

    1. HTML5报表插件安装及使用编辑 插件安装 插件网址以及设计器插件安装方法和服务器安装插件的方法可以官网上面搜索,这里就不做详细介绍了. 移动端HTML5报表使用方法 安装好插件后,在浏览器中调 ...

  7. 网络基础 HTTP协议之HTTP消息(HTTP Message)

    HTTP协议之HTTP消息(HTTP Message) by:授客 QQ:1033553122 1.   消息类型(Message Type) HTTP messages包含从客户端到服务器的请求和服 ...

  8. Pytest+Allure环境的搭建

    参考博客 测试报告解释 pytest+allurre进阶 1. pytest的安装: 1.1. windows下: pip install pytest 1.2. linux下: pip instal ...

  9. go语言开发环境、goland、IDE

    1.下载: https://studygolang.com/dl 可以从这个网址下载,版本根据你的系统来: 64位系统,可以下载推荐版本: 我安装的是32位系统,下载的是下面这个: 如果你的是其他的系 ...

  10. idea常规设置

    java开发目前很多都是使用IntelliJ IDEA这款神器.废话不多说,官网地址:https://www.jetbrains.com/idea/ 我一直都是保持最新版本,安装之后注册. 首先需要安 ...