P2P 不是让网络更快,是把「上传」这个人人都有的资源摊开用。 人数越多越快,只有一个人时一点不快——这是它的本质。
前一节是「一个人看一路流」,这一节是「一群人互相传同一份文件」。 Demo 把 1 GB 文件、10 Mbps 服务器这条账算清楚,看倍数到底从哪儿来。
一、三种形态,一条演进线
P2P 的定义很简单:每个节点既是客户端也是服务器。 但「谁管索引」这一件事,决定了三种完全不同的实现。
| 形态 | 谁管索引 | 典型代表 | 问题 |
|---|---|---|---|
| 集中式 | 中央服务器 | Napster | 服务器挂了全网瘫 |
| 纯分布式 | 靠泛洪查询 | Gnutella | 查询流量随人数平方涨 |
| 混合式 | tracker 给名单 | BitTorrent | tracker 仍是单点 |
第二行的问题是致命的:泛洪查询的意思是「问遍我认识的所有人,他们再问遍他们认识的人」, 流量会随人数平方增长,所以纯分布式网络一上规模就自己把自己淹死。 第三行是今天的答案:tracker 只负责「告诉你还有谁在下载」,文件本身一点不经过它。 于是索引这件事依然集中,但流量彻底分散——这是「集中」和「分散」各取一半的折中。 再往后一步是 DHT,也就是分布式哈希表,它把「谁有这个文件」这件事也分散到所有节点上, tracker 就不需要了。 Kademlia 是最常见的实现,BitTorrent 的「无 tracker 种子」就靠它。
二、为什么人数越多越快
先看纯服务器模式:1 GB 的文件、服务器上行 10 Mbps,一个人下要 819 秒, 一百个人下就是把这 819 秒重复一百遍,因为服务器得把同一份数据发一百次。 一百人共 22.76 小时,一千人 9.48 天。 这就是「热门内容一上线就瘫」的数学原因:服务器带宽是固定的,而需求随人数线性增长。 P2P 改了一件事:下完的人变成新的源。 总上传能力等于「服务器上行加上所有 peer 上行之和」, 这个和随人数增长,所以人均时间不再线性变长。 一千人时总上传到 1010 Mbps,比单机快 101 倍。 但第一行必须看清楚:一个人时是 1.00 倍。 peer 的上传能力这时完全用不上,因为它手上还没有东西。 这一点极常被忽略:P2P 不创造带宽,它只改变数据从谁那儿出发。 没有第二个人的时候,它和直接下载一模一样。
三、四个把理想拉回现实的因素
101 倍是理论值,真实环境到不了,原因有四条:
| 限制 | 具体是什么 |
|---|---|
| 不对称带宽 | 家宽上行常常只有下行的十分之一 |
| 搭便车 | 一部分人只下不上,有效 peer 远小于总人数 |
| 分块调度 | 块的分布不均,最后几块要靠少数人补齐 |
| NAT 穿透 | 大量 peer 在 NAT 后面,直连要靠打洞 |
第一条最容易被低估:你按 1 Mbps 上行估算,实际家宽可能只有 200 kbps, 总上传能力立刻缩水,所以真实测出来的加速比往往只有理论值的几分之一。 第三条是 BitTorrent 里最经典的「最后一公里」问题: 所有块都齐了,就差一块,而这一块只在一个人手里——那个人就是全网瓶颈。 所以真实客户端会做「稀有块优先」,先把最稀缺的块补上, 这是「调度策略比带宽更重要」的典型场景。 第四条决定了「能不能连上」:两个都在 NAT 后面的 peer 没法直接建连, 要靠 STUN 探出自己的公网地址、靠打洞让两边同时发包, 实在打不通就退回 TURN 中继——而中继一开,流量又回到了服务器上。 所以 P2P 从来不是「不需要服务器」,是「服务器少干点活」。
四、动手 Demo:P2P 不是「更快」,是「把上传摊开」
1 GB 文件、服务器上行 10 Mbps、每个 peer 上行 1 Mbps,把两种模式的耗时和倍数一起算出来。
size, up, peer = 1024, 10, 1.0 # MB、Mbps、每 peer Mbps
for n in (1, 10, 100, 1000):
t_cs = size * 8 * n / up
t_p2p = max(size * 8 / up, size * 8 * n / (up + n * peer))
print(n, round(t_cs), round(t_p2p), "%.2f 倍" % (t_cs / t_p2p))
实跑输出:
--------------------------------------------------------------------
P2P 不是「更快」,是「把上传摊开」
--------------------------------------------------------------------
**一个 1 GB 的文件,服务器上传带宽 10 Mbps。**
**纯客户端服务器模式,100 个人下载要多久**:**答案是把 100 份都从服务器发一遍。**
下载人数 服务器总耗时 折合小时 折合天
------------------------------------------------------
1 819 秒 0.23 小时 0.01 天
10 8192 秒 2.28 小时 0.09 天
100 81920 秒 22.76 小时 0.95 天
1000 819200 秒 227.56 小时 9.48 天
**第三行已经要 22 小时了。**
**而且这 22 小时里,第一个下载的人早就下完了**——**后面的人在排队等带宽。**
**P2P 的做法是「下完的人变成新的源」**:**每个下载者一边下一边上传,总上传能力随人数增长。**
**一个常用的估算式是「服务器上传加所有 peer 上传之和」。**
人数 总上传能力 P2P 耗时 纯服务器耗时 快多少
----------------------------------------------------------------
1 11 Mbps 819 秒 819 秒 1.00 倍
10 20 Mbps 4096 秒 8192 秒 2.00 倍
100 110 Mbps 7447 秒 81920 秒 11.00 倍
1000 1010 Mbps 8111 秒 819200 秒 101.00 倍
**注意第一行是 1.00 倍,一点没快**:**只有一个人时,那份数据还是得从服务器出发。**
**peer 的上传能力这时完全用不上,因为它手上还没有东西。**
**这一点常被忽略:P2P 不创造内容,它只改变内容的流向。**
**从 10 人往上,优势才开始出现**,
**而且人数越多,倍数越接近「总上传能力除以服务器上传」这个比值。**
**1000 人时快了 101.0 倍**——**因为总上传能力从 10 Mbps 涨到了 1010 Mbps。**
**但真实的 P2P 到不了这个数**,原因有四条:
限制 具体是什么
------------------------------------------------------------------
**不对称带宽** **家宽上行只有下行的十分之一**
**搭便车** **一部分人只下不上,有效 peer 数远小于总人数**
**分块调度** **块的分布不均,最后几块要靠少数人补齐**
**NAT 穿透** **大量 peer 在 NAT 后面,直连要靠打洞**
**第三条是 BitTorrent 里最经典的「最后一公里」问题**:
**所有块都齐了,就差一块,而这一块只在一个人手里**——**那这个人就是瓶颈。**
**所以真实的客户端会做「稀有块优先」,先把最少的块补上。**
**这是「调度策略比带宽更重要」的典型场景。**
第一行是 1.00 倍,这是这段代码最该记住的地方。
它说明 P2P 的加速完全来自「别人也有这份数据」,而不是来自什么更聪明的协议。
倍数趋近的那个值可以推出来:人多了以后,耗时约等于「总量除以总上传」,
而纯服务器模式是「总量乘人数除以服务器上传」,
两者一比,倍数就趋近「总上传除以服务器上传」,
也就是 1 加「人数乘单 peer 上行除以服务器上行」。
所以想把倍数做高,要么人多,要么每个人的上行大。
代码里那个 max 别漏掉:它保证耗时不会小于「服务器独自发完一份的时间」,
没有它,一人时会算出比直连还快的结果,那是模型错了,不是世界错了。
30 秒实验
- 算一下:每个 peer 上行只有 0.5 Mbps 时,一千人是多少倍?(总上传 510 Mbps,约 51 倍,正好减半)
- 想一下:为什么倍数有个理论上限?(上限就是「总上传除以服务器上传」)
- 想一下:tracker 挂了,为什么有些种子还能继续下?
常见误区
- 以为「P2P 一定更快」。 一个人时是 1.00 倍,它只是换了个数据流向。
- 以为「peer 越多带宽越够」。 搭便车和不对称上行会吃掉大半,理论值只是天花板。
- 以为「P2P 就等于盗版」。 它只是一种传输拓扑,系统镜像和固件升级分发用的都是它。
自测三问(点开对答案)
1. tracker 在 BitTorrent 里做什么? —— **只给 peer 名单**,文件数据一点都不经过它。 2. 什么是「稀有块优先」? —— **先抢最稀缺的块**,避免最后几块只剩一个来源。 3. DHT 解决了什么问题? —— **把「谁有这份数据」也分散掉**,于是不再需要 tracker。下一节看 LDAP:一种「读多写少」的目录,和数据库刻意做得不一样。
- ☐ (本节完,下一节 8.7.3 LDAP)