php 回调cache 方案,基于PHP的一种Cache回调与自动触发技术

$s = microtime(true); for($i=0; $iaaa($array, $array, $array); $data = a::bbb($array, $array, $array); } $e = microtime(true); echo "native:".($e-$s)."s\n"; $s = microtime(true); for($i=0; $i

在PHP中,知道一个对象和方法,其实调用方法很简单,比如上面的例子

$a = new a(); $data = $a->aaa($array, $array, $array); $obj = $a; $func = ‘aaa’; $params = array($array,$array,$array); $obj->$func($params[0],$params[1],$params[2]); // 通过这种方式可以直接执行 这种方式的执行性能怎么样,经过我们对比测试发现

native:0.0092940330505371s

call_user_func:0.028635025024414s

call_user_func_array:0.048038959503174s

my_callback:0.11308288574219s

在加入大量方法策略验证中,性能损耗比较低,时间消耗仅是原生方法的1.25倍左右,远小于call_user_func的3倍多,call_user_func_array的5倍多,具体封装后的代码switch(count($params)){

case 0: $result = $obj->{$func}();break;

case 1: $result = $obj->{$func}($params[0]);break;

case 2: $result = $obj->{$func}($params[0],$params[1]);break;

case 3: $result = $obj->{$func}($params[0],$params[1],$params[2]);break;

case 4: $result = $obj->{$func}($params[0],$params[1],$params[2],$params[3]);break;

case 5: $result = $obj->{$func}($params[0],$params[1],$params[2],$params[3],$params[4]);break;

case 6: $result = $obj->{$func}($params[0],$params[1],$params[2],$params[3],$params[4],$params[5]);break;

case 7: $result = $obj->{$func}($params[0],$params[1],$params[2],$params[3],$params[4],$params[5],$params[6]);break;

default: $result = call_user_func_array(array($obj, $func), $params); break;

}

在使用这种方法之前,考虑过使用create_function来创建匿名函数,执行函数回调,经过测试create_function只能创造全局函数,不能创建类函数和对象函数,遂放弃。

完成以上准备工作后,就可以使用回调机制了,再次调用的业务代码….

// 相关变量赋值

$db = new Wk_DB();

$callback[‘obj‘] = $db;

$callback[‘func‘] = ‘getTopFeeds‘;

$callback[‘params‘] =

array(‘site_id‘=>$siteid,‘boutique‘=>$seminal, ‘offset‘=>"0",

‘rows‘ => "20", ‘uid‘

=>null,‘tag_id‘=>$tag_id,‘type‘=>$type);

$top_feed_list =

$cache->smart_fetch(‘site_top_feeds‘,$callback,‘feed‘);

使用以上方法实现对cache调用的封装,同时保证性能的高效,从而解决第一和第四个问题。

至此已经完成前四个问题,从而实现Cache的封装,并有效的避免了上面提到的第二,第三,第四个问题。但是对于第五个问题,dogpile问题,并没有解决,针对这种问题,最好的方式是在cache即将失效前,有一个进程主动触发db操作,获取DB数据放入Cache中,而其他进程正常从Cache中获取数据(因为此时cache并未失效);好在有Redis缓存,我们可以使用Redis的两个特性很好解决这个问题,先介绍下这两个接口

TTL方法:以秒为单位,返回给定 key 的剩余生存时间 (TTL, time to live),当 key 不存在时,返回 -2 。当

key 存在但没有设置剩余生存时间时,返回 -1 。否则,以秒为单位,返回 key

的剩余生存时间。很明显,通过这个方法,我们很容易知道key的还剩下的生存时间,通过这个方法,可以在key过期前做点事情,但是光有这个方法还不行,我们需要确保只有进程执行,而不是所有的进程都做,正好用到下面这个方法。

SETNX方法:将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则SETNX

不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET) 的简写。返回值:设置成功,返回 1

。设置失败,返回 0

。通过这个方法,模拟分布式加锁,保证只有一个进程做执行,而其他的进程正常处理。结合以上Redis方法的特性,解决第五种的问题的,实例代码。…

// 变量初始化

$key = “this is key”;

$expiration = 600;

$recalculate_at = 100;

$lock_length = 20;

$data = $cache->fetch($key);

$ttl = $cache->redis->ttl($key);

if($recalculate_at>=$ttl&&$r->setnx("lock:".$key,true)){

$r->expire(“lock:”.$key, $lock_length);

$db = new Wk_DB();

$data = $db->getXXX();

$cache->store($key, $expiration, $value);

}

原文:http://www.cnblogs.com/2881064178dinfeng/p/7219199.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值