在工程师的理想世界中,架构总是美丽的。但在高规模系统的现实世界中,你必须做出妥协。工程师在一开始就必须思考的一个基本问题是恶性的写入速度与读取速度之间的权衡。
通常,你会牺牲其中一个来换取另一个。但在我们的案例中,在AWS中处理PB级数据时,这种妥协并没有影响我们的速度——而是打击了我们的钱包。
我们构建了一个完美写入数据的系统,但每次从存档中读取时,它都以最痛苦的方式消耗预算。毕竟,从AWS读取PB级数据需要支付数据传输费、请求计数费和存储类别检索费...这可是一大笔钱!
这是我们如何优化它使其更高效且更具成本效益的故事!
真实故事:几个月前,我们的一位解决方案架构师想从一个罕见的低流量网站拉取样本导出,以向潜在客户展示产品。由于API中的一个错误,文件数量的安全限制没有被应用。
因为这个"罕见"网站的数据与高流量网站一起分散在数百万个存档中,系统试图恢复我们几乎一半的历史存储来找到那几个页面。
这个诚实的错误最终让我们花费了近$100,000的AWS费用!
现在,我立即修复了API错误(并添加了严格限制),但架构漏洞仍然存在。这是一个定时炸弹...
让我告诉你Bright Data网络存档架构的故事:我如何将系统驱入"廉价"存储的陷阱,以及我如何使用重排管道爬出来。
当我开始在网络存档上工作时,系统已经在摄取大量数据流:每分钟数百万请求,每天数十TB。基础架构的构建有一个主要目标:在不丢失数据的情况下捕获一切。
它依赖于高吞吐量系统最持久的策略:仅追加日志。
对于摄取阶段,这种设计是完美的。在深度存档中存储数据只需几分钱,而写入吞吐量几乎是无限的。
这种架构对写入来说是完美的...直到客户要求历史数据。那时我面临一个根本矛盾:
cnn.com、google.com和shop.xyz的混合。cnn.com的所有页面。"这里就是激发本文的错误所在。像许多工程师一样,我习惯于考虑延迟、IOPS和吞吐量。但我忽略了AWS Glacier计费模型。
我想:"好吧,检索几千个存档很慢(48小时),但不会太贵。"
现实:AWS不仅对API调用收费,还对恢复的数据量收费(每GB检索$)。
想象一个客户请求来自单个域名的1,000个页面。由于写入逻辑是按时间顺序的,这些页面可能分散在1,000个不同的TAR存档中。
为了给客户提供这50 MB的有用数据,灾难发生了:
我们付费恢复TB级的垃圾只为提取金子粒。这是一个经典的数据局部性问题,变成了财务黑洞。
我无法快速更改摄取方法——传入流太并行且庞大,无法"即时"排序(尽管我正在研究),而且我还需要一个适用于已存档数据的解决方案。
因此,我设计了重排管道,一个"碎片整理"存档的后台进程。
这是一个异步ETL(提取、转换、加载)过程,具有几个关键核心组件:
选择:对客户没有要求的数据进行排序是没有意义的。因此,我将所有新数据引导到管道中,以及客户特别要求恢复的数据。我们第一次检索时会多付费,但第二次就不会发生了。
\
洗牌(分组):多个工作程序并行下载未排序的文件,并按域名组织缓冲区。由于系统是异步的,我不担心传入流会使内存过载。工作程序以自己的节奏处理负载。
\
重写:我将排序后的文件写回S3,使用新的前缀(以区分排序文件和原始文件)。
2024/05/05/random_id_ts.tar→[cnn, google, zara, cnn]2024/05/05/cnn/random_id_ts.tar→[cnn, cnn, cnn...] MERGE INTO或UPDATE成本过高。这一变化从根本上改变了产品的经济性:
cnn.com时,系统只恢复cnn.com所在的数据。Bright Data正在进一步扩展网络存档。如果你喜欢:
那么我很想与你交流。
我们正在招聘强大的Node.js工程师,帮助构建下一代网络存档。拥有数据工程和ETL经验是非常有利的。请随时将您的简历发送至[email protected]。
随着我继续扩展存档——以及我不断发现打破它的新创意方法,更多更新即将到来!
\


