文档章节

cache缓存失效高并发读数据库的问题

昨日今日明日
 昨日今日明日
发布于 2012/12/11 00:19
字数 911
阅读 1.3K
收藏 9

精选30+云产品,助力企业轻松上云!>>>

在网上看到有用其他语言实现的例子,这里用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锁定等待 缺点:代码复杂性增加,前台数据要求不那么严格时可以使用这里输入代码

昨日今日明日
粉丝 3
博文 17
码字总数 7394
作品 0
程序员
私信 提问
加载中
此博客有 1 条评论,请先登录后再查看。
数据库缓存一致性问题

缓存是高并发高性能的利器 但是在使用缓存时,特别是更新缓存和更新数据库之间的先后顺序,很多人有不同的争议。 策略 先更新数据库,再更新缓存; 先删除缓存,再更新数据库; 先更新数据库...

春哥大魔王的博客
2018/12/28
47
0
使用缓存的正确姿势

缓存是现在系统中必不可少的模块,并且已经成为了高并发高性能架构的一个关键组件。这篇博客我们来分析一下使用缓存的正确姿势。 缓存能解决的问题 提升性能 缓解数据库压力 缓存的适用场景 ...

osc_ragotoz1
2018/05/14
2
0
缓存层设计套路(一)

一、背景 对于传统的后端业务场景(或者单机应用)中,访问量以及对响应时间的要求均不高,通常只使用DB即可满足要求。这种架构简单,便于快速部署,很多网站发展初期均考虑使用这种架构。但...

_hugh
2018/06/22
0
0
缓存的三种方式

使用缓存的正确姿势 缓存是现在系统中必不可少的模块,并且已经成为了高并发高性能架构的一个关键组件。这篇博客我们来分析一下使用缓存的正确姿势。 缓存能解决的问题 提升性能 绝大多数情况...

osc_5f6m2xhg
2018/05/14
0
0
缓存ABC

缓存ABC Intro 缓存是一种比较常见的用来将提高系统性能的方式。从线程缓存、进程缓存、到内存缓存再到分布式缓存再到CDN,都是属于缓存的范畴。 缓存的本质是以提高读的效率,牺牲一些内存空...

WeihanLi
2018/08/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

iOS14新特性探索之二:App Widget小组件应用

iOS14新特性探索之二:App Widget小组件应用 iOS 14除了引入了亮眼的App Clips功能外。还有一个也非常惹争议的功能就是App Widget。App Widget可以理解为小组件,在非常早的Android版本中就有...

珲少
22分钟前
19
0
科目二笔记

窄路掉头 行至肩膀与白线平行,向左打到底,等待车行进入窄路。待车与路程45°时,回半圈,继续前行待车与边线平行后回正。然后继续行至车盖压住前面的线后向左打到底,伸出头看前轮与边线距...

bug0day
30分钟前
6
0
Java基础系列——数组相关算法(11)

这里介绍一下数组中的常用算法 杨辉三角形 杨辉三角:它的两个边都是1,内部其它都是肩上两个数的和。 public class YangHui { public static void main(String[] args) { ...

卢佳鹏
31分钟前
23
0
thinkphp-nginx.conf

server{ listen 80; server_name test.cn; index index.php; root /data/wwwroot/test_tp5/public; include thinkphp.conf; location ~ [^/]\.php(/|$) ......

mind-blowing
32分钟前
9
0
Mysql死锁处理

1、错误信息 在mysql客户端执行update语句报错信息:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction下面是在程序里面看到的错误信息com.mysql.cj.jdbc.ex...

简到珍
35分钟前
12
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部