147.md 11.9 KB
Newer Older
W
wizardforcel 已提交
1
# Tumblr:哈希处理每秒 23,000 个博客请求的方式
W
init  
wizardforcel 已提交
2

W
wizardforcel 已提交
3
> 原文: [http://highscalability.com/blog/2014/8/4/tumblr-hashing-your-way-to-handling-23000-blog-requests-per.html](http://highscalability.com/blog/2014/8/4/tumblr-hashing-your-way-to-handling-23000-blog-requests-per.html)
W
init  
wizardforcel 已提交
4

W
wizardforcel 已提交
5
![](img/b53e7c03eb181dee4f3635b07ef4a84e.png)
W
init  
wizardforcel 已提交
6

W
wizardforcel 已提交
7
*这是 Tumblr 的 SRE 工程师 [](http://michael.tumblr.com/) [Michael Schenck](http://michael.tumblr.com/) 的特邀帖子。*
W
init  
wizardforcel 已提交
8

W
wizardforcel 已提交
9
在 Tumblr,博客(或 Tumblelog)是我们互联网上访问量最高的面孔之一。 tumblelogs 最方便的方面之一是其高度可缓存的特性,这是奇妙的,因为 Tumblr 网络为我们的用户提供了很高的视图/发布比率。 就是说,扩展边界代理层(更不用说缓存层)对满足所有这些请求是必需的,这并非完全简单。
W
init  
wizardforcel 已提交
10

W
wizardforcel 已提交
11
本文介绍了负责博客服务的外围部分的体系结构,这是我们流量更大的外围端点之一。
W
init  
wizardforcel 已提交
12

W
wizardforcel 已提交
13
这是我们的方法。
W
init  
wizardforcel 已提交
14

W
wizardforcel 已提交
15
### 统计信息
W
init  
wizardforcel 已提交
16

W
wizardforcel 已提交
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
*   共有 278 名员工,团队中有 6 名员工负责 Tumblr 的所有外围(Perimeter-SRE),包括一名经理。

*   超过 2800 台服务器中,不到 20%的服务器用于博客服务功能

*   每秒(峰值)超过 23,000 个博客请求

*   每秒(峰值)超过 6,500 个博客缓存清除事件

*   超过 1.96 亿个博客

*   超过 930 亿个帖子

### 平台

*   [HAProxy](http://www.haproxy.org/)

*   [清漆](https://www.varnish-cache.org/)

*   [](http://bird.network.cz/)

### 我们在哪里-基于地图的分区

在早期,我们只需要一台活动和一台备用代理服务器以及清漆节点。 两者都很容易管理,监视和高度可用。

但是,由于要满足所有用户请求,因此将达到容量限制,并且由于流行而导致停机前,必须准备好下一步步骤(即使不是理想的部署)。

### 超出单个代理节点

超出单个 活动 代理服务器的数量非常普遍,并且通常涉及 DNS。 像循环 A 记录这样基本的东西可能会满足您的需求,但通常值得花额外的钱进行健康检查 GSLB 配置(即使您只有一个地理位置)。

DNS 的缺点是,尽管名称服务器将以相当均匀的速率对每个 IP 进行响应,但不能保证每个查找都将用于相同数量的请求。 用户 A 可能在一分钟内向解析的 IP 发出 10 个请求,而机器人 B 可能在同一分钟内发出 100 个请求。 如果您有两个 IP,则用户 A 获得一个 IP,而机器人 B 获得另一个 IP,而它们是仅有的两个发出请求的客户端,那么您的一个代理的请求速率是另一个的 10 倍。

较低的 TTL 可以减轻此影响,以便 30 秒 TTL 可以平衡两个代理之间的那 110 个请求。 在最初的 30 秒内,用户 A 将转到代理 P1,而机器人 B 将转到代理 P2。 然后,他们的下一个解决方案可能会交换 IP,以便用户 A 将其请求发送到代理 P2,而机器人 B 将其请求发送到代理 P1。 在该分钟窗口结束时,每个代理将处理大约 60 个请求。 TTL 较低的缺点是查找更多,因此 DNS 成本较高(但 DNS 通常是您较便宜的第三方服务之一)。

### 超出单个清漆节点

虽然 DNS 可以为您增加代理层的时间,但是缩放清漆要复杂一些。 即使您使用单个清漆节点的容量限制围绕请求并发进行,您也不希望简单地在循环中添加两个清漆节点。 这降低了缓存命中率,清除了更多的资源/时间,并且实际上并没有增加缓存的工作量(仅复制它)。

超出单个清漆节点的最简单迭代是 静态分区 。 这涉及确定您的唯一标识符,并在两个清漆节点之间划分此空间。

对于 Tumblelogs,这是博客的主机名。 由于 DNS 不区分大小写,因此您只需要担心 40 个字符即可。 字母数字(a-z 和 0-9)和四个允许的字符(-_。〜)。 因此,对于两个清漆节点,博客主机名在这两个缓存节点之间被分割(在第一个字符上)。

### 均匀分布的分区-通过一致的哈希

前面的两个示例(DNS 循环和静态分区)都是朝着正确方向迈出的一步,但是在分区方面却提供了非常粗糙的粒度。 在足够小的规模上,这种粒度不一定是有问题的,但是随着您的流量开始增长,方差变得更加明显。 结果,减少最不热和最热节点处理的流量差异变得越来越重要。 这就是一致性哈希真正可以发挥作用的地方。

### 分区代理流量

如果您的服务器所处的环境可以影响服务器前面的路由器,用户和代理服务器之间的路由器的路由表,那么您可以利用等价的多 -路径路由(ECMP)。 ECMP 使您能够将代理视为同一哈希环中的多个切片,然后在这些切片之间映射请求者。

这是通过通知到特定目标 IP(高可用性 IP)的多个路径(代理服务器)的路由基础结构来实现的。 然后,ECMP 将对请求源进行哈希处理,以确定哪个代理应接收此请求会话的数据包。 典型的 ECMP 实现提供第 3 层(仅 IP)和第 3 + 4 层(IP:端口)哈希选项。 第 3 层意味着来自特定 IP 的所有请求将转到特定的代理,这可能有助于调试,但与使用单个 NAT IP 的大型网络不平衡。 第 3 + 4 层通常提供最佳的分发,但是调试特定的客户端变得更具挑战性。

有多种方法可以 通知 路由器多个路径,但是我建议使用 OSPF 或 iBGP 进行动态路由通告。 一个人只需要在环回接口上侦听高度可用的 IP,启用内部路由以及将自己的 IP 作为下一跃点广告到该高度可用的 IP。 我们发现 BIRD 提供了一种轻巧可靠的方式来执行来自代理的路由广告。

### 划分清漆流量

Tumblelog 通过其完全限定的域名(FQDN)进行标识,因此,博客的所有 URI 路径将始终在该博客 FQDN 下找到。 Tumblelog 的大部分是 tumblr.com 的子域,例如 [engineering.tumblr.com](http://engineering.tumblr.com/) ,但是我们也支持用户携带自己的自定义域名 。

考虑各种 FQDN 时,很明显,TLD 的变体数量最少,然后是域名(特别是由于绝大多数是 tumblr.com),然后是子域。 因此,我们最重要的位出现在可变长度字符串的最左侧。

### 了解问题域

![](img/acbf9820b55f36b5e6df32353fdd183a.png)

*   完美-演示将散列函数应用于我们的测试数据集时,其散列函数是否为 完美

*   constant_hdr-主机标头上的一致性哈希(最佳现实结果)

*   constant_hdr_use_domain_only-基本域名(即 tumblr.com 或 foo.net)上的一致性哈希,只有两个阵营 tumblr.com 和所有其他域名

*   mapbased_firstchar-将主机标头的第一个字符映射到清漆节点(我们的原始静态分区实现)

*   mapbased_hdr-基于主机标头的映射

虽然一致的散列显然是 tumblelog FQDN 的最平均分布的领先者,但是我们接着确定散列函数是否合适。 默认情况下,HAProxy 使用 SDBM 哈希函数。 但是,在进一步研究后,通过比较 SDBM,CRC,MD5,DJB2 等,我们确定 DJB2 提供了更好的分布。 这导致我们向 HAProxy 提交了补丁,以使哈希函数可配置(有关更多信息,请参见“感谢”部分)。

### 比较静态分区和一致性哈希

![](img/92b6bf9ab0a831619ca9f08d88d90435.png)

这显示了在移至最佳匹配哈希函数之前和之后,每个清漆节点每秒请求之间的方差变化。

### 其他注意事项

### 节点增长

在任一模型中,节点增长将意味着键空间移位,从而导致缓存失效。 在一致的哈希模型中,预测将失效的键的百分比要容易得多。 基本上为 1 / N(N 是添加新节点之前的缓存节点数)。 使用静态分区模型,除非您对要从中获取键空间的节点的请求进行分析,否则最糟糕的情况是小于或等于键上键的总百分比。 您从中获取键空间的节点。

### 节点故障

使用静态分区时,除非您提供故障转移选项,否则单节点故障将导致无法访问 1 / N 密钥。 HAProxy 确实允许您拥有一个备用节点,但是现在您可以决定了。 每个密钥空间有 2N 个缓存节点(一个活动,一个备用)或共享的备用节点。 一种极端情况是 浪费 占硬件的 50%,其中频谱的另一端(所有活动节点之间共享 1 个备用节点)意味着两个故障节点导致备用 支持其他活动节点的密钥空间的 2 倍。

使用一致的哈希,将自动处理节点故障。 删除一个节点后,将移动 1 / N 个键(导致 1 / N 个键无效),并且每个剩余的活动节点的键空间均匀增加。

### 正在清除缓存

将清除请求发送到单个清漆节点很容易,但是从多个清漆节点清除也应该很容易。 不必使代理服务器和清除服务器保持同步,最简单的方法是通过同一代理服务器发送所有清除请求。

拒绝来自非本地 IP 空间的清除尝试非常重要,以防止任何恶意的批量清除。

### 获得的经验教训

*   您知道尚未回答的问题的答案。 面对扩展挑战时,请不要忽视您已经在其他地方使用的模式。

*   通过简单扩展。 在短期内可能会增加复杂性以克服可伸缩性挑战,但最终会赶上您。

*   了解您的哈希函数。 您使用的哈希函数与决定如何处理哈希值同样重要。

*   降级,不失败。 建议您的代理人监视自己达到后端的能力。 如果不能,则不要停止发布路由,而只是发布非优先级路由(例如,使用 OSPF 会增加路径成本)。 这样,如果所有后端都无法正常运行,您仍然可以提供错误页面,而不是无法访问。

### 谢谢

##  *   [Blake Matheny](http://tumblr.mobocracy.net/) 和 [Andrew Terng](http://andrew.tumblr.com/) 进行了散列函数比较并为 HAProxy 创建了补丁。

*   [Bhaskar Maddala](http://maddalab.tumblr.com/) 与 HAProxy 社区合作,以获取 [此功能已添加到 HAProxy 1.5 版本](http://cbonte.github.io/haproxy-dconv/configuration-1.5.html#4.2-hash-type)

*   [Arnoud Vermeer](http://blog.arnoudvermeer.nl/)[Aaron Prat](http://aaronprat.tumblr.com/) 与 ECMP / OSPF 流量分配有关。 

## 相关文章 [

*   [关于 HackerNews](https://news.ycombinator.com/item?id=8132473)
*   [雅虎以 10 亿美元的价格收购了 Tumblr 架构](http://highscalability.com/blog/2013/5/20/the-tumblr-architecture-yahoo-bought-for-a-cool-billion-doll.html)
*   [Tumblr Architecture-150 亿页面浏览量一个月,比 Twitter 难扩展](http://highscalability.com/blog/2012/2/13/tumblr-architecture-15-billion-page-views-a-month-and-harder.html)

对于任何混乱,我们深表歉意,共有 278 位 Tumblr 员工。

负责 Tumblr 所有外围(Perimeter-SRE)的团队由 6 人组成(包括一名经理)。

本文介绍了负责博客服务的外围部分的体系结构,这是我们流量更大的外围端点之一。

对于那些不了解哈希的人来说,它会使您变得 O(1)复杂,并且比对普通 b 树数据库的搜索要快。 令人惊讶的结果,我想这就是您扩展 tumblr 之类的方式的原因:)

非常有趣的文章。
但是有一个问题:您提到 BIRT 是 IP 平衡器,尽管 Haproxy 也是平衡器,但是对于 TCP / HTTP 级别,不是 IP。 那么负载均衡人员到底是谁呢?

感谢您分享这个幕后或“后台”视图。 “ 1.96 亿个博客”数量巨大,接近 1000 亿个帖子表明这些博客已被实际使用,而不是像其他平台那样,通常一旦注册就此后一直处于闲置状态。

从网络工程的角度来看,这非常有趣。 我猜想您的 HAProxy 框上正在运行 BIRD,然后将散列的流量平衡到 Varnish? 是否还可以通过 Varnish 服务器从您的边缘路由器提供网络图? 谢谢!