关于两个机房的讨论

如何最大限度的提升中国的网站速度,今天发信给我信任的朋友们,老冒回复如下:我朝Internet南北不畅通的解决方案(老旧方案)(需要翻墙。可以在Google Reader里面订阅http://robertmao.com/feeds/latest/访问)。很多要点老冒几乎都提到了,我在此列出我的一些问题和思考,共有用样需求的各位讨论。

1. MySQL跨越广域网的复制(Replication of MySQL)是否稳定可靠

除了老冒写到的基于页面或者部分页面的缓存方案(Squid as cache),还有一种更加冒险,但是实时性更好的方案就是在异地的数据中心建立MySQL的slave节点,进行主数据中心和附属数据中心的Master-slave replication. 按说MySQL复制本身已经是一个非常健壮和成熟的解决方案,但是跨越广域网的效果如何,尚待验证。我觉得,只要延迟平均在秒级别,偶尔出现分钟级别的延迟也可以接受,毕竟整体已经好于缓存+通知过期。

如果通过VPN+SSH在两个机房建立稳定的链路连接,把两个机房可以当成一个网络延迟稍微长一点,稍微不稳定一点的局域网来用,至少比cache方案有一个优点:可以在大动态数据量的时候,获得更好的秒级别的实时性。

同理,基于这种链路的Solr (Lucene)复制,也是一个可以考虑的架构,但是一个未知数。具体情况如何,如小马过河,只有各家自己试过才知道。

如果实现,就可以在系统级别,而非在应用代码级别实现异地的数据的自动cache, validations, rebuild。看起来很美。

2. MySQL master-master复制

除了主从方案,还有一种多中心方案。数据中心A和数据中心B各自有自己的数据库,但为了避免命名冲突,一个中心的数据采用奇数编号,另外一个采用偶数(或者等中心数大于2的时候,对某一大于中心总数的数字取模)。如果从MySQL以及绝大多数的数据库角度,这个操作非常方便。简述如下:

假设A和B在初始时候的数据是一样的,最大编号(auto_increment的上一次给出值)是401。这个时候,只要简单的把两个数据库的auto_increment_increment设成2,

auto_increment_increment = 2

并且把A的数据库的表的AUTO_INCREMENT值设成一个比现在大得多的一个奇数,比如501,B设成502就好了。跳一下的好处是,可以不用停机,在一个机房操作完成的时候有足够的时间去操作第二个机房(只要那个机房的ID增长不要碰到502就好了)。从此A的id就按照503,505向上增长,而B的id开始按照502,504增长。

另外有一种直接使用GUID作为id的方案,个人觉得太重了。

这个方案做ID切分以后,就为master-master replication做好了准备。之后两个中心可以相互实时互相复制了。开起来也很美。

但问题是,在大型系统里面,就算有再成熟的技术,简单的永远胜过复杂的方案。对于master-master的复制,我现在依然心有余悸。我的心理障碍就是因为以前技术支持的时候做过一个case,就是因为Windows 2000里面的Domain Controller可以master-master的复制,原理上是一个有问题,其他的可以把好的信息传过来,但实际上,一个小bug或者一个不小心的配置,可以让一台主域控制器的错误拖垮其他的所有控制器。master-master的方案在多于2个节点的时候,也需要额外的设计。

3. 关于cache

基于文件静态化的方案的好处显而易见,但是过期永远是心头的痛。对于像带有翻页这样的操作,除了第一页,其他页面的cache几乎不可能,因为谁都不愿意因为一条信息的更新,让后面的无穷无尽的翻页页面的cache重建。

对于链路层的动态加速,觉得在现在的CND提供商无法获取真正优势网络资源的实际情况下,好似概念多于实际。

所以,如果需要实时,或者准实时的加速,权衡所有方案,我觉得在异地放置Smart CDN是一个比较可行的解决方案。Smart CDN(抱歉,是我新造的词),就是前端部署的不仅仅是页面缓存,而是包括MySQL,搜索,Memcached等等一系列的服务,然后通过第一条提到的方式进行同步。这。。。。。。不是100%确信,只是一种想法。不过我相信这么做的人应该不在少数。

我这里抛砖引玉,希望有过经验的同学分享你的好主意,尤其是成功的案例。在此谢过。

《关于两个机房的讨论》上的9个想法

  1. 基于文件静态化的方案的好处显而易见,但是过期永远是心头的痛。对于像带有翻页这样的操作,除了第一页,其他页面的cache几乎不可能,因为谁都不愿意因为一条信息的更新,让后面的无穷无尽的翻页页面的cache重建。

    cache有两个级别,一个是实体,比如一个发言,一个是列表,比如一个发言列表,个体的缓存是容易做到的,上面提到的主要是列表没办法缓存。对于这个地方可以这么做的,比如
    列表是由sql语句select * from table where a>10 order by b产生,这种情况下可以在内存中维护符合条件的列表有序集合,每一个实体的更新删除对应修改列表,这样的情况下基本能一直的命中缓存,不知是否详细?

  2. 首先确认,能去想到两个数据中心的时候,你现有的业务已经很庞大,程序员已经把数据库搞到一定程度了,垂直或水平的分割肯定已经有了,你说的 auto_increment += 2 对于一个单独的表来说我是很容易接受的,但是扩大到所有库的所有表时,我已经理解不上去了,这时候同步不一致怎么办?mysql replication 本来就已经让我很不放心(主要是延迟不确定),我觉得这东西最适合的场景是备份。

    一组页面的清 cache,是否试过 memcache 的 Namespaces ? http://code.google.com/p/memcached/wiki/FAQ#Namespaces
    我是觉得缓存前一页或前三页之类的就可以了,因为通常第一页的访问比重占 98%,其他页没有加 cache 的必要,即使加了命中率也不理想,浪费 memcache 的内存和链接。除非是个别访问量超大的重点区域,这个时候因为基数大所以要 cache,不然我觉得后面的页访问 mysql slave 就可以了。当然,还是看实际环境,先加上,看命中率再决定是否去掉。

    关于 mysql 和 memcached 直接更新方式,我想这个可能你已经看过了 http://www.facebook.com/note.php?note_id=23844338919&id=9445547199&index=0

  3. Platinum 的第一条说得很有道理,就是我们在考虑两个数据中心的时候,更多的情况容易陷入技术的讨论,而忽略足够的必要性的研究。是否分开是一个比如何分开重要得多的决定。这是另外值得讨论的话题。

    就拆分本身,的确是库的一个或指定的几个单独的表要进行奇偶数拆分,而不需要对每一个表。因为最近的web应用,不同于企业级的ERP,CRM或者必须画出UML图才能理解的大型的应用。它的特点大多是表简单,但是数据量超大。对于奇偶分割,仅仅是为了避免在两个中心同时写入时id的冲突。如果仅仅是不经常变动的配置表,大可不必拆分。甚至保证这些表仅在一地修改,并且同步到异地更好。(我的倾向:就算是主表,也是在一个地方写,在多个地方读,也就是倾向于我的第一种设计,而不是第二种master-master replication)

  4. 像论坛、天涯这种,第一页是最老数据的,全cache也是可能的,特别是天涯,删帖还占楼就更方便了。blog这种把新数据做第一页的,做全数据cache也是可以的,反过来把最老数据做第一页就行,最新一页的cache可能不满一页,总是取两页cache合并,稍显复杂,如果有删除会比较麻烦。对于cache命中率要求比较高的,总是会偏复杂。

  5. Platinum的这篇文章相当好:http://www.facebook.com/note.php?note_id=23844338919&id=9445547199&index=0,以前还没有看过。

  6. 老冒在邮件里面继续扩展道:

    “SQUID的问题是cache颗粒度太大,导致失效频繁。 其实从技术方案的设计上,完全可以设计出更好的cache server, 在edge server上有简单逻辑来产生页面,而cache server仅cache更小粒度的数据(web slice, data set, data…)以提高命中率。 这种方案我认为更promissing, 曾经有人提出ESI(Edge Side Include)的概念,但不知道为何并没有见更多产品,也许因为这样东西的用户太少,也许因为大的web服务公司把这个认为是自己的竞争武器而不肯提供。 Microsoft 有个Edge Computing Networking的概念和这个是类似的,自己google 一下ESI和ECN吧。”

    的确是这样的,这个问题的本质,也就是方案1和CDN(Squid)的主要不同在于,cache的粒度。对于频繁变化的页面,把其中的一块一块的block(Web slice)cache起来显然比把整个页面cache更合理,而组装工作,我们认为是达到实时性必须的成本。同样,把整个MySQL当做一个Cache来用,随时由master MySQL来更新(过期)slave mysql,就是一个最低粒度的cache机制,然后在此之上,想干什么就可以干什么了。就像我提的Smart CDN的那样子。

    通过老毛冒给的ECN这个关键字找到这个论文:http://www.microsoft2.net/2008/04/27/think-week-paper-edge-computing-network/
    基本上是对于同一个方向的思考。(但是,虽然我和我太太都在微软工作了7年,在几年后重新读微软这篇论文里面关于IP,关于保护自己的competitive advantage宁肯自己做,而不愿意把技术分享给别人的想法,还是觉得非常的不舒服。)

  7. 翻页操作的cache,如果在内部采用多个定长的block,分页时从对应的block中取数据,在这种情况下,假设新增一条记录,只需要更新第一页对应的那个block即可,其它block的cache仍然有效。

  8. 1.文中描述的论坛的list的Cache问题?如果真地出现问题,说明list的访问量已经很大了(数据系统(mysql)撑不住),更新量也很大(简单的cache都失效策略都不管用),所以你可以在前者上解决,也可以在后者上解决。我曾经开发过自己的mysql engine,list是内存模式,所以性能不会比cache差。也开发过类memchace的cache,进行细粒度控制,不是简单的作废keyvalue对,而是多种策略(比如:更新value)

    2.感觉楼主的网站也不小,在机房上没有条件多机房光纤相连?或者是选择这样的IDC?

    3.更新请求如果不是有特殊需求,这种master-master很危险啊。

发表回复

您的电子邮箱地址不会被公开。