Python AWS Lambda批写入DynamoDB的执行速度较慢,且具有多个线程 免责声明:我知道这个问题会惹恼一些人,因为它是模糊的,理论性的,并且几乎没有代码。

Python AWS Lambda批写入DynamoDB的执行速度较慢,且具有多个线程 免责声明:我知道这个问题会惹恼一些人,因为它是模糊的,理论性的,并且几乎没有代码。,python,multithreading,amazon-web-services,amazon-dynamodb,aws-lambda,Python,Multithreading,Amazon Web Services,Amazon Dynamodb,Aws Lambda,我在Python中有一个AWS Lambda函数,它从S3读取一个非规范化记录文件,正确格式化其内容,然后通过批写将其上传到DynamoDB。这一切都像广告宣传的那样有效。然后,我尝试将这个管道的上传部分分解成线程,希望更有效地利用DynamoDBs的写容量。但是,多线程版本的速度要慢50%左右。由于代码很长,我加入了伪代码 NUM_THREADS = 4 for every line in the file: Add line to list of lines if we've r

我在Python中有一个AWS Lambda函数,它从S3读取一个非规范化记录文件,正确格式化其内容,然后通过批写将其上传到DynamoDB。这一切都像广告宣传的那样有效。然后,我尝试将这个管道的上传部分分解成线程,希望更有效地利用DynamoDBs的写容量。但是,多线程版本的速度要慢50%左右。由于代码很长,我加入了伪代码

NUM_THREADS = 4
for every line in the file:
   Add line to list of lines
   if we've read enough lines for a single thread:
       Create thread that uploads list of lines
       thread.start()
       clear list of lines.

for every thread started:
    thread.join()
到目前为止我检查过的问题的重要注意事项和可能来源:
  • 使用DynamoDB Local在本地测试时,线程确实会使我的程序运行得更快
  • 相反,如果我只使用一个线程,或者即使我使用多个线程,但我在启动线程后立即加入线程(实际上是单线程),程序完成得更快。1线~30s,多线~45s
  • 我在线程之间没有共享内存,没有锁,等等
  • 我尝试为每个线程创建新的DynamoDB连接,并共享一个连接,但没有效果
  • 我已经证实,添加更多的线程并不会压倒DynamoDB的写容量,因为它会产生相同数量的批写请求,并且在整个执行过程中,我没有比单个线程更多的未处理项
  • 线程化应该可以提高执行时间,因为程序是网络绑定的,即使Python线程实际上并不在多个内核上运行
  • 我尝试先读取整个文件,然后生成所有线程,认为最好不要中断磁盘IO,但没有效果
  • 我尝试了线程库和进程库

我知道这个问题是非常理论化的,所以可能很难找到问题的根源,但是有没有我不知道的Lambda怪癖?我还有什么可以帮助诊断问题的吗?非常感谢您的帮助。

内特,您是否完全排除了Dynamodb端的问题?写入请求的总数可能相同,但对于多线程,每秒的请求数可能不同

控制台提供了一些有用的图表来显示您的写入(或批写入)是否受到限制。如果Lambda函数中没有正确的“后退,重试”逻辑,Lambda将不断尝试,问题会变得更糟

还有一件事,你(但我)可能已经很清楚了。我的印象是,batch_writes在容量规划方面为您节省了资金。(比如说,20次一批写200篇文章只需要10个写作单元。我可以发誓我在一次演讲中听到一个AWS的家伙提到过这一点,但这不是重点。)

事实上,批处理可以为您节省一些时间,但在经济上没有任何节约

最后一个想法:我敢打赌,Lambda处理时间比增加Dynamodb写入容量要便宜。如果您并不急于让Lambda完成,为什么不让它在单线程上运行呢


祝你好运

结果表明线程处理速度更快,但只有当文件达到某个文件大小时。我最初工作的文件大小约为1/2 MG。使用10mg文件,线程版本的速度提高了50%。仍然不确定为什么它不能处理较小的文件,也许它只是需要时间来做一个“烹饪”,你知道我的意思吗?计算机是喜怒无常的事物。

作为背景,我对python和dynamoDB以及使用python的多处理库有很好的经验。由于文件大小相当小,因此可能是进程的设置时间让您对性能感到困惑。如果还没有,请使用python多处理池,如果需要将任何数据传回主线程,请根据您的用例使用map或imap。在python中,使用池是运行多个进程最简单的方式。如果您需要应用程序以更快的速度运行,那么您可能希望研究使用golang并发,并且您可以始终将代码构建为二进制代码,以便在python中使用。干杯。

是的,我一直在通过CloudWatch检查它的行为,没有节流。我确实知道,它们的价格仍然与个人写作相同。我考虑过精简上传到S3的文件,直到只需要一个线程,这很可能是我所做的,但这应该是可能的,我想看看我是否可以修复它。也许还有另一个选择。不要将文件精简到S3,而是将它们加载到一个Kinesis流中。。。然后,通过将Lambda函数焊接到Kinesis流,可以调整一次有多少“事件”进入Lambda函数。