memcache@facebook

memcache@facebook演讲者是 Marc,FB资深架构师,这个PPT讨论了FB如何通过memcache来进行scale来承载高流量。这篇PPT相当有水准,很多思路值得学习借鉴。 由于未参加Qconf,只是从ppt中分析揣摩,难免有不准确的地方还望指正。

Facebook的规模是400m活跃用户

    *每天有超过60million的status updates,平均每秒694次。
    *每月有超过3billion张照片的上传,平均每秒上传23张。
    *每周有超过5billion的内容碎片信息(web links, news stories,blog posts, notes, photo albums, etc.)的分享,平均每秒8k次
    *网站上平均每个用户有130个好友
    *50billion的好友关系图谱数据

Infrastructure

    *成千上万的服务器分别部署于美国东西海岸的多个机房(包括Web servers、DB servers、Memcache Servers、Other services)

Memcache的状况
所有memcached服务器每秒承担400m次gets请求和28m次sets请求
cache了超过2T的items,超过200T bytes
网路I/O:receive 60GB/s transmit 120GB/s

单台memcached服务器每秒承担80k gets和2k sets
存放200M的items
网络I/O:receive 9.7MB/s, transmit 19MB/s。

Memcache Rules of the Game

    *从 memcache 获取对象
    *如果 miss ,就直接从数据库获取并且将对象 set 到 memcache 中
    *更新数据库中的一条记录,直接从缓存中删除这个对象
    *在 memcache 中存放的对象都是比较简单的对象,没有派生继承之类的对象
    *每一个 memcache 对象直接与数据库中的数据进行映射。也即是说,FB他们绝大多数场景下都是把数据库当做Key/Value Store在使用。

Pools and Threads
不同的对象有着不同大小和不同的访问模式。 facebook 建立了 memcache 池 ( 本人认为用 region 这种说法可能更为贴切 ) ,以此来分隔不同类型的对象以提升缓存性能和内存利用率。

Phatty Phatty Multiget (notes)

    *PHP runtime 是单线程和同步的。
    *要想性能变得更好,得要让数据支持并行读取,这是必须得要让 memcache 以并行的方式获取请求。
    *当初 facebook 只是在 PHP 上使用 polling I/O 的方式。
    *之后他们写了一个 PHP 的 C 扩展,使其支持真正的异步 I/O 。
    *上面的这两个做法所带来的结果是通过并行机制来降低延迟。

Pools and Threads (notes)

    *隐私对象虽小,但命中率很差
    *用户 个人信息 较大,而且具有良好的命中率
    *facebook 他们将不同的类的对象分散到不同的 memcache 服务器的不同的池中。
    *memcache 原本就是一个经典的单线程 的UNIX 守护进程
    *为了 让memcache更好的榨取服务器 的效能 ,在 memcache 服务器上开了 4 个 memcache 实例 ,每个实例占用 1/4 的内存。
    *但也带来了另外的麻烦,比如每个连接数增长了 4 倍
    *4 倍的元数据开销
    *采用 多线程服务

Connections and Congestion (notes)

    *当增加 web 服务器 ,与memcache box的连接也会增长。
    *每个网络服务器运行50-100 PHP 进程。
    *每个 memcache box 有 超过 100 万 + TCP 连接。
    *UDP 可以减少连接的数量。
    *当添加用户和功能, 也就意味着每一次的 memcache 的 multiget 操作所传入的 keys 也在不断的增加。
    *受欢迎的名人和 团体。
    *开放 平台和FBML 。
    *上面这一系列的场景都会导致 拥塞。

Serialization and Compression

    *1 千个 PHP 序列化的对象
    *修改为他们自己设计的序列化
    *基于 thrift 的格式来进行序列化
    *性能提升 3 倍
    *与先前的内存占用相比,变小了 30%
    *采用 gzcompress 来序列化字符串


Multiple Datacenters (notes)

    *早些时候FB是两个数据中心。其中一个中心提供对外服务,另外一个中心并不对外服务,只做灾备。说白了还是一个单数据中心的架构
    *事实上,随着FB的快速成长, 单数据中心无法再满足业务的需求。
    *但即便是这样 FB仍然还是采用了单Master的数据库层次结构。更多是借助于缓存以及对数据库的Sharding来分摊压力。
    *对于memcache还是记住那个游戏规则,数据一旦更新,删除所有层级与之相关的缓存。
    *同时FB通过自行研发的mcproxy来复制多套缓存,以此来抵挡更多的读操作。

Multiple Regions (notes)

    *早期系统只部署在美国西海岸, 由于FB是面向全球的, 这就导致了美国东海岸和欧洲用户的延迟非常严重
    *因此,FB在 Ashburn VA 部署了slave数据库
    *slave 库通过追踪 master 库的 binlog 来进行同步
    *数据同步的过程中肯定会有延迟,同时也会引入一些资源竞争的情况
    *为解决这个问题,FB仍然是通过mcproxy来解决这个问题
    *解决的思路是,在进行 mysql 更新和插入的操作中加入了 对memcache进行 删除的程序逻辑
    *在东海岸也通过 mcproxy 与 slave mysqld进行集成,在其中 加入一个线程来进行同步后的缓存删除清理工作

Replicated Keys (notes)

    *随着像病毒式的groups和applications的不断演进, 从而使得一部分的数据访问频率极高(ppt中称之为Hot key)。
    *对于这种热门数据,他需要比通常的单台memcache服务器处理更多的gets操作。
    *但是前面提到的memcache的游戏规则,一旦更新,删除所有相关的缓存。
    *意味着有更多的请求会打到数据库。同时也意味着这台数据库会执行更多的查询。
    *最终会导致数据库被打死,从而使得与之相关的 groups和applications完全当掉。
    *解决的思路是创建Key别名,并将此分发到不同的服务器上 ,用更多的服务器来分摊请求的压力。
    *再将热门的 keys 分发到所有的 web 服务器上,并存为localcache。
    *每一个 web 服务器 也都 匹配一个 gets 的别名
    *get key:xxx => get key:xxx#N .(没看太懂,以我自己的理解,是不是 key:xxx#N就是key:xxx的副本,key:xxx#N表示本地缓存,key:xxx表示在memcache中的缓存,数据也都是一致的,我估计FB有一个缓存层在统管localcache、memcache等各种类型的cache)
    *遇到更新操作的时候,每个web服务器删除所有的别名缓存以及原有memcache中的缓存。
(最后这两条纯属YY,可能有不正确的地方。)


New Rule

    *如果键是热门数据,那么就采用别名的机制来进行读取
    *在更新的时候删除所有的别名缓存

Mirrored Pools (notes)

    *随着FB的memcache层的成长,keys/packet的比率也在逐渐下降。
    *先前从1个服务器获取100个keys,只需要发送一个 packet ( 100 keys/ 1 server = 1 packet )
    *随着memcache层的增大,100个服务器,那么获取100个keys最糟糕的情况是需要发送100个 packet ( 100 keys/ 100 server = 100 packets )
    *这网络开销多了去了
    *memcache 服务器每次请求的内核中断也多了去了
(看不懂了,直接上原文了%>_<%)

    *Confirmed Info - critical account meta-data
    *Have you confirmed your account    *
    *Are you a minor    *
    *Pulled from large user-profile objects
    *Since we just need a few bytes of data for many users

前面有个动画,看不了,省略号.......
Hot Misses (notes)

    *再回忆一下缓存的游戏规则
    *更新就删除
    *miss了就查库,然后再set到缓存
    *当这个对象是非常poplar的,查询的也会变得频繁,甚至会打死数据库
    *流量控制!

可以通过下面这个Rule来做到流量控制
Memcache Rules of the Game (再给Memcache Rule of the Game添点料)

    *针对于那些热门数据, 一旦miss在进行db查询前抢先加入一个互斥锁。
    *在memcache上针对于这个对象通过add协议加入一个互斥标记。
    *比如这个对象通过key:xxx来获取,如果miss,那么就add一个key:xxx#mutex的缓存(key:xxx => key:xxx#mutex)
    *如果add成功就执行query操作
    *如果add失败(因为mutex缓存已经存在) 回退并重试
    *query操作执行成功后删除mutex缓存

Hot Deletes (notes)

    *FB也尚未走出困境
    *在频繁更新对象的场景下,Cache mutex这招也不管用了。
    *就像viral groups and applications中的membership列表、walls
    *每个进程刚刚才创立一个互斥对象,发现马上这个对象又立即被删除了。
    *...又搞了一次
    *...又搞了一次
    *...虚脱了!

Rules of the Game: Caching Intent
翻译出来总觉得别扭 ,直接看英文吧!

    *Each memcache server is in the perfect position to detect and mitigate contention
    *Record misses
    *Record deletes
    *Serve stale data
    *Serve lease-ids
    *Don’t allow updates without a valid lease id

Shaping Memcache Traffic

    *mcproxy 好比是路由器
    *通过mcproxy进行接入控制
    *通过mcproxy来解决 跨数据中心的传输互联问题

Cache Hierarchies

    *通过mcproxy 来对冷集群进行预热以便让缓存充满后再切换到这堆集群上。
    *对没有缓存的集群进行代理(Proxies for Cacheless Clusters)
对mcproxy感兴趣的童鞋可以去看看moxi。与memcache proxy特性比较类似。
moxi => memcache proxy

Big Low Latency Clusters

    *Bigger Clusters are Better
    *Low Latency is Better
    *L 2.5
    *UDP
    *Proxy Facebook Architecture

Why Memcache Works

    *一句话,通过拆分降低延迟,也会带来更好的用户体验
    *充分利用memcache中提供的一些健壮的原语
    *做好key与server的映射规划,不同的类型的对象分别存放到不同的缓存服务器上(key-to-server mapping)
    *尽可能用并行的方式来获取数据(parallel I/O)
    *流量控制(flow-control)
    *传输设施的构筑,引入mcproxy类似的解决方案来解决一系列的跨机房跨地域的问题。(traffic shaping)
    *scaling问题所涵盖的领域太广,具体场景具体分析,不排除会使用一些特设或临时的(Ad-hoc)解决方案

你可能感兴趣的:(职场,memcache,Facebook,休闲)