如何更快下载GCP存储桶内650万个小体积对象?
原来使用gsutil -m cp下载速度极慢的核心原因有三点:
- 单对象体积过小(仅2KB),每个对象单独建立HTTP连接、元数据交互的开销远大于实际数据传输开销
- 本地笔记本到GCP存储桶所在区域的公网延迟高、带宽有限,公网传输小文件的效率极低
- 下载落地为本地文件再删除的操作属于完全无效的IO开销,进一步拉低了处理效率
直接流处理,跳过本地文件落地
无需将对象下载为本地临时文件,直接通过GCS官方SDK将对象内容拉取到内存,处理后直接写入CSV。以Python的google-cloud-storage库为例,核心逻辑如下:from google.cloud import storage import csv # 初始化GCS客户端 client = storage.Client() bucket = client.get_bucket("你的存储桶名称") # 遍历指定前缀下的所有对象 blobs = bucket.list_blobs(prefix="你的文件夹前缀") with open("output.csv", "w", encoding="utf-8", newline="") as f: writer = csv.writer(f) # 按需写入CSV表头 writer.writerow(["json_content"]) for blob in blobs: # 直接读取对象内容到内存,无本地磁盘写入 json_content = blob.download_as_text() writer.writerow([json_content])可以将单线程遍历改为多协程/多进程模式,并发数调整到30~50(GCS单用户默认每秒操作上限为1000,完全满足需求),处理效率可提升数十倍。
将任务迁移到GCP同区域计算资源运行
本地公网传输是最大的性能瓶颈,直接开一台与存储桶同区域的GCE虚拟机(最低配标准型即可),或者使用Cloud Run等无服务资源运行处理任务,同区域内网拉取GCS数据的带宽可达10Gbps以上,延迟仅几毫秒,比公网传输效率高几十倍。处理完成后仅需要传输最终生成的13GB左右CSV文件到本地即可,传输成本极低。使用更高效率的命令行工具替代原生gsutil
如果不想自行编写代码,可使用谷歌新一代GCS命令行工具gcloud storage替代gsutil,该工具针对小文件批量传输做了深度优化,同环境下速度是gsutil的3~5倍。也可以直接通过并行cat命令直接拼接内容到CSV,无需落地文件:gsutil ls gs://<bucket>/<folder>/*.json | xargs -n 1 -P 50 gsutil cat >> output.csv上述命令会启动50个并行进程拉取对象内容,直接追加到output.csv文件中。
利用GCP原生服务做无代码批量处理
可以直接将GCS桶内的JSON文件批量导入到BigQuery表,再通过BigQuery的导出功能直接生成CSV文件,全程无需自行开发、运维任务,GCP内部处理650万条数据通常仅需1~2小时,导出的CSV可以直接拉取到本地。
注意:如果JSON内容本身包含换行符、逗号等CSV特殊字符,建议通过SDK处理时做好转义,避免生成的CSV格式错乱。
内容的提问来源于stack exchange,提问作者Kevin Danikowski

