文档章节

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

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

在网上看到有用其他语言实现的例子,这里用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)

kslr
kslr
$value = $$model->getlist($catid); 错误
缓存更新的套路

看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,另一个是查询操作...

OSC一霸
2016/09/01
258
0
搞懂分布式技术15:缓存更新的套路

缓存更新的套路 看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,...

你的猫大哥
06/23
0
0
ASP.NET Core 中的缓存

目录 缓存的基本概念 缓存原理 缓存设计 分布式缓存 Memcache 与 Redis 的比较 缓存穿透,缓存击穿,缓存雪崩解决方案 数据一致性 使用内置 MemoryCache 使用分布式缓存 Redis 使用 Stackexc...

RoyZShare
08/14
0
0
大型分布式网站架构:缓存在分布式系统中的应用

缓存是分布式系统中的重要组件,主要解决高并发,大数据场景下,热点数据访问的性能问题。提供高性能的数据快速访问。 一、缓存概述 缓存是分布式系统中的重要组件,主要解决高并发,大数据场...

烂猪皮
04/26
0
0
分布式数据库与缓存双写一致性方案解疑

作者介绍 孤独烟,中国平安研发工程师,目前负责规则云平台架构设计以及需求研发工作。毕业后一直从事Java开发工作,在Web开发、架构设计上有多年的实战经验。在MySQL性能优化、JVM调优、分布...

孤独烟
06/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

67:shell脚本介绍 | shell脚本结构 | 执行data命令用法 | shell脚本中变量

1、shell脚本介绍: shell是一种脚本语言和传统的开发语言相比,会比较简单: shell有自己语法,可以支持逻辑判断、循环等语法: 可以自定义函数,目的是减少重复的代码: shell是系统命令的集合...

芬野de博客
26分钟前
0
0
json schema

json schema是用来验证和描述json对象结构的。 在线验证:https://www.jsonschemavalidator.net/ json schema 编辑器,推荐VSCode,写上"$schema": "https://raw.githubusercontent.com/jso......

谷永权
30分钟前
0
0
部署生产级的 Kubernetes 集群,使用kubespray

部署生产级的 Kubernetes 集群,使用kubespray 项目源码,https://github.com/openthings/kubespray 国内部署,https://github.com/zhangguanzhang/Kubernetes-ansible 欢迎加入 kubernetes......

openthings
38分钟前
0
0
73.分发系统介绍 expect脚本远程登录 执行命令 传递参数

20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行命令 20.30 expect脚本传递参数 20.27 分发系统介绍: 场景:业务越来越大。用的比如app,后端(也就是服务器)所使用...

王鑫linux
43分钟前
0
0
SpringBoot应用不能访问项目静态页面html问题处理

问题描述:SpringBoot搭建web应用在eclipse中启动能够正常访问页面,打包成jar之后不能访问到页面,没有任何出错提示。 环境:使用的是前后端分离架构,没有使用模板,前端html和静态文件放到...

奋斗小蜗牛
46分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部