大数据处理框架:Flink:Flink状态与容错机制_第1页
大数据处理框架:Flink:Flink状态与容错机制_第2页
大数据处理框架:Flink:Flink状态与容错机制_第3页
大数据处理框架:Flink:Flink状态与容错机制_第4页
大数据处理框架:Flink:Flink状态与容错机制_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

大数据处理框架:Flink:Flink状态与容错机制1大数据处理框架:Flink:Flink状态与容错机制1.1Flink简介与核心概念1.1.1Flink的基本架构Flink是一个用于处理无界和有界数据流的开源流处理框架。它提供了低延迟、高吞吐量和强大的状态管理能力,使其成为实时数据处理的理想选择。Flink的核心组件包括:FlinkCluster:由多个节点组成,用于执行并行数据流处理任务。JobManager:负责任务的调度和协调,管理TaskManager和作业的生命周期。TaskManager:执行实际的数据处理任务,提供计算资源和状态后端。CheckpointCoordinator:负责容错机制,协调检查点和恢复操作。1.1.2流处理与批处理Flink支持两种主要的数据处理模式:流处理和批处理。流处理允许Flink处理连续的、无界的数据流,而批处理则用于处理有限的、有界的数据集。这两种模式在Flink中是统一的,意味着相同的API和编程模型可以用于处理流和批数据,提供了极大的灵活性。示例:流处理与批处理的代码示例#流处理示例

frompyflink.datastreamimportStreamExecutionEnvironment

env=StreamExecutionEnvironment.get_execution_environment()

#从Socket读取数据流

data_stream=env.socket_text_stream('localhost',9999)

#批处理示例

frompyflink.datasetimportExecutionEnvironment

env=ExecutionEnvironment.get_execution_environment()

#从文件读取数据集

data_set=env.read_text('input.txt')1.1.3状态在Flink中的重要性状态管理是Flink的核心特性之一,它允许Flink处理程序在处理数据流时保持中间结果,从而实现复杂的数据流操作,如窗口聚合、状态更新和事件时间处理。状态可以是键控状态或操作符状态,分别用于基于键的数据处理和整个操作符的状态管理。示例:使用状态进行窗口聚合frompyflink.datastreamimportStreamExecutionEnvironment,TimeCharacteristic

frompyflink.datastream.stateimportValueStateDescriptor

frompyflink.datastream.windowimportTumblingEventTimeWindows

env=StreamExecutionEnvironment.get_execution_environment()

env.set_stream_time_characteristic(TimeCharacteristic.EventTime)

#从Socket读取数据流

data_stream=env.socket_text_stream('localhost',9999)

#定义窗口大小为5秒

windowed_stream=data_stream.key_by(lambdax:x[0]).window(TumblingEventTimeWindows.of(5000))

#在窗口内进行聚合操作

result=windowed_stream.reduce(lambdax,y:x+y)

#注册状态描述符

state_desc=ValueStateDescriptor('my-state',type_info=Types.INT())

#使用状态

defprocess_function(key,window,input,ctx,out):

state=ctx.get_state(state_desc)

#获取状态值

value=state.value()

#更新状态

state.update(value+1)

#输出结果

out.window_result(value)

result=windowed_cess(process_function)1.2Flink状态与容错机制1.2.1Checkpoint机制Checkpoint是Flink实现容错的关键机制。它定期保存所有操作符的状态快照,当系统发生故障时,可以从最近的Checkpoint恢复状态,从而保证数据处理的正确性和一致性。Checkpoint机制支持两种模式:Checkpoint和Savepoint。示例:配置Checkpointfrompyflink.datastreamimportStreamExecutionEnvironment

env=StreamExecutionEnvironment.get_execution_environment()

#设置Checkpoint间隔为5秒

env.enable_checkpointing(5000)

#设置Checkpoint模式为EXACTLY_ONCE

env.get_checkpoint_config().set_checkpointing_mode('EXACTLY_ONCE')

#设置Checkpoint超时时间为1分钟

env.get_checkpoint_config().set_checkpoint_timeout(60000)

#设置允许在故障恢复时有未完成的Checkpoint

env.get_checkpoint_config().enable_externalized_checkpoints(True)1.2.2Savepoint机制Savepoint是用户手动触发的Checkpoint,它可以在任何时间点保存状态,而不仅仅是定期的Checkpoint。Savepoint主要用于在升级或更改作业配置时,保存当前状态,以便在新的作业配置下恢复。示例:触发Savepoint#使用FlinkCLI触发Savepoint

./bin/flinksavepoint-d<job-id>-t<savepoint-dir>1.2.3状态后端状态后端是Flink用于存储状态的组件。Flink提供了多种状态后端,包括MemoryStateBackend、FsStateBackend和RocksDBStateBackend。选择合适的状态后端对于保证状态的持久性和性能至关重要。示例:配置状态后端frompyflink.datastreamimportStreamExecutionEnvironment

env=StreamExecutionEnvironment.get_execution_environment()

#使用RocksDB作为状态后端

env.set_state_backend('RocksDBStateBackend')

#设置状态后端的存储路径

env.get_checkpoint_config().setCheckpointStorage('hdfs://localhost:9000/checkpoints')1.2.4容错恢复当Flink检测到故障时,它会从最近的Checkpoint或Savepoint恢复状态。恢复过程包括重新启动失败的操作符实例,并从状态后端加载状态数据。示例:从Savepoint恢复作业#使用FlinkCLI从Savepoint恢复作业

./bin/flinkrun-s<savepoint-dir><job-jar>通过上述示例和解释,我们深入了解了Flink的状态管理和容错机制,包括流处理与批处理的区别、状态在Flink中的重要性、Checkpoint和Savepoint的配置与触发,以及状态后端的选择和容错恢复的过程。这些知识对于构建可靠、高效的大数据处理系统至关重要。2大数据处理框架:Flink状态管理与容错机制2.1Flink状态管理2.1.1状态的分类在ApacheFlink中,状态(State)是流处理和批处理任务中保存中间结果的关键机制。Flink支持两种类型的状态:OperatorState和KeyedState。OperatorStateOperatorState是与算子(Operator)关联的状态,它不依赖于数据流中的键。例如,一个算子可能需要维护一个计数器来跟踪处理了多少个元素,这种状态就是OperatorState。它适用于所有输入数据,而不仅仅是特定键的数据。KeyedStateKeyedState是与数据流中的键关联的状态。在Flink中,当数据流被键控(Keyed)时,每个键都有自己的状态,这种状态只与该键相关的数据有关。KeyedState非常适合处理需要按键分组的数据,例如,维护每个用户的状态信息。2.1.2状态后端详解Flink的状态后端(StateBackend)负责存储和管理状态。状态后端的选择对性能和容错能力有重大影响。Flink提供了几种状态后端:MemoryStateBackendMemoryStateBackend将状态存储在任务管理器(TaskManager)的内存中。这是最简单和最快的状态后端,但不提供持久化存储,因此在任务失败时,状态可能会丢失。FsStateBackendFsStateBackend将状态存储在文件系统中,如HDFS、S3或本地文件系统。它提供了持久化存储,即使在任务失败或机器故障时,状态也可以恢复。这是生产环境中最常用的状态后端。RocksDBStateBackendRocksDBStateBackend使用RocksDB作为状态存储引擎。它提供了高性能的持久化存储,适用于需要大量状态数据的场景。RocksDBStateBackend可以配置为将状态存储在磁盘上或使用内存作为缓存。2.1.3状态检查点机制Flink的检查点(Checkpoint)机制是其容错能力的核心。检查点允许Flink在任务失败时,从最近的检查点恢复状态,从而避免了从头开始处理数据。检查点原理检查点是通过将状态快照(Snapshot)保存到持久化存储中实现的。当Flink决定创建一个检查点时,它会向所有任务发送一个检查点屏障(CheckpointBarrier)。检查点屏障包含一个全局唯一的检查点ID。当一个任务接收到检查点屏障时,它会保存当前的状态到状态后端,并将状态快照的元数据发送到作业管理器(JobManager)。检查点配置Flink提供了多种配置选项来控制检查点的创建和恢复:checkpointInterval:设置检查点的间隔时间。checkpointTimeout:设置检查点的超时时间,如果在超时时间内检查点没有完成,Flink会放弃这个检查点。checkpointingMode:设置检查点的语义,可以是EXACTLY_ONCE或AT_LEAST_ONCE。代码示例下面是一个使用Flink的检查点机制的代码示例:importorg.apache.flink.streaming.api.CheckpointingMode;

importorg.apache.flink.streaming.api.datastream.DataStream;

importorg.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

publicclassCheckpointExample{

publicstaticvoidmain(String[]args)throwsException{

//创建流处理环境

finalStreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();

//设置检查点

env.enableCheckpointing(5000);//每5000毫秒创建一个检查点

env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);//设置检查点语义

env.getCheckpointConfig().setCheckpointTimeout(60000);//设置检查点超时时间为60000毫秒

//创建数据流

DataStream<String>text=env.socketTextStream("localhost",9999);

//进行处理

DataStream<String>result=text

.map(newTokenizer())

.keyBy(0)

.timeWindow(5000)

.reduce(newWordCountReducer());

//执行任务

env.execute("WordCountwithCheckpoints");

}

}在这个示例中,我们创建了一个流处理环境,并启用了检查点。我们设置了检查点的间隔时间为5000毫秒,检查点的语义为EXACTLY_ONCE,检查点的超时时间为60000毫秒。然后,我们创建了一个数据流,对数据进行了处理,并执行了任务。2.2总结Flink的状态管理机制和检查点机制是其流处理和批处理任务的核心。通过合理选择状态后端和配置检查点,可以确保Flink任务的高性能和高容错性。3容错机制与恢复策略3.1容错的重要性在大数据处理中,容错性是确保数据处理系统稳定性和可靠性的重要因素。ApacheFlink作为一款高性能的流处理和批处理框架,其容错机制设计得尤为精妙,能够有效应对各种故障,如节点失败、网络故障等,确保数据处理的正确性和一致性。3.2检查点与容错3.2.1原理Flink的检查点(Checkpoint)机制是其容错的核心。检查点通过定期保存应用程序的状态快照,使得在发生故障时,可以从最近的检查点恢复,从而避免从头开始处理数据,大大减少了恢复时间。3.2.2内容检查点触发:Flink的JobManager定期向所有TaskManager发送检查点屏障(CheckpointBarrier),屏障包含一个全局唯一的检查点ID。状态保存:当屏障到达TaskManager时,所有正在运行的任务会保存当前状态,并将状态快照发送到持久化存储(如HDFS)。确认与完成:状态保存完成后,TaskManager会向JobManager发送确认消息,当所有任务都确认后,检查点被视为成功。3.2.3示例代码//创建流执行环境

StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();

//设置检查点间隔为5秒

env.enableCheckpointing(5000);

//设置检查点模式为EXACTLY_ONCE

env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);

//设置检查点超时时间为60秒

env.getCheckpointConfig().setCheckpointTimeout(60000);

//设置检查点存储位置

env.setStateBackend(newFsStateBackend("hdfs://localhost:9000/flink/checkpoints"));3.3故障恢复流程3.3.1原理当Flink检测到故障时,它会从最近成功的检查点恢复状态。这一过程包括重新启动失败的任务,从持久化存储中加载状态快照,以及重新建立任务之间的依赖关系。3.3.2内容故障检测:Flink通过心跳机制监控任务的运行状态,一旦检测到任务失败,立即触发恢复流程。状态恢复:从最近的检查点加载状态,恢复任务的执行上下文。重新建立依赖:对于流处理任务,Flink会重新建立任务之间的数据流依赖,确保数据的正确处理顺序。3.3.3示例描述假设我们有一个简单的流处理任务,包括数据源(Source)、数据转换(Transform)和数据接收器(Sink)。如果在数据转换阶段发生故障,Flink会从最近的检查点恢复数据转换任务的状态,并重新建立与数据源和数据接收器的连接,继续处理数据。//定义数据源

DataStream<String>source=env.addSource(newMySourceFunction());

//定义数据转换

DataStream<String>transformed=source.map(newMyMapFunction());

//定义数据接收器

transformed.addSink(newMySinkFunction());

//执行任务

env.execute("MyFlinkJob");在上述代码中,如果MyMapFunction在执行过程中失败,Flink会自动从最近的检查点恢复其状态,然后重新开始执行MyMapFunction,确保数据处理的连续性和正确性。通过上述原理和示例的介绍,我们可以看到Flink的容错机制和检查点策略是如何确保大数据处理任务的稳定性和可靠性的。在实际应用中,合理配置检查点参数,选择合适的持久化存储,对于提高Flink应用的性能和容错能力至关重要。4高级状态与容错特性4.1状态一致性保证在ApacheFlink中,状态一致性是通过其强大的状态后端和检查点机制实现的。Flink提供了几种不同的状态一致性级别,包括EXACTLY_ONCE、AT_LEAST_ONCE和AT_MOST_ONCE。为了确保最高级别的状态一致性,即EXACTLY_ONCE,Flink使用了检查点和两阶段提交协议。4.1.1检查点机制检查点是Flink状态一致性保证的核心。它通过定期保存应用程序状态的快照来实现。当应用程序运行时,Flink会周期性地触发检查点,将所有操作符的状态以及它们之间的依赖关系保存到持久化存储中。这样,如果系统发生故障,可以从最近的检查点恢复,确保处理的精确一次语义。示例代码//创建StreamExecutionEnvironment

StreamExecutionEnvironmentenv=StreamExecutionEnvironment.getExecutionEnvironment();

//设置检查点间隔为5秒

env.enableCheckpointing(5000);

//设置检查点模式为EXACTLY_ONCE

env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);

//设置检查点超时时间为60秒

env.getCheckpointConfig().setCheckpointTimeout(60000);

//设置最小检查点间隔为500毫秒

env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500);

//允许检查点失败

env.getCheckpointConfig().enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);4.1.2两阶段提交协议Flink的两阶段提交协议(Two-PhaseCommitProtocol)用于处理有状态的流操作符和外部系统之间的交互,如数据库。这确保了在故障恢复时,流处理和外部系统之间的操作能够保持一致。4.2故障恢复的最佳实践在设计Flink应用程序时,确保故障恢复的效率和可靠性是至关重要的。以下是一些最佳实践:4.2.1使用状态后端Flink提供了多种状态后端,如FsStateBackend、RocksDBStateBackend和MemoryStateBackend。选择合适的状态后端对于优化性能和确保容错能力至关重要。示例代码//使用RocksDBStateBackend

RocksDBStateBackendrocksDBStateBackend=newRocksDBStateBackend(newPath("hdfs://localhost:9000/flink/checkpoints"),true);

env.setStateBackend(rocksDBStateBackend);4.2.2配置检查点合理配置检查点参数,如检查点间隔、超时时间、最小检查点间隔等,可以提高故障恢复的效率。4.2.3使用SavepointsSavepoints是手动触发的检查点,可以在应用程序升级或重新配置时使用,确保状态的一致性。示例代码//触发Savepoint

StringsavepointPath=env.executeCheckpoint("my-savepoint");4.3状态管理的高级技巧Flink的状态管理提供了灵活性和控制力,以下是一些高级技巧:4.3.1状态后端的持久化将状态后端配置为持久化存储,如HDFS或S3,可以确保状态在故障后仍然可用。4.3.2状态的聚合和清理在检查点过程中,状态可以被聚合和清理,以减少存储需求和提高恢复速度。示例代码//清理旧检查点

env.getCheckpointConfig().setCheckpointStorage(newFsCheckpointStorage("hdfs://localhost:9000/flink/checkpoints"));

env.getCheckpointConfig().setCheckpointCleanup(CheckpointCleanupOptions.ON_CANCELLATION);4.3.3状态的查询和分析Flink提供了状态查询API,可以在运行时或故障恢复后查询和分析状态数据。4.3.4状态的迁移和升级在应用程序升级或重新配置时,可以使用Savepoints或状态迁移API来迁移状态,确保状态的一致性和应用程序的连续性。示例代码//使用Savepoint恢复应用程序

env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,5000));

env.setStateBackend(newRocksDBStateBackend(newPath("hdfs://localhost:9000/flink/checkpoints"),true));

env.executeFromSavepoint("hdfs://localhost:9000/flink/savepoints/my-savepoint");通过遵循这些高级状态与容错特性,可以构建出既高效又可靠的Flink应用程序,即使在大规模数据处理和复杂故障场景下也能保持状态的一致性和处理的精确性。5Flink容错的实践案例5.1实时流处理的容错案例在实时流处理中,Flink的容错机制确保了即使在节点故障的情况下,也能保持数据处理的正确性和一致性。下面通过一个具体的实时流处理场景来展示Flink如何实现容错。5.1.1场景描述假设我们正在处理一个实时的用户点击流数据,目标是统计每分钟内每个URL的点击次数。数据源为Kafka,数据接收后通过Flink进行处理。5.1.2容错策略Flink通过checkpoint机制来保存状态,确保在故障发生时可以从最近的checkpoint恢复。5.1.3代码示例frompyflink.datastreamimportStreamExecutionEnvironment

frompyflink.tableimportStreamTableEnvironment,EnvironmentSettings

frompyflink.table.windowimportTumble

#创建执行环境

env=StreamExecutionEnvironment.get_execution_environment()

env.set_parallelism(1)#设置并行度

t_env=StreamTableEnvironment.create(env,environment_settings=EnvironmentSettings.new_instance().in_streaming_mode().use_blink_planner().build())

#读取Kafka数据

t_env.execute_sql("""

CREATETABLEclickstream(

urlSTRING,

timestampTIMESTAMP(3),

WATERMARKFORtimestampAStimestamp-INTERVAL'5'SECOND

)WITH(

'connector'='kafka',

'topic'='clicks',

'properties.bootstrap.servers'='localhost:9092',

'format'='json'

)

""")

#定义窗口统计

t_env.execute_sql("""

CREATEVIEWurl_clicksAS

SELECT

url,

TUMBLE_START(timestamp,INTERVAL'1'MINUTE)ASwindow_start,

TUMBLE_END(timestamp,INTERVAL'1'MINUTE)ASwindow_end,

COUNT(*)ASclick_count

FROMclickstream

GROUPBYurl,TUMBLE(timestamp,INTERVAL'1'MINUTE)

""")

#输出结果到控制台

t_env.execute_sql("""

CREATETABLEconsole_sink(

urlSTRING,

window_startTIMESTAMP(3),

window_endTIMESTAMP(3),

click_countBIGINT

)WITH(

'connector'='print'

)

""")

#将结果写入控制台

t_env.execute_sql("""

INSERTINTOconsole_sink

SELECT*FROMurl_clicks

""")

#启动Flink作业

t_env.execute("URLClicksCount")5.1.4解释创建执行环境:初始化Flink的执行环境和表环境。读取Kafka数据:定义一个Kafka连接器读取名为clicks的主题数据。定义窗口统计:使用TUMBLE窗口函数,每分钟统计一次URL的点击次数。输出结果:将统计结果输出到控制台。执行作业:启动Flink作业。5.2批处理作业的容错策略Flink的批处理作业通常处理静态数据集,如HDFS上的文件。Flink通过保存作业状态和数据集的元数据来实现容错。5.2.1代码示例frompyflink.datasetimportExecutionEnvironment

frompyflink.tableimportBatchTableEnvironment,EnvironmentSettings

#创建执行环境

env=ExecutionEnvironment.get_execution_environment()

t_env=BatchTableEnvironment.create(env,environment_settings=EnvironmentSettings.new_instance().in_batch_mode().use_blink_planner().build())

#读取HDFS上的数据

t_env.execute_sql("""

CREATETABLEhdfs_source(

idINT,

nameSTRING,

ageINT

)WITH(

'connector'='filesystem',

'path'='hdfs://localhost:9000/data/users.csv',

'format'='csv'

)

""")

#数据处理

t_env.execute_sql("""

CREATEVIEWuser_statsAS

SELECT

name,

AVG(age)ASavg_age

FROMhdfs_source

GROUPBYname

""")

#输出结果到HDFS

t_env.execute_sql("""

CREATETABLEhdfs_sink(

nameSTRING,

avg_ageFLOAT

)WITH(

'connector'='filesystem',

'path'='hdfs://localhost:9000/data/user_stats.csv',

'format'='csv'

)

""")

#将结果写入HDFS

t_env.execute_sql("""

INSERTINTOhdfs_sink

SELECT*FROMuser_stats

""")

#执行Flink作业

t_env.execute("UserStatistics")5.2.2解释创建执行环境:初始化Flink的批处理环境。读取HDFS数据:定义一个HDFS连接器读取users.csv文件。数据处理:计算每个用户的平均年龄。输出结果:将结果写回到HDFS上的user_stats.csv文件。执行作业:启动Flink作业。5.3容错机制在复杂场景下的应用在复杂场景下,如多流连接和状态更新,Flink的容错机制需要更细致的配置来确保数据的一致性和正确性。5.3.1场景描述假设我们有两个实时流,一个为用户点击流,另一个为用户位置流,目标是统计每分钟内每个URL在不同地理位置的点击次数。5.3.2容错策略Flink通过checkpoint和savepoint机制来保存状态,确保在故障发生时可以从最近的checkpoint或savepoint恢复。5.3.3代码示例frompyflink.datastreamimportStreamExecutionEnvironment

frompyflink.tableimportStreamTableEnvironment,EnvironmentSettings

frompyflink.table.windowimportTumble

#创建执行环境

env=StreamExecutionEnvironment.get_execution_environment()

env.set_parallelism(1)

t_env=StreamTableEnvironment.create(env,environment_settings=EnvironmentSettings.new_instance().in_streaming_mode().use_blink_planner().build())

#读取Kafka数据

t_env.execute_sql("""

CREATETABLEclickstream(

urlSTRING,

timestampTIMESTAMP(3),

WATERMARKFORtimestampAStimestamp-INTERVAL'5'SECOND

)WITH(

'connector'='kafka',

'topic'='clicks',

'properties.bootstrap.servers'='localhost:9092',

'format'='json'

)

""")

t_env.execute_sql("""

CREATETABLElocationstream(

locationSTRING,

timestampTIMESTAMP(3),

WATERMARKFORtimestampAStimestamp-INTERVAL'5'SECOND

)WITH(

'connector'='kafka',

'topic'='locations',

'properties.bootstrap.servers'='localhost:9092',

'format'='json'

)

""")

#定义窗口统计

t_env.execute_sql("""

CREATEVIEWurl_clicksAS

SELECT

url,

TUMBLE_START(timestamp,INTERVAL'1'MINUTE)ASwindow_start,

TUMBLE_END(timestamp,INTERVAL'1'MINUTE)ASwindow_end,

COUNT(*)ASclick_count

FROMclickstream

GROUPBYurl,TUMBLE(timestamp,INTERVAL'1'MINUTE)

""")

t_env.execute_sql("""

CREATEVIEWlocation_clicksAS

SELECT

url_clicks.url,

location_clicks.location,

url_clicks.window_start,

url_clicks.window_end,

url_clicks.click_count

FROMurl_clicks

JOINlocationstream

ONurl_clicks.window_start=locationstream.timestamp

""")

#输出结果到控制台

t_env.execute_sql("""

CREATETABLEconsole_sink(

urlSTRING,

locationSTRING,

window_startTIMESTAMP(3),

window_endTIMESTAMP(3),

click_countBIGINT

)WITH(

'connector'='print'

)

""")

#将结果写入控制台

t_env.execute_sql("""

INSERTINTOconsole_sink

SELECT*FROMlocation_clicks

""")

#启动Flink作业

t_env.execute("URLClicksbyLocation")5.3.4解释创建执行环境:初始化Flink的执行环境和表环境。读取Kafka数据:定义两个Kafka连接器,分别读取clicks和locations主题数据。定义窗口统计:使用TUMBLE窗口函数,每分钟统计一次URL的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论