`
85977328
  • 浏览: 1898598 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

memcached(二十)Dogpile效应

 
阅读更多
    Redis/Memcached高并发访问下的缓存失效时可能产生Dogpile效应(Cache Stampede效应)
    避免Memcached缓存的Dogpile效应
Memcached的read-through cache流程:
  • A客户端读取缓存
  • B没有的话就由客户查询持久层
  • C生成缓存
  • D返回数据


Memcached缓存示例:
package com.chinaso.phl.high.current;

import java.util.ArrayList;
import java.util.List;

import net.rubyeye.xmemcached.MemcachedClient;

/**
 * 缓存一定加载业务层上
 * @author piaohailin
 * @date   2013-12-10
*/
public class TestService {
    private TestDao testDao         = new TestDao();

    MemcachedClient memcachedClient = null;

    public TestService(MemcachedClient memcachedClient) {
        this.memcachedClient = memcachedClient;
    }

    public List<TestVo> getAll() {
        List<TestVo> result = null;

        /*读取缓存 */
        try {
            result = memcachedClient.get("all");
        } catch (Exception e) {
            /*
             如果发生异常,则处理掉,     
             继续读取持久化存储层 
            不能因为缓存的异常,而中断业务
             */
        }
        if (result != null) {
            return result;
        }

        /*读取持久层 */
        result = testDao.getAll();

        /*设置缓存*/
        try {
            if (result == null) {
                //区分查不出数据和持久层里面是空数据的情况,防止高并发空查询持久层
                //是一条空查询,超时时间可以设置短点
                memcachedClient.set("all", 500, new ArrayList<TestVo>());
            } else {
                //查询出数据,超时时间可以稍微多一些
                memcachedClient.set("all", 1800, result);
            }
        } catch (Exception e) {
        }

        /*返回数据*/
        return result;
    }
}

    假如上面的testDao.getAll()是耗时3秒(或更长时间)的运算或数据库操作.当缓存服务器不可用(比如:缓存实例宕机,或网络原因)或是缓存失效瞬间,如果恰好有大量的访问请求,那就会出现机器CPU消耗或数据库操作次数短时间内急剧攀升,可能会引发数据库/Web服务器故障.这种方式不适合在高并发场景下使用,适合并发量低,单次查询耗时的场景.

避免这样的Dogpile效应,通常有两种方法:

使用独立的更新进程
    使用独立的进程(比如:cron job)去更新缓存,而不是让web服务器即时更新数据缓存.举个例子:一个数据统计需要每五分钟更新一次(但是每次计算过程耗时1分钟),那么可以使用cron job去计算这个数据,并更新缓存.这样的话,数据永远都会存在,即使不存在也不用担心产生dogpile效应,因为客户端没有更新缓存的操作.这种方法适合不需要即时运算的全局数据.但对用户对象,朋友列表,评论之类的就不太适用.

使用”锁”
    除了使用独立的更新进程之外,我们也可以通过加”锁”,每次只允许一个客户端请求去更新缓存,以避免Dogpile效应.
处理过程大概是这样的:
  • A请求的缓存没命中
  • A请求”锁住”缓存key
  • B请求的缓存没命中
  • B请求需要等待直到”锁”释放
  • A请求完成,并且释放”锁”
  • B请求缓存命中(由于A的运算)

Memcached使用”锁”的示例:.
package com.chinaso.phl.high.current;

import java.util.ArrayList;

import net.rubyeye.xmemcached.MemcachedClient;

/**
 * @author piaohailin
 * @date   2013-12-10
*/
public class TestSynchronizedService {
    private TestDao testDao         = new TestDao();

    MemcachedClient memcachedClient = null;

    public TestSynchronizedService(MemcachedClient memcachedClient) {
        this.memcachedClient = memcachedClient;
    }

    public TestVo get(String key) throws Exception {
        TestVo result = null;
        /*读取缓存 */
        try {
            result = memcachedClient.get(key);
        } catch (Exception e) {
            /*
             如果发生异常,则处理掉,     
             继续读取持久化存储层 
            不能因为缓存的异常,而中断业务
             */
        }

        if (result != null) {
            return result;
        }

        //此处用法参考类com.chinaso.phl.high.current.TestSychronizedString.java
        //只有在字符串内容相同的时候才会锁起来
        synchronized (key.intern()) {
            try {
                //从缓存读取会比较慢,此处应该在本地设置一个flag,以提高速度
                result = memcachedClient.get(key);
            } catch (Exception e) {
            }
            if (result == null) {
                /*读取持久层 */
                result = testDao.get(key);

                /*设置缓存*/
                try {
                    if (result == null) {
                        //区分查不出数据和持久层里面是空数据的情况,防止高并发空查询持久层
                        //是一条空查询,超时时间可以设置短点
                        memcachedClient.set(key, 500, new ArrayList<TestVo>());
                    } else {
                        //查询出数据,超时时间可以稍微多一些
                        memcachedClient.set(key, 1800, result);
                    }
                } catch (Exception e) {
                }
            }
        }
        /*返回数据*/
        return result;
    }
}

    上面的处理方法有个缺陷,就是缓存失效时,所有请求都需要等待某个请求完成缓存更新,那样无疑会增加服务器的压力.如果能在数据失效之前的一段时间触发缓存更新,或者缓存失效时只返回相应状态让客户端根据返回状态自行处理,那样会相对比较好.

下面的get方法就是返回相应状态由客户端处理:




    上面的memcached缓存失效时,只有一个客户端请求会返回Cache::GenerateData状态,其它的都会返回Cache::NotFound.客户端可通过检测这些状态做相应的处理.
    需要注意的是:”锁”的TTL值应该大于generateData()消耗时间,但应该小于实际缓存对象的TTL值.

参考文章
文章中的Q2整说明的是“dogpile效应”
http://weibo.com/p/1001603862417250608209
分享到:
评论

相关推荐

    memcached 64位 window

    标题"memcached 64位 window"指的是在Windows操作系统上运行的64位版本的Memcached缓存系统。Memcached是一种分布式内存对象缓存系统,广泛用于减轻数据库负载,提高Web应用的性能。由于是64位版本,这意味着它可以...

    memcached安装软件 libevent magent memcached

    Memcached是一款高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库的负载。它通过在内存中存储数据来提供快速的数据访问,从而提高应用的性能。本篇文章将详细讲解如何安装和配置memcached,...

    memcached windows稳定版

    在终端(也即cmd命令界面)下输入 ‘c:\memcached\memcached.exe -d install’ 安装 3. 再输入: ‘c:\memcached\memcached.exe -d start’ 启动。NOTE: 以后memcached将作为windows的一个服务每次开机时自动启动...

    memcached安装包以及MemCachedClient

    首先,你需要下载 Memcached 的源码包或预编译二进制包。在Unix/Linux系统中,通常通过包管理器如`apt-get`(Ubuntu/Debian)或`yum`(CentOS/RHEL)进行安装。例如: ```bash sudo apt-get install memcached ``` ...

    memcached服务器端memcached.exe 下载

    标题“memcached服务器端memcached.exe 下载”指的是获取memcached服务端的可执行文件,`memcached.exe`是Windows环境下运行memcached服务的程序。这个绿色版的memcached意味着它无需安装,下载解压后即可直接运行,...

    windows下memcached+memcached.dll 5.3.8

    1. **下载Memcached**: 首先,你需要访问Memcached的官方网站或者第三方下载站点,找到适用于Windows的最新或指定版本的二进制文件,例如`memcached-5.3.8.zip`。 2. **解压与安装**: 下载完成后,解压文件到一个...

    安装Memcached及Memcached配置

    例如,Windows用户可以访问http://code.jellycan.com/memcached/下载win32二进制文件。 - 安装过程包括解压缩下载的文件到任意目录,例如`D:\memcached`,然后打开命令行工具,切换到`Memcached.exe`所在的目录。 ...

    hibernate-memcached包

    **hibernate-memcached包** 是一个专为Hibernate框架设计的扩展,目的是将流行的分布式内存缓存系统Memcached整合到Hibernate中,作为其二级缓存解决方案。在大型分布式应用中,缓存技术是提高性能的关键,特别是...

    gomemcached, 一个用于围棋的memcached二进制.zip

    gomemcached, 一个用于围棋的memcached二进制 gomemcached这是中的一个memcached二进制协议工具包。它提供客户端和服务器功能以及一小部分示例服务器,如果我值得纯度,就可以以使用服务器。前端服务器设计 基本设计...

    python-memcached python-memcached

    Python-memcached是Python语言的一个库,用于与Memcached缓存系统进行交互。Memcached是一种高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库的负载,提高数据访问速度。Python-memcached库则...

    memcached.exe及memcached.dll

    **二、Memcached.exe和Memcached.dll** 1. **memcached.exe**:这是Memcached服务的可执行文件,通常在Windows系统中运行。它负责启动和管理Memcached服务,处理客户端的请求,并在内存中存储和检索数据。 2. **...

    php7 的memcached扩展php_memcached.dll扩展

    Memcached是一种分布式内存对象缓存系统,广泛应用于Web应用程序,以提高数据读取速度,减轻数据库负载。在PHP环境中,使用Memcached扩展可以方便地存储和检索数据,尤其适用于处理高并发场景。 `...

    项目中使用 hibernate-memcached 做二级缓存

    本文将详述如何在项目中使用Hibernate与Memcached结合实现二级缓存,并探讨Memcached的基本原理和使用方法。 首先,我们需要理解什么是Hibernate的二级缓存。在Hibernate框架中,一级缓存是每个Session级别的,它...

    php memcached安装文档以及Memcached扩展

    ### 二、PHP Memcached扩展安装 1. **选择合适的版本**:根据你的PHP版本,选择对应的`php_memcache.dll`扩展。在提供的文件列表中,我们看到有针对PHP 5.2、5.3和5.4的不同版本。确认你的PHP版本后,选择对应的dll...

    memcached-1.5.4

    **memcached-1.5.4源码分析与编译指南** `memcached`是一款高性能、分布式的内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库负载,提高数据访问速度。它通过将数据存储在内存中,实现快速读取,避免了频繁...

    memcached安装包以及java所需的memcached架包

    **memcached** 是一款高性能、分布式内存对象缓存系统,广泛应用于Web应用中,用于减轻数据库负载,提高数据访问速度。它将数据存储在内存中,以键值对的形式提供快速的数据检索服务。memcached的设计目标是简洁和...

    Windows 下安装 Memcached1

    #### 二、准备工作 1. **下载安装包**:根据您的系统类型(32位或64位)和所需版本号,选择合适的安装包下载。 - 32位系统 1.2.5版本:[下载链接]...

    memcached-1.5.11.tar.gz

    二、Memcached的安装与配置 1. 解压文件:首先,我们需要对"memcached-1.5.11.tar.gz"进行解压,这通常可以通过tar命令完成,例如`tar -zxvf memcached-1.5.11.tar.gz`。 2. 编译与安装:进入解压后的目录,执行`./...

Global site tag (gtag.js) - Google Analytics