我有一个用Python编写的Lambda函数,该函数具有为来自AWS S3中3个文件的3个表运行Redshift复制命令的代码。
示例:
我有表A,B和C。
The python code contains:
'copy to redshift A from "s3://bucket/abc/A.csv"'
'copy to redshift B from "s3://bucket/abc/B.csv"'
'copy to redshift C from "s3://bucket/abc/C.csv"'
只要这三个文件中的新文件到达S3中的“ s3:// bucket / abc /” 位置,就会触发此代码。因此,即使只有一个csv文件到达,它也会加载所有三个表。
最佳方案:将代码分解为三个不同的Lambda函数,并将其直接映射到每个更新/上传的源文件。
但是,我的要求是继续执行一个Lambda代码,它将仅对那些已更新的csv文件选择性地运行一部分(使用if)。
示例:
if (new csv file for A has arrived):
'copy to redshift A from "s3://bucket/abc/A.csv"'
if (new csv file for B has arrived):
'copy to redshift B from "s3://bucket/abc/B.csv"'
if (new csv file for C has arrived):
'copy to redshift C from "s3://bucket/abc/C.csv"'
当前,要实现此目的,我将这些文件的元数据(LastModified)存储在python dict中,并且文件名是关键。打印字典将是这样的:
{'bucket/abc/A.csv': '2019-04-17 11:14:11+00:00', 'bucket/abc/B.csv': '2019-04-18 12:55:47+00:00', 'bucket/abc/C.csv': '2019-04-17 11:09:55+00:00'}
然后,只要新文件出现在三个文件中的任何一个中,就会触发Lambda,我正在阅读字典,并将每个文件的时间与字典中的相应值进行比较,如果新的LastModified增加了,我正在运行该表的复制命令。
所有这些,因为无法解决这种用例的S3事件/ CloudWatch。
如果不能很好地说明问题,请提出进一步的问题。
答案 0 :(得分:2)
当Amazon S3事件触发AWS Lambda函数时,它提供存储桶名称和对象密钥,作为event
的一部分:
def lambda_handler(event, context):
# Get the bucket and object key from the Event
bucket = event['Records'][0]['s3']['bucket']['name']
key = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'])
当对象详细信息作为列表传递时,我怀疑每个事件仅提供了一个对象(因此使用[0]
)。但是,我不是100%肯定会一直如此。除非另有证明,否则最好假设一下。
因此,如果您的代码需要特定的对象,则您的代码将是:
if key == 'abc/A.csv':
'copy to Table-A from "s3://bucket/abc/A.csv"'
if key == 'abc/B.csv':
'copy to Table-B from "s3://bucket/abc/B.csv"'
if key == 'abc/C.csv':
'copy to Table-C from "s3://bucket/abc/C.csv"'
无需存储LastModified
,因为每当上传新文件时都会触发该事件。另外,请注意将数据存储在全局字典中,并希望在将来的执行中将其保留-并非总是如此。如果Lambda容器在一段时间内未运行,则可以将其删除;如果并发执行,则可能会创建其他Lambda容器。
如果您始终希望获得3个文件,并且总是按一定顺序上传 ,那么您可以使用第3个文件的上传触发该过程,然后将其复制全部3个文件都移至Redshift。