第16课: Scaling Memcache at Facebook
- 我们为什么读这篇论文
- 是关于经验的论文,没有什么新思想/技术
- 三种阅读方式
- 不认真一致性问题的警惕性故事
- 从现成的 S/W 看超高容量的令人印象深刻的故事
- 性能与一致性之间的根本斗争
- 我们可以争论他们的设计,但不是他们的成功
- 网站如何随着负载的增加而扩展?
- 随时间演变的典型故事:
- 1.单机器,web 服务器,应用,数据库
- 数据库存储在磁盘上,崩溃回复,事务,SQL
- 应用查询数据库,格式化,HTML
- 但是负载增长,你的 PHP 应用需要太多的 CPU 时间
- 2.许多 web 前端,一个共享的数据库
- 一个简单的变化,web 服务器和 app 已经分开存储
- 前端无状态,所有共享(和并发控制)通过数据库
- 但是负载增长,增加更多的前端,很快单数据库服务器变成瓶颈
- 3.许多 web 前端,数据库通过数据库集群共享
- 数据库通过 key 分区数据
- app 查看 key(例如用户),决定正确的数据库
- 如果没有数据太受欢迎(注:热门数据)会有很好的数据库并行性
- 痛楚 -- 跨分区的事务和查询可能不生效
- 很难划分得太细
- 但是数据库很慢,即使读,为什么不缓存读请求呢?
- 数据库通过 key 分区数据
- 4.许多 web 前端,很多读缓存,很多写库
- 具有成本效益的大量读取和 memcached 比数据库快10倍
- memcached 只是一个内存哈希表,很简单
- 复杂的数据库和 memcacheds 可能不同步
- 下个瓶颈就是数据库写 -- 很难解决
- 具有成本效益的大量读取和 memcached 比数据库快10倍
- Facebook 基础架构大图
- 很多用户,好友列表,状态,帖子,喜好,照片
- 最新/一致的数据显然并不重要
- 因为人类宽容?
- 高负载:每秒数十亿次操作
- 是一台数据库服务器的吞吐量的10,000倍
- 许多数据中心(至少西部和东部海岸)
- 每个数据中心 -- “区域”
- “真实”数据通过 MySQL 数据库分片
- memcached 层(mc)
- web 服务器(memcached 的客户端)
- 每个数据中心的数据库包含所有副本
- 西海岸的是主服务器(master), 其他的是通过 MySQL 异步日志复制的从服务器(slave)
- 很多用户,好友列表,状态,帖子,喜好,照片
- FB 应用如何使用 mc?
- 读:
v = get(k) (计算 hash(k) 来选择 mc 服务器) if v is nil { v = fetch from DB set(k, v) }
- 写
v = new value send k,v to DB delete(k)
- 应用确定 mc 和数据库的关系
- mc 不知道数据库的一切
- FB 使用 mc 作为“旁观”缓存
- 实际数据在数据库中
- 缓存的值(如果有)应该和数据库一致
- 读:
- FB 在 mc 中存储什么?
- 论文没有说
- 可能是 userID -> name; userID -> friend list; postID -> text; URL -> likes
- 数据库中数据的基本备份
- 论文课程:
- 旁观比看起来的更复杂 -- 一致性
- 论文试图整合互相遗忘的存储层
- 缓存是关键
- 并非真正关于减少用户可见的延迟
- 主要是关于承担巨大负载
- 缓存丢失和故障会造成无法忍受的数据库复制
- 他们可以忍受适度的过时数据:没有新鲜度保证
- 过时数据让人头疼
- 想要避免无限的过时(例如,缺少delete())
- 想要读取自己的写入
- 每个性能修复都带来了新的过时源
- 大量“扇出” => 并行抓取,in-cast 拥塞
- 旁观比看起来的更复杂 -- 一致性