【发布时间】:2020-12-13 14:38:30
【问题描述】:
我正在尝试使用 Airflow 将数据摄取到 Redshift。我的源数据库中有许多表,我已经用 Python 编写了模块,这些模块在 Redshift 中执行端到端 ETL。我打算使用 Airflow 来协调它们的执行,其中每个表的 ETL 将是 DAG 中的一项任务。他们主要担心的是我想避免为我的每个表建立与 Redshift 的连接。相反,我想在开始时建立一次连接,并希望为我的每个下游任务重新使用该连接。 我尝试使用 xcom,但似乎连接对象不是可腌制的,因此不起作用(“连接”被腌制的概念也没有多大意义)。我也尝试如下使用全局变量,但似乎它不起作用,因为它显然为每个任务实例化了一个新对象:
redcon = None
red_iam_role = None
dag = DAG('redshift_etl', description='An example redshift etl prototype', schedule_interval='0 12 * * *', start_date=datetime(2017, 3, 20), catchup=False)
def connect_to_redshift():
global redcon, red_iam_role
if redcon is None or red_iam_role is None:
(redcon, red_iam_role) = redshift_utilities.get_connection('redshift_cluster', 15) #a module that returns a tuple consisting of redshift connection object (using psycopg2) and redshift_iam_role which I use for a few tasks.
return {"connection": redcon, "iam_role": red_iam_role}
else:
return {"connection": redcon, "iam_role": red_iam_role}
def first_task(redshift_params,**context):
print(redshift_params["connection"])
def second_task(redshift_params,**context):
print(redshift_params["connection"])
first_task_dag = PythonOperator(task_id='first_task',provide_context=True,op_kwargs={"redshift_params":connect_to_redshift()}, python_callable=first_task, dag=dag)
second_task_dag = PythonOperator(task_id='second_task',provide_context=True,op_kwargs={"redshift_params":connect_to_redshift()}, python_callable=second_task, dag=dag)
first_task_dag >> second_task_dag
有什么方法可以实现吗?我不想在 Airflow 中设置连接(例如 JdbcHook)并在这种情况下使用它。
【问题讨论】:
-
您为什么关心重用相同的连接?你想在不同的任务中使用临时表吗?
-
由于像 Redshift 这样的 MPP 系统通常对同时连接的数量有限制,并且每个连接都有成本因素(例如会话建立、资源分配、消息交换),因此通常认为建立连接到此类系统一次,然后重复使用该系统完成所有操作。
-
您可以使用池(一种气流功能)来限制并发,并确保在操作员设计中关闭连接。除此之外,我认为你只需要让你的任务“更大”,并在一个任务中做更多的事情,具有相同的联系,如果这对你很重要的话。