Hadoop实践指南:揭秘HDFS元数据并解析案例

news2024/11/29 22:47:50

1.什么是元数据

元数据(Metadata),描述数据的数据(data about data)。

1.1 HDFS元数据

元数据:关于文件或目录的描述信息,如文件所在路径、文件名称、文件类型等等,这些信息称为文件的元数据metadata

命名空间:文件系统中,为了便于管理存储介质上的,给每个目录、目录中的文件、子目录都起了名字,这样形成的层级结构,称之为命名空间;

HDFS元数据:文件目录树、所有的文件(目录)名称、文件属性(生成时间、副本、权限)、每个文件的块列表、每个block块所在的datanode列表;

1.2 元数据存在形式

Edits Log

HDFS编辑日志文件,保存客户端对HDFS的所有更改记录,如增、删、重命名文件(目录),这些操作会修改HDFS目录树;NameNode会在编辑日志edit日志中记录下来;类似mysql的binlog。一旦系统出故障,可从editlog进行恢复。

Fsimage

fsimage:HDFS元数据镜像文件,即将namenode内存中的数据落入磁盘生成的文件;保存了文件系统目录树信息以及文件、块、datanode的映射关系。

以上都是扫盲,具体数据实际长什么样的呢?

2.实体存在形式

NameNode的存放地址: hdfs-site.xml

<property>
  <name>dfs.namenode.name.dir</name>
  <value>file:///dfs/nn</value>
</property>

JournalNode: hdfs-site.xml。HA模式下,进行元数据的共享存储。

<property>
  <name>dfs.journalnode.edits.dir</name>
  <value>/hadoop/hdfs/journal</value>
</property>

DataNode是HDFS的实际存储节点,负责管理它所在节点的存储;客户端的读写请求。并且定期上报心跳和块的存储位置。

3.元数据生成方式

既然知道存在哪里了,知其燃,还要知其所以燃。接下来,我们从拾材开始:这些数据的生产条件是啥?

1.时间:dfs.namenode.checkpoint.preiod 距离上次的间隔时间:默认3600s,1小时;

2.空间:dfs.namenode.checkpoint.txns edits中的事务限制:默认1000000;

3.人为:使用命令进行保存(集群维护时候操作,防止掉数据);  

# 1.输入文件
hdfs dfs -put /var/log/messages /tmp/

# 2.开启安全模式
hdfs dfsadmin -safemode enter

# 3.创建checkpoint
hdfs dfsadmin -saveNamespace

# 4.退出安全模式
hdfs dfsadmin -safemode leave

操作记录如下:

图片

4.元数据内容剖析

4.1 Fsimage查看

hdfs oiv -i /dfs/nn/current/fsimage_0000000000000171597 -o /dfs/nn/current/fsimage_0000000000000171597.xml -p XML

数据案例

<inode>
 <id>56086</id>
 <type>FILE</type>
 <name>messages</name>
 <replication>3</replication>
 <mtime>1638524892939</mtime>
 <atime>1638524892773</atime>
 <preferredBlockSize>134217728</preferredBlockSize>
 <permission>hdfs:supergroup:0644</permission>
 <blocks>
  <block>
<id>1073758952</id>
<genstamp>18128</genstamp>
<numBytes>239785</numBytes>
  </block>
 </blocks>
<storagePolicyId>0</storagePolicyId>
</inode>

目录解释

Path  目录路径
•   Replication  备份数
•   ModificationTime  最后修改时间
•   AccessTime 最后访问时间
•   PreferredBlockSize首选块大小 byte
•   BlocksCount  块 数
•   FileSize 文件大小 byte
•   NSQUOTA 名称配额 限制指定目录下允许的文件和目录的数量。
•   DSQUOTA  空间配额 限制该目录下允许的字节数
•   Permission权限
•   UserName 用户
•   GroupName 用户组

从这里来看,这是我们刚才上传文件message的记录。页面上看到的记录页面如下:

图片

4.2 Edits文件

查询命令格式

hdfs oev -i /dfs/nn/current/edits_0000000000000230755-0000000000000230770 -o edits.xml -p XML

数据案例:随便一个记录

<RECORD>
 <OPCODE>OP_ADD</OPCODE>
 <DATA>
<TXID>230762</TXID>
<LENGTH>0</LENGTH>
<INODEID>69782</INODEID>
<PATH>/tmp/.cloudera_health_monitoring_canary_files/.canary_file_2021_12_07-22_59_58.179c3216fc1fddcf</PATH>
<REPLICATION>3</REPLICATION>
<MTIME>1638889198054</MTIME>
<ATIME>1638889198054</ATIME>
<BLOCKSIZE>134217728</BLOCKSIZE>
<CLIENT_NAME>DFSClient_NONMAPREDUCE_-580922430_1500</CLIENT_NAME>
<CLIENT_MACHINE>172.21.208.131</CLIENT_MACHINE>
<OVERWRITE>true</OVERWRITE>
<PERMISSION_STATUS>
  <USERNAME>hdfs</USERNAME>
  <GROUPNAME>supergroup</GROUPNAME>
  <MODE>438</MODE>
</PERMISSION_STATUS>
<ERASURE_CODING_POLICY_ID>0</ERASURE_CODING_POLICY_ID>
<RPC_CLIENTID>c56340fe-a1fd-44aa-a726-8e407b9c8f90</RPC_CLIENTID>
<RPC_CALLID>211691</RPC_CALLID>
 </DATA>
  </RECORD>

4.3 blockreport

除了NameNode存储的元数据意外,DataNode也有干活,专业词汇叫:blockreport

全量块汇报(Full Block Report,简称FBR)

全量块汇报,顾名思义,就是将DN中存储的所有block信息都汇报给NN。

通常,DN中都存储一定数量级的block,全量汇报时,耗时会相对更长,发送的数据也会更多。因此,全量块汇报的时间间隔相对也会更长,间隔时间可配置,默认间隔为6小时。

增量块汇报(Incremental Block Report,简称IBR)

由于全量块汇报的时间间隔很长,那么在这期间的block信息变更要通知到NN,这就是增量块汇报的逻辑了。

当block块的状态发送变更时,DN就会触发发送增量块汇报信息给NN。增量块汇报的时间间隔也是可以配置的,默认间隔为0。即一旦触发增量块汇报,就立即发送。如果大于0,则按间隔时间发送增量块汇报.

而这个数据,可以在NN服务的startup页面可以查看到信息。最下面的Blocks(141470/141471) 就是DataNode的blockreport信息,就是用来更新元数据信息的。

图片

以上就是HDFS相关的元数据相关的内容,不知看了,有概念了吗?看懂了,就可以加入元宇宙了。

5.元数据异常处理案例

元数据很重要,他的离去,往往会同步带走几个倒霉蛋(被迫离职的背锅侠),虽然搞了很多的保障策略,但是异常还是有概率发生的。那么接下来,我们就来说明下一些常见的元数据异常处理。

5.1 元数据版本不一致

异常表现

这种异常,往往出现在集群安装阶段,特别是高可用集群的安装阶段。主要表现为:

1.两给NN服务节点的元数据不一致,导致无法实现主备搭建。2.NN服务与DN服务版本不一致,导致DN节点无法加入到集群。

原因

这种异常现象表现有:NN服务无法启动、DN服务启动了,但是加入不到集群。

报错日志

23/08/28 05:50:20 WARN namenode.NameNode: Registration IDs mismatched: the DatanodeRegistration ID is NS-145281851-CID-d4fe6b45-8766-441e-8e98-ba09164c211c-1685956713522 but the expected ID is NS-1072740375-CID-abd29939-1b50-4cc1-9585-6964de90a91b-1678793793759
23/08/28 05:50:20 INFO ipc.Server: IPC Server handler 0 on default port 8020, call Call#1053 Retry#0 org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol.sendHeartbeat from 192.168.131.230:52548
org.apache.hadoop.hdfs.protocol.UnregisteredNodeException: Unregistered server: DatanodeRegistration(192.168.131.230:50010, datanodeUuid=14e37d26-4196-433e-8d10-bef402eadd24, infoPort=50075, infoSecurePort=0, ipcPort=8010, storageInfo=lv=-57;cid=CID-d4fe6b45-8766-441e-8e98-ba09164c211c;nsid=145281851;c=1685956713522)
  at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.verifyRequest(NameNodeRpcServer.java:1744)

其中报错关键字:Registration IDs mismatched注册的ID不匹配。

这种类似的报错信息会出现在DataNode,NameNode,JournalNode服务的启动程序中。遇到这个报错,那么大概可以断定,你的程序的元数据信息出现问题了

异常解析 

这种问题一般怎么发生的呢?

经过N年的经验,这种一般都是不按正常部署操作流程导致的。其中,有几个步骤是和元数据相关的。

#1.元数据初始化程序
#该命令,是在集群安装阶段,NN第一个节点初始化集群时候用的。这是元数据数据诞生的地方,会在第一个NameNode节点,dfs.namenode.name.dir配置所在地方。
hdfs namenode -format

#2.元数据同步到JournalNode阶段
#该操作的功能,是将步骤1 NN初始化后的元数据信息,同步到所有的JournalNode服务。
hdfs namenode -initializeSharedEdits

#3.备份NN节点节点同步
#该操作,是将步骤1中的元数据中的内容,同步到第二个NN节点。
hdfs namenode -bootstrapStandby

#4.Data元数据
hadoop-daemon.sh start datanode
hdfs-start.sh
start-all.sh
hdfs datanode

DataNode的元数据生成,或者集群的加入,是在第一次启动服务的时候从NN节点获取的。开启的启动方式有很多种,只要能启动DataNode,都能生成对应的元信息。

元数据版本不一致问题,一般都是上面讨论的几个步骤出了点小小的差异导致的。比如最常见的重复初始化:初始化成功,并同步过元数据,或者启动过DN服务。然后再后续步骤中发现有问题,又重新初始化了集群。这样就会出现以上的报错。具体是哪个服务报错呢?就得看你上面的步骤都做了那些。

异常处理 

既然都知道了异常的产生步骤和原理,那么处理起来就方便多了。

1.大招

不管啥,直接删除集群所有的信息,然后直接“梭哈”重新来一次。删除的信息包括:

删除内容

配置项

案例

主NN节点元数据信息

dfs.namenode.name.dir

/hadoop/hdfs/namenode

备NN节点元数据信息

同上(不同机器)

同上(不同机器)

JournalNode元数据信息

dfs.journalnode.edits.dir

/hadoop/hdfs/journal

DataNode数据

dfs.datanode.data.dir

/hadoop/hdfs/data

特别说明,该操作会清空所有hdfs数据,一般用于安装阶段出问题,如果你的集群已经有数据了,那么该方法就不能用了,不然,你就是前辈(背锅侠,最好的结果就是赔偿N+1)。

2.备节点或JournalNode元数据不一致

如果集群有数据了,不能删数据啥的。那么现在正在使用的元数据信息,是保存在主节点(Activate NameNode)服务,遇到这种情况,就删除JournalNode和备节点的NN服务,然后使用Data元数据的步骤再执行同步操作。

3.DataNode元数据不一致

这种情况,应该是你的节点加错集群了。首先确认下这台主机是你操作集群的主机吗(一个公司可能多有个集群)。如果是确认没问题的,那么就备份(删除)现在的DataNode目录数据,然后重新启动服务即可。

5.2 元数据文件错误

异常表现

此处特指的错误,是特指文件的损坏,某个元数据(fsimage,edits_inprogress,edits)文件损坏。

原因

这种异常,一般出现在暴力关机(断电、强制关机)情况下,导致元数据写入不完整。导致下次启动的时候,无法加载文件。

报错日志


23/08/28 23:07:15 ERROR namenode.FSImage: Failed to load image from FSImageFile(file=/hadoop/hdfs/namenode/current/fsimage_0000000000000118333, cpktTxId=0000000000000118333)
java.io.IOException: Negative seek offset
  at java.io.RandomAccessFile.seek(RandomAccessFile.java:555)
  at org.apache.hadoop.hdfs.server.namenode.FSImageUtil.loadSummary(FSImageUtil.java:63)

这类报错特别明显,会直接告诉你那个文件有问题。

异常处理 

既然知道问题了,原因也知道了,那么处理起来就好办了,不是有问题吗?那么我们就去下载没问题的啊。下载的地方有:运行中的NameNode; JournalNode节点;

建议,优先下载NN节点的内容,因为是最新的,最全的。这样不会掉数据。其次才是JournalNode的。

如果发现拷贝了其他节点的元数据过来但是依旧不能启用,那麻烦就到了,大概率不好修了。

5.3 元数据内容错误

异常表现

在10年+的职业生涯中,这种报错只遇到一个,他属于元数据的内容错误,严格得来说,是元数据是正确的,但是,他执行不了。听起来有点绕,咋们来屡屡。

原因

情况是这样的,这个集群因为历史遗留原因,几乎是放养状态,然后NameNode Standby节点挂了很久很久…

那么问题就来了,没地方做edits日志的合并了,里面超级多的fsimage文件…此处知识点,请自行百度《HDFS 元数据合并流程》

然后fsimage过多,在NN服务再次启动的时候,那些都得需要执行一次的啊,然后发现,有些操作直接报错了无法执行下去。

具体的操作是OP_CLOSE执行失败,并提升对应的删除目录。到具体的HDFS上去看,发现是一个TMP目录,早就删除了,连父目录都不知删了多久了。

报错日志

情况是这样的,这个集群因为历史遗留原因,几乎是放养状态,然后NameNode Standby节点挂了很久很久…

那么问题就来了,没地方做edits日志的合并了,里面超级多的fsimage文件…此处知识点,请自行百度《HDFS 元数据合并流程》。

然后fsimage过多,在NN服务再次启动的时候,那些都得需要执行一次的啊,然后发现,有些操作直接报错了无法执行下去。

具体的操作是OP_CLOSE执行失败,并提升对应的删除目录。到具体的HDFS上去看,发现是一个TMP目录,早就删除了,连父目录都不知删了多久了。

异常解析 

大概的日志报错信息如下,就是加载image的时候直接error,提示某个操作执行失败:

23/08/28 23:55:05 ERROR org.apache.hadoop.hdfs.server.namenode.FSEditLogLoader: Encountered exception on operation CloseOp [length=0, inodeId=0, path=/x/x/x/x, replication=3, 
mtime=1693288028609, atime=1693288028005, blockSize=268435456, blocks=[blk_1167720789_98154524], permissions=x:x:rw-r-----, aclEntries=null, clientName=, clientMachine=, opCode=OP_CLOSE, txid=1097889118]
java.io.IOException: File is not under construction: /x/x/x/x

其中包含具体的关键词:OP_CLOSE

异常处理 

这种问题是OP_CLOSE操作时候,需要验证执行的可行性,需要处于under construction的状态,但是现在的集群状态已经不满足此情况,对此,需要将这些操作做下小小的修改。将OP_CLOSE操作修改OP_TIMES操作。

修改前案例(此处,已经将具体数据进行了脱敏,修改为xxx)

 <RECORD>
    <OPCODE>OP_CLOSE</OPCODE>
    <DATA>
      <TXID>1097889118</TXID>
      <LENGTH>0</LENGTH>
      <INODEID>0</INODEID>
      <PATH>/xxx/xxx/xxx/xxx</PATH>
      <REPLICATION>3</REPLICATION>
      <MTIME>1693288028609</MTIME>
      <ATIME>1693288028005</ATIME>
      <BLOCKSIZE>134217728</BLOCKSIZE>
      <CLIENT_NAME></CLIENT_NAME>
      <CLIENT_MACHINE></CLIENT_MACHINE>
      <OVERWRITE>false</OVERWRITE>
      <BLOCK>
        <BLOCK_ID>1212673348</BLOCK_ID>
        <NUM_BYTES>7290666</NUM_BYTES>
        <GENSTAMP>138932875</GENSTAMP>
      </BLOCK>
      <PERMISSION_STATUS>
        <USERNAME>xxxx</USERNAME>
        <GROUPNAME>xxxx</GROUPNAME>
        <MODE>420</MODE>
      </PERMISSION_STATUS>
    </DATA>
  </RECORD>

替换后的内容为

 <RECORD>
    <OPCODE>OP_TIMES</OPCODE>
    <DATA>
      <TXID>1097889118</TXID>
      <LENGTH>0</LENGTH>
      <PATH>/xxx/xxx/xxx/xxx</PATH>
      <MTIME>1693288028609</MTIME>
      <ATIME>-1</ATIME>
    </DATA>
  </RECORD>

整体的步骤如下

1. 使用hdfs oev 将edits日志解析为xml格式;                                        

2. 使用shell 或者其他程序,将xml中的关于OP_CLOSE的操作整段替换为OP_TIMES操作。此处,可以使用shell按关键词 进行分块拆分和替换。

3. 将修改后的xml,重新恢复成edits日志后,再启动服务。   

以上,就是笔者关于元数据的一些相关实践,感谢各位大佬的查看。

Hadoop实践指南:揭秘HDFS元数据并解析案例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1253729.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

二进制数据转换成十六进制表示 binascii.hexlify()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 二进制数据转换成十六进制表示 binascii.hexlify() 选择题 binascii.hexlify()参数的数据类型可以是&#xff1f; import binascii number 11 byte_data number.to_bytes() hex_data bin…

NX二次开发UF_CURVE_ask_conic_data 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_conic_data Defined in: uf_curve.h int UF_CURVE_ask_conic_data(tag_t conic, UF_CURVE_conic_t * conic_data ) overview 概述 Reads the data from the conic ar…

SSF-CNN:空间光谱融合的卷积光谱图像超分网络

SSF-CNN: SPATIAL AND SPECTRAL FUSION WITH CNN FOR HYPERSPECTRAL IMAGE SUPER-RESOLUTION 文章目录 SSF-CNN: SPATIAL AND SPECTRAL FUSION WITH CNN FOR HYPERSPECTRAL IMAGE SUPER-RESOLUTION简介解决问题网络框架代码实现训练部分运行结果 简介 ​ 本文提出了一种利用空…

基于STC12C5A60S2系列1T 8051单片读写掉电保存数据IIC总线器件24C02多字节并显示在液晶显示器LCD1602上应用

基于STC12C5A60S2系列1T 8051单片多字节读写掉电保存数据IIC总线器件24C02多字节并显示在液晶显示器LCD1602上应用 STC12C5A60S2系列1T 8051单片机管脚图STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式及配置STC12C5A60S2系列1T 8051单片机I/O口各种不同工作模式介绍IIC通…

pytorch分布式训练

1 基本概念 rank&#xff1a;进程号&#xff0c;在多进程上下文中&#xff0c;我们通常假定rank 0是第一个进程或者主进程&#xff0c;其它进程分别具有1&#xff0c;2&#xff0c;3不同rank号&#xff0c;这样总共具有4个进程 node&#xff1a;物理节点&#xff0c;可以是一个…

Java游戏之王者荣耀

首先创建类&#xff1a; 游戏运行结果如下&#xff1a; GameFrame类 所需图片&#xff1a; GameObject类 Turret类 所需图片&#xff1a; TurretBlue类 TurretRed类 Champion类 所需图片&#xff1a; 单个&#xff1a; move包: ChampionDaji类 所需图片&#xff1a; Minio…

css加载会造成阻塞吗??

前言 前几天面试问到了这个问题&#xff0c;当时这个答得不敢确定哈哈&#xff0c;虽然一面还是过了 现在再分析下这个&#xff0c;总结下&#xff0c;等下次遇到就能自信得回答&#xff0c;666 准备工作 为了完成本次测试&#xff0c;先来科普一下&#xff0c;如何利用chr…

输出后,我悟了!

大家好&#xff0c;我是木川 今天和前同事吃饭聊天&#xff0c;谈到了输出&#xff0c;今天简单谈下关于输出的重要性 一、为什么要输出 1、不输出容易忘&#xff0c;如果不输出很容易就忘记了&#xff0c;如果再遇见一次&#xff0c;还是需要重新学习&#xff0c;实际上是浪费…

【如何学习Python自动化测试】—— Python 的 unittest 框架

10 、Python 的 unittest 框架 10.1 Unittest 框架介绍 Unittest是Python语言中的一种测试框架&#xff0c;是Python标准库中的一个模块。它可以帮助开发者编写自动化测试&#xff0c;可以进行单元测试、集成测试、功能测试等各种类型的测试。 Unittest的特点是简单易学&#…

用 Addon 增强 Node.js 和 Electron 应用的原生能力

前言 Node.js Addon 是 Node.js 中为 JavaScript 环境提供 C/C 交互能力的机制。其形态十分类似 Java 的 JNI&#xff0c;都是通过提供一套 C/C SDK&#xff0c;用于在 C/C 中创建函数方法、进行数据转换&#xff0c;以便 JavaScript / Java 等语言进行调用。这样编写的代码通常…

突破技术障碍:软件工程师如何应对项目中的难题?

在软件开发项目中&#xff0c;工程师常常会遇到各种技术难题。这些难题可能涉及到复杂的算法、不兼容的系统、难以预见的软件行为&#xff0c;或者其他许多方面。 以下是一些策略和方法&#xff0c;可以帮助软件工程师有效地应对这些挑战&#xff1a; 1、理解问题&#xff1a;…

MySQL数据库——存储函数(介绍、案例)

目录 介绍 案例 介绍 存储函数是有返回值的存储过程&#xff0c;存储函数的参数只能是IN类型的。具体语法如下&#xff1a; CREATE FUNCTION 存储函数名称 ([ 参数列表 ]) RETURNS type [characteristic ...] BEGIN-- SQL语句RETURN ...;END ; characteristic说明&#xf…

Matplotlib子图的创建_Python数据分析与可视化

Matplotlib子图的创建 plt.axes创建子图fig.add_axes()创建子图 plt.axes创建子图 前面已经介绍过plt.axes函数&#xff0c;这个函数默认配置是创建一个标准的坐标轴&#xff0c;填满整张图。 它还有一个可选的参数&#xff0c;由图形坐标系统的四个值构成。这四个值表示为坐…

05 _ 系统设计目标(三):如何让系统易于扩展?

从架构设计上来说&#xff0c;高可扩展性是一个设计的指标&#xff0c;它表示可以通过增加机器的方式来线性提高系统的处理能力&#xff0c;从而承担更高的流量和并发。 你可能会问&#xff1a;“在架构设计之初&#xff0c;为什么不预先考虑好使用多少台机器&#xff0c;支持…

C语言之指针知识点总结

C语言之指针知识点总结 文章目录 C语言之指针知识点总结1. 初识指针1.1 取地址操作符 &1.2 指针变量1.3 解引用操作符 *1.4 指针变量1.4.1 大小1.4.2 指针类型的意义 1.5 void*指针1.6 const关键字1.61 const修饰变量1.6.2 const修饰指针变量 1.7 指针的运算1.7.1 指针-整数…

堆和栈的区别 重点来说一下堆和栈;堆与栈之间的联系

文章目录 堆和栈的区别重点来说一下堆和栈&#xff1a;那么堆和栈是怎么联系起来的呢? 堆与栈的区别 很明显&#xff1a; 今天来聊一聊java中的堆和栈&#xff0c;工作当中这两个也是经常遇到的&#xff0c;知识我们没有去注意理论上的这些内容&#xff0c;今天就来分享一下。…

MIPI 打怪升级之DSI篇

MIPI 打怪升级之DSI篇 目录 1 Overview2 DSI Mode 2.1 Video 模式2.2 Command 模式3 DSI Physical Layer 3.1 数据流控3.2 双向性3.3 Video Mode Interfaces3.4 Command Mode Interfaces3.5 Clock4 多通道管理 4.1 通道数匹配4.2 线上数据分布5 DSI 协议 5.1 包格式 5.1.1 短包…

Scrapy爬虫异步框架(一篇文章齐全)

1、Scrapy框架初识 2、Scrapy框架持久化存储&#xff08;点击前往查阅&#xff09; 3、Scrapy框架内置管道&#xff08;点击前往查阅&#xff09; 4、Scrapy框架中间件&#xff08;点击前往查阅&#xff09; Scrapy 是一个开源的、基于Python的爬虫框架&#xff0c;它提供了…

CleanMyMac X4.14.5Crack最新Mac电脑清理优化最佳应用

CleanMyMac X 4.14.5是用于清理和优化Mac的最佳应用程序和强大工具。它看起来很棒而且很容易理解。该软件可以清理、保护、优化、稳定和维护您的 Mac 系统。您可以立即删除不必要的、不寻常的、无用的垃圾文件、损坏的文件垃圾&#xff0c;并释放大量内存空间。此外&#xff0c…

【Unity实战】切换场景加载进度和如何在后台异步加载具有庞大世界的游戏场景,实现无缝衔接(附项目源码)

文章目录 最终效果前言一、绘制不同的场景二、切换场景加载进度1. 简单实现2. 优化 三、角色移动和跳跃控制四、添加虚拟摄像机五、触发器动态加载场景六、最终效果参考源码完结 最终效果 前言 观看本文后&#xff0c;我的希望你对unity场景管理有更好的理解&#xff0c;并且能…