php环境下cache失效,cache缓存失效高并发读数据库的问题

这篇博客探讨了如何使用PHP实现缓存策略来优化数据库访问。文章通过两种方法展示了如何利用Memcache进行缓存操作,以减少在高并发场景下对数据库的压力。方法一在缓存失效时通过加锁避免了并发读取数据库的问题,而方法二则引入了更复杂的锁机制和过期时间管理,以应对可能的时间不一致性和伪过期情况。这两种方法在不同场景下各有优劣,适用于对数据实时性要求不同的应用。
摘要由CSDN通过智能技术生成

在网上看到有用其他语言实现的例子,这里用php写下,以加深理解。

用php具体代码实现

首先设计一个访问数据库的模型类

class model

{

function getlist($catid)

{

}

}

方法一:

$cache = new cache(); //实例化一个已封装过的memcache类

function getnewlist($catid)

{

global $cache;

$key = "newslist-catid=".$catid; //设置一个cache key

$value = $cache->get($key); //获取key对应的cache

if($value == null) //key 对应的cache过期

{

//按说过期的时候就应读取数据库 用getlist($catid)方法了。在小流量小并发时不会出现什么问题,当大并发时,可能会有几千个人同时访问到了cache失效,如果都去读取db的话,会造成db资源浪费甚至崩溃

并发读取数据库势必会造成很慢的情况,如果还没有从数据库中读取出来并写入到cache中。这时候再有人访问过来,就又进入读取db的操作了。

//因此增加锁

$mutex_key = $key."-mutex"; //设置mutex key,用于支持本key的一个锁

if($cache->add($mutex_key, 1) == true ) //对mutex_key 设置一个整数为1 的缓存,不计算马上存储。add方法就是第一次存储时返回true,如果已经存在返回false。这就相当于一个锁,避免了再次被执行

{

$model = new model(); //实例化模型

$value = $model->getlist($catid); //读取数据库获得catid的列表信息,数据库设置中应为catid建立索引

$cache->set($key, $value);//刷新缓存

$cache->delete($mutex_key);//释放锁缓存

}

else//如果有并发访问过来,等待处理

{

sleep(2); //设置2秒的锁等待

getnewlist($catid);//尝试去读取结果

}

}

return $value;

}

方法二:

$cache = new cache(); //实例化一个memcache类

function getnewlist($catid)

{

global $cache;

$expiretime = 360; //过期时间6分钟

$key = 'newlist-catid='.$catid;

$value = $cache->get($key);

if($value == null) //缓存失效

{

//设置一个锁等待

$mutex_key = $key.'-mutex';

if($cache->add($mutex_key, 1) == true) //设置一个锁

{

$model = new model(); //实例化模型

$value = $model->getlist($catid); //读取数据库获得catid的列表信息,数据库设置中应为catid建立索引

$cache->set($key, array('timeout' => time() + $expiretime, 'value' => $value), $expiretime*2);//刷新缓存,这步可以在cache类中封装

//这里有个问题,就是可能每个cache服务器会出现时间不一致,造成不是你预想的时间。对timeout赋值,如果只设置 $expiretime,如何获取时间节点问题。

$cache->delete($mutex_key);//释放锁缓存

}

else

{

sleep(2); //设置2秒的锁等待

getnewlist($catid);//尝试去读取结果

}

}

else//如果还没有过期

{

//如果timeout已经过期,因为timeout设置的时间短,此时$key还没有到期,实际上是个伪过期时间点,timeout作为一个真正的到期时间点

if($value['timeout'] < time())

{

//设置锁

$mutex_key = $key.'-mutex';

if($cache->add($mutex_key, 1) == true)//首先捕获到并设置个锁

{

$value['timeout'] = time() + $expiretime ; //马上延长过期时间

$cache->set($key, $value, $expiretime*2); //延长时间并保存,防止在高并发状态下,数据库读取时间长,而缓存已失效。

$model = new model(); //实例化模型

$value = $model->getlist($catid); //读取数据库获得catid的列表信息,数据库设置中应为catid建立索引

$cache->set($key, array('timeout' => time() + $expiretime, 'value' => $value), $expiretime*2);//刷新缓存,这步可以在cache类中封装

$cache->delete($mutex_key);//释放锁缓存

}

}

return $value['value'];

}

}

相比于方法一, 优点:避免cache失效时刻,大量请求无法执行add(key_mutex)而进入sleep锁定等待 缺点:代码复杂性增加,前台数据要求不那么严格时可以使用这里输入代码

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值