• Feeds

  • Archive for July, 2010


    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)。

    谈团队每周技术交流

    最近在微博上提到了每周五进行一次内部的技术交流,方法也在不断的改进中,目前情况分享如下。希望也能听到一些更好的建议。

    内容选取

    大部分都是接近工作的,比如应用层如何访问cache及db、当前项目的重构或某个复杂的算法等。比如一个重构的话题让大家找出项目中目前不合理的若干问题,并分析这些问题存在的历史原因。然后大家分别发表自己认为合适的解决方案并进行讨论。

    可以取得的成效

    • 团队成员取长补短,获得更全面的技术
    • 分享经验,避免成员步入已知的雷区
    • 提高分析技术问题的能力
    • 认识不足,找到自己需要提高的方向
    • 达成团队更多共识,比如什么是好的做法什么是不推荐的做法

    后续主题

    以后可以进一步考虑的讨论主题,最大的原则是考虑跟近期项目有相关性,比如

    • 互联网应用合适的压力测试方式
    • profiler 系统性能分析,热点调用的主要消耗点并提出解决方案。
    • 工具介绍,可以提高效率或者对工作有帮助
    • 某个算法,如粉丝排序

    与code review的区别

    code review关注代码细节, 团队讨论更关注宏观抽象层面的问题,但部分时候团队讨论也进行一些有代表意义的code改进。

    与主题演讲区别

    倾向于圆桌式的讨论,需要大家参与的开放式问题。以前也尝试过主题式的,但是由于团队内的主题演讲空间有限,演讲者可能要先精通某个领域才适合讲,如果每周一轮不太可行,比如Facebook Engineering tech talks也是精英演讲的方式,结果也不是非常活跃。因此每周一次更合适讨论一些跟工作相关未达成共识的话题,这样更敏捷,也更容易给参与者带来成效。

    -EOF-

    广告:我们团队招收各层次技术人才,包括Java后端工程师,数据架构师(MySQL),PHP工程师, 数据挖掘工程师(如精通Hadoop)等,工作地点是北京,有兴趣可以直接给我邮件。

    上次提到的Web 2.0技术沙龙已经与CSDN顺利举行了第一期,由于之前报名的已经非常多,就未在博客上宣传了,第一期活动今天已经结束。

    Twitter停用Cassandra原因分析

    Twitter在其7.9一篇官方技术博客Cassandra at Twitter Today提到暂停使用Cassandra来代替MySQL存储feed的计划,这是Twitter一个重要的架构策略调整,因为之前Twitter一直是业界Cassandra方向的领头羊。

    For now, we’re not working on using Cassandra as a store for Tweets. This is a change in strategy. Instead we’re going to continue to maintain our existing Mysql-based storage. We believe that this isn’t the time to make large scale migration to a new technology. We will focus our Cassandra work on new projects that we wouldn’t be able to ship without a large-scale data store.

    Twitter为什么要停用Cassandra

    我们来分析一下Twitter停止使用Cassandra的原因
    1. Cassandra仍然缺少大并发海量数据访问的案例及经验,Cassandra来源自Facebook,但是在Facebook内部Cassandra目前只用在inbox search产品上,容量大约有100-200T。且Inbox Search在Facebook的基础架构中也并非核心应用。并且还传出不少rumors说facebook已经放弃Cassandra。

    2. 新产品需要一定稳定期,Cassandra代码或许还存在不少问题,但是Twitter如果投入大量的精力来改进Cassandra和比较优化MySQL的投入来看有点得不偿失。在QCon Beijing上@nk也提到Cassandra在Twitter的内部测试中曾经暴露出不少严重的问题。

    Twitter为什么之前选用Cassandra

    此问题曾经在QCon Beijing 2010做过介绍,在去年的第一期广州技术沙龙也有过交流,类似Twitter这样的网站使用Cassandra的主要原因有
    1. 数据增长规模需要不断增加新服务器,传统的切分方案在面临增删硬件时候需要手工维护,当数据规模速度增快,业务又不运行停机维护,手工维护的成本增加造成系统运维不堪重负。
    2. 不能简单增加服务器解决请求量增长的问题,需要数据架构师精细的规划。
    3. 每一个新的特性都需要重复评估数据拆分及访问优化的问题,架构师需要投入大量精力review几乎相同的业务场景。

    Twitter的调整对于MySQL业界来说或许是一大利好,MySQL虽然受近期Oracle收购阴影的影响,但是对于目前大多数拥有海量数据访问的网站依然是他们第一选择。MySQL简单,可靠,安全,配套工具完善,运维成熟。业界碰到的大部分可扩展性方面的问题在MySQL中其实都有清晰明确的解决方法。虽然重复sharding的问题很烦,增删机器相关的运维工作也很繁琐,但是这些工作量还是在可以接受的范围内。

    究竟Twitter这次策略改变是NoSQL运动的一次挫折还是前进中的一段小插曲?我们拭目以待。目前另外一大Web 2.0巨头Digg仍然在使用Cassandra。