每日S3文件同步至Redshift时最后一个文件未加载的时区相关问题排查及修复方案咨询
每日S3文件同步至Redshift时最后一个文件未加载的时区相关问题排查及修复方案咨询
碰到这种因时区导致的文件漏加载问题确实挺头疼的,我帮你梳理下代码里的潜在问题,再给出具体的排查和修复思路:
先定位核心问题方向
从你提供的代码和描述来看,大概率是时区不统一导致文件筛选逻辑出错,或者S3文件路径前缀与代码生成的前缀不匹配,最终漏选了最后一个文件。咱们一步步拆解:
排查步骤先做起来
核对S3文件路径与代码生成的前缀
找到那个未加载的文件,看看它在S3的存储路径是不是和代码里非backfill模式生成的prefix一致(代码里是context/folder/LA时区日期)。如果文件在另一个日期的路径下,那就是前缀生成逻辑出问题了。检查文件的LastModified时间
S3文件的LastModified默认是UTC时区,把这个时间转换成你业务用的America/Los_Angeles时区,看看是否属于Airflow运行日期对应的LA日期范围。比如Airflow的ds是UTC日期2024-05-21,转成LA可能是2024-05-20,那文件的LA时间是否落在2024-05-20当天?加日志验证关键变量
在代码里多打几个关键日志:- 打印
cloud_redshift_sync里的airflow_run_date(原始UTC日期)和date_airflow(转换后的LA日期) - 在
get_file_from_s3里打印每个文件的LastModified(UTC)以及转成LA时区后的时间 - 打印最终筛选出来的文件列表,确认是否包含了那个未加载的文件
- 打印
针对性修复方案
1. 统一时区处理,修复文件筛选逻辑
你代码里get_file_from_s3的非backfill分支,原本的时间范围判断被注释掉了,而且即使恢复,也存在时区不统一的问题(S3的LastModified是UTC,代码里的ds是LA时区)。修改后的代码如下:
def get_file_from_s3(s3_client, raw_bucket, folder, ds, backfill, backfill_start, backfill_end): print("Inside get_file_from_s3 function") files = [] backfill_start = datetime.strptime(backfill_start, "%Y-%m-%d").replace(tzinfo=pytz.utc) backfill_end = datetime.strptime(backfill_end, "%Y-%m-%d").replace(tzinfo=pytz.utc) objects=get_all_s3_objects(s3_client, Bucket=raw_bucket, Prefix=folder) if (backfill).lower() == "true": print(f"Backfill mode enabled from {str(backfill_start)} to {str(backfill_end)}") for obj in objects: print(f"Checking object {obj['Key']} with LastModified (UTC) {str(obj['LastModified'])}") if obj['LastModified'] < backfill_end and obj['LastModified'] >= backfill_start: print(f"Adding {obj['Key']} to files for backfill") filename = obj['Key'] print(f"File added for backfill: {filename}") files.append(filename) return files else: print(f"Single day mode enabled for LA date {str(ds)}") # 把LA时区的ds转成UTC,和S3的LastModified统一时区再比较 ds_utc = ds.astimezone(pytz.utc) ds_next_utc = ds_utc + timedelta(days=1) print(f"UTC time range: {ds_utc} to {ds_next_utc}") for obj in objects: obj_last_modified_utc = obj['LastModified'] # 转成LA时区方便日志排查 obj_last_modified_la = obj_last_modified_utc.astimezone(pytz.timezone('America/Los_Angeles')) print(f"Checking object {obj['Key']}: LastModified (UTC) {obj_last_modified_utc}, (LA) {obj_last_modified_la}") if obj_last_modified_utc < ds_next_utc and obj_last_modified_utc >= ds_utc: filename = obj['Key'] print(f"Adding {obj['Key']} to files for single day") files.append(filename) print(f"Final selected files: {files}") return files
2. 确保prefix生成逻辑与S3存储规则匹配
- 如果你的S3文件是按UTC日期路径存储的,那代码里的
date_airflow不需要转LA时区,直接用原始的airflow_run_date就行:# 替换原date_airflow生成代码 date_airflow = airflow_run_date - 如果S3确实是按LA日期路径存储的,那当前的prefix生成逻辑没问题,但要确保文件筛选逻辑和路径规则对应。
3. 排查Redshift加载环节的时区问题
如果文件已经被正确筛选到,但Redshift没存储数据,还要检查:
- Redshift表的时区设置是否和数据中的时间字段一致
- 加载脚本有没有对时间字段做错误的时区转换,导致数据被过滤或插入失败
备注:内容来源于stack exchange,提问作者devia
相关产品推荐
相关产品推荐

