Files
solana/docs/i18n/zh/docusaurus-plugin-content-docs/current/cluster/turbine-block-propagation.md

89 lines
5.8 KiB
Markdown
Raw Normal View History

---
title: 涡轮Turbine区块传播
---
Solana 集群使用一个叫做 _Turbine_ 的多层区块传播机制来广播所有节点的交易,该过程只产生少量的重复信息。 群集将自身分成小的节点集合,叫做 _neighborhoods邻居_。 每个节点负责与其附近的其他节点分享它收到的任何数据,同时将数据传播到其他邻居的小节点。 这样,每个节点只需要与少数节点通信。
在其插槽中,领导人节点会在第一个邻居的验证节点\(层 0\) 之间分配碎片。 每个验证节点在其邻居之间共享各自的数据,但也在下一层\(层 1\) 中将碎片转化为某个邻居的一个节点。 每个 1 层节点与邻居节点共享数据, 并在下一层重新传输到节点,以此类推,直到集群中的所有节点都收到了所有碎片。
## 邻居分配 - 权重选择
为了使数据扩散发挥作用,整个集群必须就如何将划分邻居达成一致。 为了实现这一点,所有公认的验证节点 \(TVU 节点\) 都按质押权重排列并存储在一个列表中。 然后以不同的方式索引这该列表,来查明邻居边界并相互重新传送。 例如,领导者只需选择第一个节点来构建层 0。 最高权重的质押持有者会让得票最多的节点优先成为领导者。 0 层和下层节点使用相同的逻辑来找到他们的邻居和下一个层节点。
为了减少攻击向量的可能性,每个碎片都向邻居发送一个随机树。 每个节点使用代表集群的同一批节点。 随机树是通过碎片集生成的它使用领导者ID、插槽和碎片索引来生成种子。
## 层和邻居结构
当前领导者将其初始广播到最多 `DATA_PLANE_FANOUT` 的节点。 如果该层 0 小于集群中的节点数,则数据平面扫描机制在下面添加图层。 随后的图层遵循这些约束来决定图层容量:每个邻居包含的 `DATA_PLANE_FANOUT` 节点。 0 层从带有扩散节点的 1 个邻居开始计算。 每个附加层中的节点数量增加了一个扩散因素。
如上文所述, 图层中的每个节点只能向邻居广播它的碎片,并且在某些下层邻居中只能播放一个节点, 不适用于集群中的每个 TVU 节点。 有一个理解该问题的好方法0 层从带有扩散节点的 1 个邻居开始计算1 层增加扩散邻居, 每个带有扩散节点和 2 层的节点都会有 `扩散 * 在 1 层的节点数量`,以此类推。
这样,每个节点进行通信最大只能达到 `2 * DATA_PLANE_FANOUT - 1` 个节点。
下面的图表显示了领导人如何在 0 层向 0 令居发送两个扩散的碎片,以及 0 邻居的节点如何彼此分享他们的数据。
![领导者向 0 层中的 0 号邻居发送碎片](/img/data-plane-seeding.svg)
下面的图表显示了 Neighborhood 0 如何向 Neighborhood 1和2 进行扩散。
![Neighborhood 0 向Neighborhood 1 和 2 号散播](/img/data-plane-fanout.svg)
最后,下图显示两个层集群都有 2 个扩散。
![具有两个扩散的两层集群](/img/data-plane.svg)
### 设置值
`DATA_PLANE_FANOUT` - 确定层 0 的大小。 后续的层由 `DATA_PLANE_FANOUT` 系数生成。 邻居的节点数量等于扩散值。 某个邻居要在添加新邻居之前被填满即如果某个邻居没有满它_必须_是最后一个。
目前,集群启动的时候就进行了配置。 未来这些参数可能会托管在链上,从而能够随着群组大小的变化而自行调整。
## 计算所需的 FEC 比率
Turbine 依赖于验证器之间数据包的再传输。 由于重新传输,任何网络宽包丢失都会加重, 同时每次访问的数据包未能到达目的地的概率也会增加。 FEC 比率需要考虑网络宽数据包丢失和传播深度。
碎片组是可以使用重建彼此的数据和编码数据集。 每个碎片组都有失败的可能性,其概率大致相当于数据包错误率超过 FEC。 如果验证节点无法重建碎片组,那就无法构建区块,它就必须先修复区块。
碎片组失败的概率可以通过二项分布计算。 如果 FEC 率是 `16:4`, 那么群组大小则为 20而且至少要有 4 个碎片失败才会导致整个组失败。 这等于 20 个碎片中的四条或更多个体失败的概率之和。
涡轮区块成功的概率为:
- 数据包失败的概率为: `P = 1 - (1 - network_packet_loss_rate)^2`
- FEC 率: `K:M`
- 尝试次数: `N = K + M`
- 碎片组失败率: `S = SUM of i=0 -> M for binomial(prob_failure = P, trials = N, failures = i)`
- 每个区块的碎片: `G`
- 区块成功率: `B = (1 - S) ^(G / N)`
- `i` 的精确结果的双向分布被定义为 `(N choose i) * P^i * (1 - P)^(N-i)`
例如:
- 网络丢包率为 15%。
- 50k Tps 的网络每秒产生 6400个碎片。
- FEC 率增加了每个块按 FEC 笔录的总碎片数。
其中 FEC 率为: `16:4`
- `G = 8000`
- `P=1 - 0.85 * 0.85 = 1 - 0.7225 = 0.2775`
- `S = i 的总和 =0 -> 4 为二项分布(prob_fail= 0.2775, trials = 20, fails = i) = 0.689414`
- `B = (1 - 0.689) ^(8000 / 20) = 10^-203`
其中 FEC 率为: `16:16`
- `G = 12800`
- `S = i 的总和 =0 -> 32 为二项分布(prob_fail= 0.2775, trials = 64, fails = i) = 0.002132`
- `B = (1 - 0.002132) ^(12800 / 32) = 0.42583`
其中 FEC 率为: `32:32`
- `G = 12800`
- `S = i 的总和 =0 -> 32 为二项分布(prob_fail= 0.2775, trials = 64, fails = i) = 0.000048`
- `B = (1 - 0.000048) ^(12800 / 64) = 0.99045`
## 邻居Neighborhoods
以下图表显示不同层中两个邻居之间的相互作用。 若要使邻居瘫痪,就需要从上面的邻居建立足够的节点\(擦除代码+1\)。 由于每个邻居都会从上层一个邻居的多个节点收到碎片, 因此上层网络出现大规模故障,才会产生不完整的数据。
![邻居的内部工作](/img/data-plane-neighborhood.svg)