• Email:
  • Feeds

  • Posts Tagged ‘cache’


    Memcache mutex设计模式

    周六的S2 Web 2.0技术沙龙上介绍了memcache中使用mutex场景(文后要演讲稿),有网友对详情感兴趣,简单介绍如下。

    场景

    Mutex主要用于有大量并发访问并存在cache过期的场合,如

    • 首页top 10, 由数据库加载到memcache缓存n分钟
    • 微博中名人的content cache, 一旦不存在会大量请求不能命中并加载数据库
    • 需要执行多个IO操作生成的数据存在cache中, 比如查询db多次

    问题

    在大并发的场合,当cache失效时,大量并发同时取不到cache,会同一瞬间去访问db并回设cache,可能会给系统带来潜在的超负荷风险。我们曾经在线上系统出现过类似故障

    解决方法

    方法一
    在load db之前先add一个mutex key, mutex key add成功之后再去做加载db, 如果add失败则sleep之后重试读取原cache数据。为了防止死锁,mutex key也需要设置过期时间。伪代码如下
    (注:下文伪代码仅供了解思路,可能存在bug,欢迎随时指出。)

    if (memcache.get(key) == null) {
        // 3 min timeout to avoid mutex holder crash
        if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
            value = db.get(key);
            memcache.set(key, value);
            memcache.delete(key_mutex);
        } else {
            sleep(50);
            retry();
        }
    }

    方法二
    在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然后再从数据库加载数据并设置到cache中。伪代码如下

    v = memcache.get(key);
    if (v == null) {
        if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
            value = db.get(key);
            memcache.set(key, value);
            memcache.delete(key_mutex);
        } else {
            sleep(50);
            retry();
        }
    } else {
        if (v.timeout <= now()) {
            if (memcache.add(key_mutex, 3 * 60 * 1000) == true) {
                // extend the timeout for other threads
                v.timeout += 3 * 60 * 1000;
                memcache.set(key, v, KEY_TIMEOUT * 2);
    
                // load the latest value from db
                v = db.get(key);
                v.timeout = KEY_TIMEOUT;
                memcache.set(key, value, KEY_TIMEOUT * 2);
                memcache.delete(key_mutex);
            } else {
                sleep(50);
                retry();
            }
        }
    }

    相对于方案一
    优点:避免cache失效时刻大量请求获取不到mutex并进行sleep
    缺点:代码复杂性增大,因此一般场合用方案一也已经足够。

    方案二在Memcached FAQ中也有详细介绍 How to prevent clobbering updates, stampeding requests,并且Brad还介绍了用他另外一个得意的工具 Gearman 来实现单实例设置cache的方法,见 Cache miss stampedes,不过用Gearman来解决就感觉就有点奇技淫巧了。

    附:本次Web2.0技术沙龙演讲主题:微博Cache设计谈,需下载请点击演讲稿下menu/download (需登录slideshare)。

    Twitter系统运维经验

    最近看到的另外一个介绍Twitter技术的视频[Slides] [Video (GFWed)],这是Twitter的John Adams在Velocity 2009的一个演讲,主要介绍了Twitter在系统运维方面一些经验。 本文大部分整理的观点都在Twitter(@xmpp)上发过,这里全部整理出来并补充完整。

    Twitter没有自己的硬件,都是由NTTA来提供,同时NTTA负责硬件相关的网络、带宽、负载均衡等业务,Twitter operations team只关注核心的业务,包括Performance,Availability,Capacity Planning容量规划,配置管理等,这个可能跟国内一般的互联网公司有所区别。

    1. 运维经验

    * Metrics

    Twitter的监控后台几乎都是图表(critical metrics),类似驾驶室的转速表,时速表,让操作者可以迅速的了解系统当前的运作状态。联想到我们做的类似监控后台,数据很多,但往往还需要浏览者做二次分析判断,像这样满屏都是图表的方法做得还不够,可以学习下这方面经验。 据John介绍可以从图表上看到系统的瓶颈-系统最弱的环节(web, mq, cache, db?)
    根据图表可以科学的制定系统容量规划,而不是事后救火。Twitter operation dashboard

    * 配置管理

    每个系统都需要一个自动配置管理系统,越早越好,这条一整理发到Twitter上去之后引起很多回应。

    * Darkmode

    配置界面可以enable/disable 高计算消耗或高I/O的功能,也相当于优雅降级,系统压力过大时取消一些非核心但消耗资源大的功能。

    * 进程管理

    Twitter做了一个”Seppaku” patch, 就是将Daemon在完成了n个requests之后主动kill掉,以保持健康的low memory状态,这种做法据了解国内也有不少公司是这样做。

    * 硬件

    Twitter将CPU由AMD换成Xeon之后,获得30%性能提升,将CPU由双核/4核换成8核之后,减少了40%的CPU, 不过John也说,这种升级不适合自己购买硬件的公司。

    2. 代码协同经验

    * Review制度

    Twitter有上百个模块,如果没有一个好的制度,容易引起代码修改冲突,并把问题带给最终用户。所以Twitter有一强制的source code review制度, 如果提交的代码的svn comment没有”reviewed by xxx”, 则pre-commit脚本会让提交失败, review过的代码提交后会通过自动配置管理系统应用到上百台服务器上。 有@xiaomics同学在Twitter上马上就问,时间成本能否接受?如果有紧急功能怎么办?个人认为紧急修改时有两人在场,一人修改一人review也不是什么难事。

    * 部署管理

    从部署图表可以看到每个发布版本的CPU及latency变化,如果某个新版本latency图表有明显的向上跳跃,则说明该发布版本存在问题。另外在监控首页列出各个模块最后deploy版本的时间,可以清楚的看到代码库的现状。

    * 团队沟通

    Campfire来协同工作,campfire有点像群,但是更适合协同工作。对于Campfire就不做更多介绍,可参考Campfire官方说明。

    3. cache

    • Memcache key hash, 使用FNV hash 代替 MD5 hash,因为FNV更快。
    • 开发了Cache Money plugin(Ruby), 给应用程序提供read-through, write-through cache, 就像一个db访问的钩子,当读写数据库的时候会自动更新cache, 避免了繁琐的cache更新代码。
    • “Evictions make the cache unreliable for important configuration data”,Twitter使用memcache的一条经验是,不同类型的数据需放在不同的mc,避免eviction,跟作者前文Memcached数据被踢(evictions>0)现象分析中的一些经验一致。
    • Memcached SEGVs, Memcached崩溃(cold cache problem)据称会给这种高度依赖Cache的Web 2.0系统带来灾难,不知道Twitter具体怎么解决。
    • 在Web层Twitter使用了Varnish作为反向代理,并对其评价较高。