savepoints

本文深入探讨了Flink中的保存点和检查点机制,解析了它们在任务恢复、状态保存及作业变更中的作用。保存点适用于计划性备份和恢复,而检查点则用于意外故障恢复,两者在实现上虽有相似之处,但在使用场景和控制上有显著区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是保存点?保存点和检查点的区别在哪
保存点是数据流的执行状态(一致的?),是通过检查点机制创建的。利用保存点可以停止和恢复,fork,或者更新任务。保存点由两部分组成:一个可靠存储上的文件路径(例如 hdfs,s3.。。),里面保存了二进制文件(通常比较大),还有一个元数据文件(相对小一些)。
可靠存储中的文件保存了job运行状态镜像的网络数据。保存点的元数据文件包括了(主要)可靠存储中全部文件的绝对路径。
注意:为了实现升级程序和flink版本,请查看下面的分配算子id这一节.
从概念上看,保存点与检查点的不同类似与传统数据库的备份和恢复日志的不同。检查点
最主要的目的是任务发生意外失败时可以提供恢复机制。flink管理检查点的生命周期,例如.
一个检查点的创建,生效,释放全部由flink控制,不需要用户参与。
作为一个周期性触发的恢复方法,检查点的实现需要满足两个主要的目标:
1)轻量的创建过程
2)尽可能快速的恢复过程
实现这些目标的优化可以利用某些属性,例如,job代码在多次执行期间不会变化。
任务被用户终止后,检查点通常被丢弃(除非显示的配置保留的检查点).
对比之下,保存点创建、生效、删除都是由用户控制。它们被用来计划性的手工备份和恢复。
例如,升级flink版本,改变作业流图,改变并行数,fork另个任务就像红蓝部署,等等。
当然,保存点必须在任务被终止之前执行。
从概念上,保存点允许创建、恢复、可移植性、支持前面提到的job变更上花费更高昂的代价。
抛开概念上的区别,当前的检查点和保存点实现基本上使用相同的代码并产生相同的输出内容。
尽管现在已经存在一个例外,后续还会介绍更多的区别。
这个例外是指增量检查点,基于RocksDB的状态存储.使用一些RocksDB的内部格式替代原生的flink savepoint格式。
相对于保存点,这是第一个实现更轻量检查点的机制。
分配算子id
本节描述了非常推荐的程序调整方式,已实现未来程序的升级更新。最主要的改变是通过uid方法手动指定算子id.
生成的id用来划分每个算子的状态。
DataStream stream = env.
// Stateful source (e.g. Kafka) with ID
.addSource(new StatefulSource())
.uid(“source-id”) // ID for the source operator
.shuffle()
// Stateful mapper with ID
.map(new StatefulMapper())
.uid(“mapper-id”) // ID for the mapper
// Stateless printing sink
.print(); // Auto-generated ID

如果不手工指定id,系统自动生成id。算子id不发生变化,保存点可以自动恢复算子状态。
自动生成的ID取决于程序的结构并且受程序改变的影响。因此推荐手工指定id。
保存点状态
保存点可以被认为是一个map表,每个有状态算子有一条从算子id到算子状态的记录
Operator ID | State
------------±-----------------------
source-id | State of StatefulSource
mapper-id | State of StatefulMapper
上面的例子里,输出算子是无状态算子,因此不在保存点状态中。
默认的,系统试着匹配保存点中的每条记录到新的程序中。

操作
在命令行可以触发保存点,执行保存点并退出,从保存点恢复,销毁保存点。
flink 1.2.0以上支持在webui里恢复保存点。

触发保存点
触发保存点时,新建一个保存点元数据文件的路径。可以通过修改默认目标路径或者通过命令行自定义目标路径。(查看targetDirectory参数)
注意:目标路径需要能同时被JobManager和TaskManager访问。例如使用分布式文件系统。

文件存储系统和RocksDB存储系统
#Savepoint target directory
/savepoints/

#Savepoint directory
/savepoints/savepoint-:shortjobid-:savepointid/

#Savepoint file contains the checkpoint meta data
/savepoints/savepoint-:shortjobid-:savepointid/_metadata

#Savepoint state
/savepoints/savepoint-:shortjobid-:savepointid/…

注意:尽管看似可以移动检查点,但当前并不支持,因为元数据中保存了文件的绝对路径。
请跟随FLINK-5778处理这个限制。

注意,当你使用内存MemoryStateBackend时,元数据和保存点状态同时被保存在元数据文件。
由于整个检查点是一个完整的整体,可以移动文件并保存在任意位置。

注意:避免移动或删除正在运行的job的最后保存点,因为这可能影响失败恢复。
保存点对精确一次的sink有副作用,因此为了确保精确一次的语义,如果保存点后没有检查点,保存点会被用作恢复。

触发保存点
$ bin/flink savepoint :jobId [:targetDirectory]
为指定jobid的任务触发保存点,返回创建的保存点路径。恢复任务或丢弃保存点时需要提供路径。

基于YARN触发保存点
$ bin/flink savepoint :jobId [:targetDirectory] -yid :yarnAppId
为指定jobid的任务和YARNId的应用触发保存点,返回创建的保存点路径。

取消任务并创建保存点
$ bin/flink cancel -s [:targetDirectory] :jobId
为指定jobid的任务触发保存点,然后取消任务。同时可以指定目标文件路径用来保存检查点。
JobManager和TaskManager能访问路径。

从保存点恢复
$ bin/flink run -s :savepointPath [:runArgs]
此操作提交一个从保存点恢复的job.指定元数据文件或保存点路径

允许未恢复状态
默认情况下恢复操作会把保存点状态全部匹配到程序算子。
如果删除了算子,允许跳过没有匹配新程序的状态。通过制定可选参数
–allowNonRestoredState(简化为-n)
$ bin/flink run -s :savepointPath -n [:runArgs]

丢弃保存点
$ bin/flink savepoint -d :savepointPath
丢弃路径对应的保存点
注意,通过文件系统直接删除保存点并不影响其它保存点或检查点(记得每个保存点时独立保存的)。

配置
通过state.savepoints.dir配置默认的保存点路径。
触发保存点时,路径被用来保存保存点。通过触发命令参数可以覆盖默认的目标路径。(查看:targetDirectory参数)
#Default savepoint target directory
state.savepoints.dir: hdfs:///flink/savepoints
未配置默认路径,命令也没有指定目标路径,触发保存点会失败。
注意:目标路径需要能被JobManager和TaskManager访问。

常见问题:
应该为任务里的每个算子分配id吗?
从经验来说,应该这样。严格的说,只需要通过uid方法为有状态算子分配id就足够了。
保存点只保存有状态算子的状态,无状态算子与保存点无关。
从实践的角度来看,推荐为所有算子分配id,因为一些内置算子例如winodw算子也存有状态,但是这些内置算子没有明显的区分出实际是否保存有状态。
如果确认一个算子完全无状态,那可以跳过uid方法。

向作业流图新增一个有状态的算子,会有哪些影响?
当添加一个新算子到作业时,算子初始化后不会有任何状态。保存点里面保存了每个有状态算子的状态。无状态算子不包含在保存点中。
新算子的行为与无状态算子是一致的。

从作业流图中删除一个有状态的算子,会有哪些影响?
默认,一个保存点恢复时会尝试将全部状态对应到恢复任务。如果恢复检查点中的状态对应的算子被删除,那么恢复因此失败。

可以设置命令参数允许状态不全部恢复 --allowNonRestoredState (简化:-n):
$ bin/flink run -s :savepointPath -n [:runArgs]

调整了作业流图中的有状态算子的顺序,会有哪些影响?
如果有状态的算子配置了ID,那么他们会正常恢复。
如果没有分配ID,在调整顺序后,有状态算子自动生成的ID很大几率会变化。这会导致你不能使用之前的保存点恢复它们的状态。

在作业流图上新增、删除或者调整无状态算子,会有哪些影响?
如果有状态的算子配置了ID,那么他们会正常恢复。
如果没有分配ID,在调整顺序后,有状态算子自动生成的ID很大几率会变化。这会导致你不能使用之前的保存点恢复它们的状态。

恢复状态时调整了并行数,会有哪些影响?
如果保存点是基于flink 1.2.0版本或以后,并且没使用弃用状态的api例如Checkpointed,你可以在恢复检查点同时指定新的并行数。
如果恢复的保存点是基于flink1.2.0版本以下或使用弃用状态的api,那么首先需要把任务和检查点迁移到flink1.2.0版本或之上,才能修改并行数。

可以将保存点文件移开稳定的存储吗?
最直接的回答是“否”,这是因为,由于技术上的原因元数据引用了保存在稳定存储的数据文件的绝对路径。
更详细的回答是:如果你由于某些原因必须移动这些文件,那么有两个方法可以作为解决方案。
第一个方法,简单但相对来说风险比较高,使用文件编辑器修改元数据文件中的路径为新文件路径。
另一个方法,使用SavepointV2Serializer类,用新路径以编程方式读取、操作和重写元数据文件。

<think>好的,我现在要处理用户关于SQLite中保存点(Savepoints)的查询。首先,我需要确认用户的需求是什么。用户之前询问了IMMEDIATE和EXCLUSIVE事务模式,现在转而问保存点,可能是在深入学习SQLite的事务控制机制。保存点允许在事务中设置标记点,以便部分回滚,这对复杂事务处理很有用。 首先,我得回顾保存点的基本概念。保存点允许在事务中创建多个检查点,用户可以在不提交或回滚整个事务的情况下,回滚到某个特定的点。这有助于处理错误恢复或部分操作撤销的情况,而不影响整个事务的其他部分。 接下来,需要解释保存点的工作机制。比如,使用SAVEPOINT语句创建保存点,ROLLBACK TO回滚到特定点,RELEASE SAVEPOINT释放保存点。同时,要强调保存点和普通事务的区别,比如保存点不需要BEGIN,可以在事务内多次设置,而普通事务只能有一个BEGIN和COMMIT/ROLLBACK。 然后,应该举例说明如何使用保存点。例如,在一个事务中进行多个操作,每个操作后设置保存点,如果某一步失败,回滚到上一个保存点,而不是整个事务。这能提高灵活性和效率。 还需要讨论适用场景,比如批量处理中的部分失败处理,复杂业务逻辑中的条件回滚,以及嵌套事务的模拟。用户可能关心的是如何在实际应用中使用保存点,所以具体的例子和场景会很有帮助。 另外,要注意保存点的嵌套和释放机制。保存点可以嵌套,但释放父保存点会同时释放子保存点。这一点需要明确说明,避免用户在使用时出现意料之外的问题。 最后,总结保存点的优势,比如提高事务的灵活性,减少全量回滚的开销,以及增强错误处理能力。同时,提醒用户正确使用保存点,避免资源泄漏,比如及时释放不再需要的保存点。 在组织回答时,要保持结构清晰,分点说明,使用代码示例和对比表格来增强可读性。确保语言简洁,符合用户要求的中文回答,并遵循之前的格式,比如使用加粗标题和代码块。同时,检查是否有遗漏的关键点,比如保存点的自动释放机制和与普通事务的交互。</think>以下是关于 SQLite 中 **保存点(Savepoints)** 的详细解释: --- ### **核心概念** **保存点(Savepoint)** 是 SQLite 中一种细粒度的事务控制机制,允许在事务中标记特定节点,并**选择性回滚到某个节点**,而无需提交或回滚整个事务。 - **核心价值**:提供更灵活的**部分回滚**能力,适用于复杂事务中需要分段控制的场景。 --- ### **1. 保存点 vs 普通事务** | 特性 | 普通事务 (`BEGIN/COMMIT/ROLLBACK`) | 保存点 (`SAVEPOINT/RELEASE/ROLLBACK TO`) | |---------------------|------------------------------------------|-------------------------------------------| | **作用范围** | 整个事务 | 事务内的子操作段 | | **回滚粒度** | 只能回滚全部操作 | 可回滚到指定保存点 | | **嵌套支持** | 不支持 | 支持多层嵌套 | | **资源占用** | 需显式提交或回滚 | 可逐步释放保存点 | --- ### **2. 保存点的基本操作** #### **(1)创建保存点** ```sql SAVEPOINT savepoint_name; -- 标记当前事务状态 ``` #### **(2)回滚到保存点** ```sql ROLLBACK TO savepoint_name; -- 回滚到指定保存点,后续操作仍可继续 ``` #### **(3)释放保存点** ```sql RELEASE SAVEPOINT savepoint_name; -- 删除保存点(不影响已提交的操作) ``` --- ### **3. 保存点的工作机制** 1. **事务内嵌套**: - 保存点可多层嵌套(例如 `SAVEPOINT A` → `SAVEPOINT B`)。 - 回滚到父保存点(如 `ROLLBACK TO A`)会**自动释放所有子保存点**(如 `B`)。 2. **回滚范围**: - `ROLLBACK TO` 仅撤销从保存点到当前状态之间的操作,**保留保存点之前的操作**。 - 事务仍处于活跃状态,可继续执行其他操作。 3. **自动释放**: - 若未显式释放保存点,事务提交或回滚时会**自动释放所有保存点**。 --- ### **4. 示例场景** #### **场景** 批量插入数据,若某一步失败,仅回滚到最近的有效保存点。 ```sql BEGIN TRANSACTION; -- 步骤1:插入数据A INSERT INTO table (id, data) VALUES (1, 'A'); SAVEPOINT sp1; -- 标记保存点 -- 步骤2:插入数据B(假设此处可能失败) INSERT INTO table (id, data) VALUES (2, 'B'); SAVEPOINT sp2; -- 步骤3:插入数据C(失败时回滚到sp2) INSERT INTO table (id, data) VALUES (3, 'C'); -- 假设步骤3失败 ROLLBACK TO sp2; -- 回滚到步骤2之后的状态(数据A和B保留) -- 继续其他操作... COMMIT; ``` #### **结果** - 数据A和B被保留,数据C被回滚。 - 事务最终提交时仅包含A和B。 --- ### **5. 适用场景** 1. **批量操作中的部分失败处理**: - 例如分批导入数据时,某批数据出错,回滚到上一批次。 2. **复杂业务逻辑的条件回滚**: - 根据业务规则选择性回滚部分操作(如库存扣减失败时仅回滚订单子步骤)。 3. **模拟嵌套事务**: - 通过多层保存点实现类似“子事务”的效果。 --- ### **6. 注意事项** 1. **保存点与锁**: - 保存点本身不改变事务的锁模式(如 `IMMEDIATE` 或 `DEFERRED`)。 2. **资源管理**: - 避免过多未释放的保存点占用内存。 3. **错误处理**: - 回滚到保存点后,需重新处理后续逻辑,避免重复错误。 --- ### **总结** **保存点**通过细粒度的回滚控制,提升了事务的灵活性和容错能力,尤其适用于需要分段提交或部分回滚的复杂业务场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值