PHP使用Memcache时模拟命名空间及缓存失效问题的解决


Posted in PHP onFebruary 27, 2016

缓存命名空间

memcache本身不支持命名空间,但是我们可以利用 memcache本身的机制,来模拟命名空间。比如:你要清除一组数据,就需要用到命名空间,来看这样一个例子,说明写在了注释里:

class Action
{
  
 public function index()
 {
  global $mc_wr;
   
  // 获取命名空间
  $ns_key = $mc_wr->get("foo_namespace_key");
  // 如果命名空间不存在,则设置一个
  if($ns_key===false) $mc_wr->set("foo_namespace_key",time());
   
  $otherParms = 'select * from user LIMIT 1';
  // 根据命名空间生成唯一的key
  $my_key = "foo_".$ns_key.'_'.md5($otherParms);
   
  // 获取当前key下的缓存
  $val = $mc_wr->get($my_key);
  if (!$val) {
   $value = 'wangdekang_'.time();
   // 缓存不存在则设置缓存 600秒, 0为随机失效时间, 为失效时间添加随机秒数,防止瞬间所有缓存同时失效
   $mc_wr->set($my_key,$value,600, 0);
  }
   
  echo $val;
 }
  
 public function clear_ns()
 {
  global $mc_wr;
  // 更新命名空间值,让当前命名空间的所有值失效, memcache自身的缓存失效机制,当缓存不在被访问,会通过LRU失效机制
  $mc_wr->set('foo_namespace_key', time());
 }
}

memcache缓存失效问题
在大并发的场合,当cache失效时,大量并发同时取不到cache,会同一瞬间去访问db并回设cache,可能会给系统带来潜在的超负荷风险。
解决方法:

方法一
在load db之前先add一个mutex key, mutex key add成功之后再去做加载db, 如果add失败则sleep之后重试读取原cache数据。为了防止死锁,mutex key也需要设置过期时间。伪代码如下

if (memcache.get(key) == null) {
 // 3 min timeout to avoid mutex holder crash
 if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
  value = db.get(key);
  memcache.set(key, value);
  memcache.delete(key_mutex);
 } else {
  sleep(50);
  retry();
 }
}

方法二
在value内部设置1个超时值(timeout1), timeout1比实际的memcache
timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然
后再从数据库加载数据并设置到cache中。伪代码如下

v = memcache.get(key);
if (v == null) {
 if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
  value = db.get(key);
  memcache.set(key, value);
  memcache.delete(key_mutex);
 } else {
  sleep(50);
  retry();
 }
} else {
 if (v.timeout <= now()) {
  if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
   // extend the timeout for other threads
   v.timeout += 3 * 60 * 1000;
   memcache.set(key, v, KEY_TIMEOUT * 2);

   // load the latest value from db
   v = db.get(key);
   v.timeout = KEY_TIMEOUT;
   memcache.set(key, value, KEY_TIMEOUT * 2);
   memcache.delete(key_mutex);
  } else {
   sleep(50);
   retry();
  }
 }
}
PHP 相关文章推荐
探讨:array2xml和xml2array以及xml与array的互相转化
Jun 24 PHP
php实现两表合并成新表并且有序排列的方法
Dec 05 PHP
Codeigniter的一些优秀特性总结
Jan 21 PHP
PHP中返回引用类型的方法
Apr 03 PHP
Laravel 5框架学习之子视图和表单复用
Apr 09 PHP
PHP学习笔记(二):变量详解
Apr 17 PHP
PHP实现微信网页授权开发教程
Jan 19 PHP
Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法
Mar 29 PHP
PHP控制前台弹出对话框的实现方法
Aug 21 PHP
PHP foreach遍历多维数组实现方式
Nov 16 PHP
php + nginx项目中的权限详解
May 23 PHP
TP - 比RBAC更好的权限认证方式(Auth类认证)
Mar 09 PHP
简单谈谈PHP中strlen 函数
Feb 27 #PHP
详解PHP的Laravel框架中Eloquent对象关系映射使用
Feb 26 #PHP
PHP文件缓存smarty模板应用实例分析
Feb 26 #PHP
PHP计算当前坐标3公里内4个角落的最大最小经纬度实例
Feb 26 #PHP
PHP实现根据时间戳获取周几的方法
Feb 26 #PHP
PHP将二维数组某一个字段相同的数组合并起来的方法
Feb 26 #PHP
关于PHP 如何用 curl 读取 HTTP chunked 数据
Feb 26 #PHP
You might like
PHP.MVC的模板标签系统(五)
2006/09/05 PHP
php中require和require_once的区别说明
2014/02/27 PHP
Windows下安装PHP单元测试环境PHPUnit图文教程
2014/10/24 PHP
Laravel 4 初级教程之Pages、表单验证
2014/10/30 PHP
PHP实现即时输出、实时输出内容方法
2015/05/27 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
javascript 面向对象编程 万物皆对象
2009/09/17 Javascript
基于Asp.net与Javascript控制的日期控件
2010/05/22 Javascript
jquery ajax 同步异步的执行示例代码
2010/06/23 Javascript
js修改table中Td的值(定义td的单击事件)
2013/01/10 Javascript
jQuery学习笔记(3)--用jquery(插件)实现多选项卡功能
2013/04/08 Javascript
js将json格式内容转换成对象的方法
2013/11/01 Javascript
JavaScript获得表单target属性的方法
2015/04/02 Javascript
基于jQuery实现放大镜特效
2020/10/19 Javascript
Javascript typeof与instanceof的区别
2016/10/18 Javascript
jQuery Ajax实现跨域请求
2017/01/21 Javascript
js时间戳与日期格式之间相互转换
2017/12/11 Javascript
vue双向数据绑定知识点总结
2018/04/18 Javascript
详解mpvue中小程序自定义导航组件开发指南
2019/02/11 Javascript
详解Element-UI中上传的文件前端处理
2019/08/07 Javascript
Vue指令之 v-cloak、v-text、v-html实例详解
2019/08/08 Javascript
基于layui table返回的值的多级嵌套的解决方法
2019/09/19 Javascript
vue实现修改图片后实时更新
2019/11/14 Javascript
[01:46]TI4西雅图DOTA2前线报道 中国选手抱团调时差
2014/07/08 DOTA
python实现通过pil模块对图片格式进行转换的方法
2015/03/24 Python
Python中datetime常用时间处理方法
2015/06/15 Python
Python装饰器的执行过程实例分析
2018/06/04 Python
使用python Fabric动态修改远程机器hosts的方法
2018/10/26 Python
python安装requests库的实例代码
2019/06/25 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
助人为乐好少年事迹材料
2014/08/18 职场文书
入党积极分子个人总结
2015/03/02 职场文书
工会工作个人总结
2015/03/03 职场文书
廉洁自律心得体会2016
2016/01/13 职场文书
Redis做数据持久化的解决方案及底层原理
2021/07/15 Redis
RestTemplate如何通过HTTP Basic Auth认证示例说明
2022/03/17 Java/Android