大数据Iceberg的branch和tags数据管理详解
在大数据领域摸爬滚打,相信大家都遇到过数据版本管理的难题。今天,咱们就来深入了解一下Apache Iceberg的两个强大功能——branch(分支)和tags(标签),搞清楚它们到底怎么用,能给我们的工作带来哪些便利。
一、Iceberg引入branch和tags的背景
在大数据场景下,数据版本管理就像一场攻坚战,面临着诸多挑战。在Iceberg还没有branch和tags功能的时候,问题可不少。
(一)数据版本管理困境
一方面,追踪数据变更历史困难重重。Iceberg通过快照记录数据表在特定时间点的状态,可快照ID是系统自动生成的,又长又没规律,很难让人记住每个ID对应的具体数据状态。就好比你存了一堆照片,每张照片都只有编号,没有名字和备注,想要找到特定时期的照片,简直大海捞针,根本弄不清数据是怎么一步步变化的。
另一方面,管理数据版本也麻烦得很。在数据湖保存不同时间点的数据版本,对数据分析和恢复至关重要。但没有branch和tags,只能靠快照ID区分版本,随着数据不断更新,快照ID越来越多,管理起来杂乱无章,想找某个特定版本的数据,真不是一般的费劲。
(二)数据隔离难题
在机器学习和数据分析工作中,经常要对数据做各种实验,尝试不同的数据处理方法、训练不同模型。要是没有branch功能,实验操作很容易直接影响主数据表。想象一下,数据科学家在主表插入实验数据,结果生产环境的数据分析结果全乱套了,根本没法用。
而且,开发人员做数据开发和测试时,也会受到很大限制。没有branch,只能在主表操作,一不小心就可能导致数据错误或丢失,影响生产环境的稳定。要是不想影响主表,就得专门构建测试表,这无疑增加了不少工作量。
为了解决这些问题,Iceberg引入了类Git的分支/标签机制,把代码管理的成熟理念运用到数据湖管理中,让我们能实现ACID事务、隔离实验、精准回溯,给数据管理带来了新的转机。
二、Iceberg的branch和tags详解
(一)tags的使用方法
Iceberg的tag实现逻辑和Git tag很相似。它就像是给某个特定的快照贴上了一个独一无二的“小标签”,指向特定的快照ID,方便我们快速定位和使用这个版本的数据。
- 创建标签:假设我们有个“employee”表,里面存着截至6月份的数据,现在想用这个版本的数据训练机器学习模型。就可以用下面的代码创建一个标签:
spark.sql("ALTER TABLE employee CREATE TAG EOM_Jun_2023")
执行完这条语句,Iceberg就会给当前版本的表创建一个叫EOM_Jun_2023的引用。之后表再有什么数据更新,都不会影响这个标签对应的版本。不过要注意,Iceberg的快照是会过期的,快照没了,tag也就跟着没了。所以创建tag的时候,最好设置一下保留时间,比如保留30天,可以这样写:
spark.sql("ALTER TABLE employee CREATE TAG EOM_June_2023 RETAIN 30DAYS ")
- tag使用示例:先往“employee”表插入一些数据:
spark.sql("INSERT INTO employees values (1, 'Harry', 'Software Engineer', 25000), (2, 'John', 'Marketing Ops', 17000)")
然后给这版数据打个保留10天的tag:
spark.sql("ALTER TABLE employees CREATE TAG june_data RETAIN 10 DAYS")
接着再插入新数据。这时候,如果想查看打tag时的数据版本,用下面的代码就能实现:
spark.sql("SELECT * FROM glue.test.employees VERSION AS OF 'june_data'").toPandas()
这样就能准确获取到打tag那个时间点的表数据了。
(二)branch的使用方法
Iceberg的branch和Git的分支原理类似,能让我们在不影响主数据的情况下,进行独立的数据操作和实验。
- 创建branch:比如要创建一个名为ML_exp的branch,可以执行下面的代码:
spark.sql("ALTER TABLE employee CREATE BRANCH ML_exp")
这就相当于在主数据的基础上,开辟了一个新的“实验场地”。
2. branch使用示例:创建好ML_exp分支后,我们可以往里面写入数据。先获取表的结构,准备好要插入的数据:
schema = spark.table("glue.test.employees").schema data = [ (6, "Troy", "CMO", 30000.0), (7, "Raine", "UX", 21000.0), (8, "Harry", "QA", 22000.0) ] df = spark.createDataFrame(data, schema)
然后把数据写入ML_exp分支:
df.write.format("iceberg").mode("append").save("employees.branch_ML_exp") //df.write.format("iceberg").option("branch", "ML_exp").mode("append").save("employees")
写完数据后,查看ML_exp分支的数据:
spark.sql("SELECT * FROM employees VERSION AS OF 'ML_exp'").toPandas()
可以看到,新插入的数据和分支创建时已有的数据都在里面。而查询原始表数据时会发现,原始表的数据并没有因为在分支上的操作而改变,依然保持完整。如果这个分支不再需要了,还能删除:
spark.sql("ALTER TABLE employees DROP BRANCH ML_exp")
(三)使用注意事项
Iceberg支持在单个表上进行分支和tag操作。要是项目中需要实现多表分支和tag,还想保证操作的一致性,类似mysql事务那种“要么都成功,要么都失败”的效果,可以试试Nessie这个工具。
三、总结
通过上面的介绍,相信大家对Iceberg的branch和tags功能有了更深入的理解。从创建、使用到管理,它们为我们管理数据版本、进行数据实验和开发测试提供了极大的便利。而Nessie在多表管理场景下也有独特的优势,大家可以根据实际需求选择使用。希望这些知识能在大家的数据管理工作中派上用场,有问题欢迎留言哦。