当前位置: 首页 > news >正文

Spark: a little summary

转眼写spark一年半了,从之前写机器学习组件、做olap到后面做图计算,一直都是用的spark,惭愧的是没太看过里面的源码。这篇文章的目的是总结一下Spark里面比较重要的point,重点部分会稍微看一下源代码,因为spark是跟clickhouse同级别的东西,复杂度也是相当的高,因为时间原因,本文也不会过度地进行展开。
只能说:源码用时方恨少。以前在写spark的时候没看源码实现真的挺遗憾的,现在也没那么多时间让我一点点细看了,之后稳定下来之后希望能有机会吧。

数据抽象

RDD

RDD 是一种抽象,是 Spark 对于分布式数据集的抽象,它用于囊括所有内存中和磁盘中的分布式数据实体。
数据分片(Partitions)是 RDD 抽象的重要属性之一。
在初步认识了 RDD 之后,接下来咱们换个视角,从 RDD 的重要属性出发,去进一步深入理解 RDD。
要想吃透 RDD,我们必须掌握它的 4 大属性:

  • partitions:数据分片(由partitioner决定)
  • partitioner:分片切割规则
  • dependencies:RDD 依赖
  • compute:转换函数

在 RDD 的编程模型中,一共有两种算子,Transformations 类算子和 Actions 类算子。开发者需要使用 Transformations 类算子,定义并描述数据形态的转换过程,然后调用 Actions 类算子,将计算结果收集起来、或是物化到磁盘。
image.png
在 Spark 中,创建 RDD 的典型方式有两种:

  • 通过 SparkContext.parallelize 在内部数据之上创建 RDD;
  • 通过 SparkContext.textFile 等 API 从外部数据创建 RDD。

使用分区变量而非RDD变量

在下面的例子中,RDD每一条都会产生一个MD5对象,这是没必要的。

// 把普通RDD转换为Paired RDDimport java.security.MessageDigestval cleanWordRDD: RDD[String] = _ val kvRDD: RDD[(String, Int)] = cleanWordRDD.map{ word =>// 获取MD5对象实例val md5 = MessageDigest.getInstance("MD5")// 使用MD5计算哈希值val hash = md5.digest(word.getBytes).mkString// 返回哈希值与数字1的Pair(hash, 1)
}

使用mapPartitions可以以数据分区为粒度的数据转换:

// 把普通RDD转换为Paired RDDimport java.security.MessageDigestval cleanWordRDD: RDD[String] = _ // 请参考第一讲获取完整代码val kvRDD: RDD[(String, Int)] = cleanWordRDD.mapPartitions( partition => {// 注意!这里是以数据分区为粒度,获取MD5对象实例val md5 = MessageDigest.getInstance("MD5")val newPartition = partition.map( word => {// 在处理每一条数据记录的时候,可以复用同一个Partition内的MD5对象(md5.digest(word.getBytes()).mkString,1)})newPartition
})

DataFrame

进程模型

image.png
对于一个完整的 RDD,每个 Executors 负责处理这个 RDD 的一个数据分片子集。每当任务执行完毕,Executors 都会及时地与 Driver 进行通信、汇报任务状态。Driver 在获取到 Executors 的执行进度之后,结合计算流图的任务拆解,依次有序地将下一阶段的任务再次分发给 Executors 付诸执行,直至整个计算流图执行完毕。

调度模型

image.png
DAGScheduler 的主要职责有三个:

  • 根据用户代码构建 DAG;
  • 以 Shuffle 为边界切割 Stages;
  • 基于 Stages 创建 TaskSets,并将 TaskSets 提交给 TaskScheduler 请求调度。

SchedulerBackend 用一个叫做 ExecutorDataMap 的数据结构,来记录每一个计算节点中 Executors 的资源状态。这里的 ExecutorDataMap 是一种 HashMap,它的 Key 是标记 Executor 的字符串,Value 是一种叫做 ExecutorData 的数据结构。
ExecutorData 用于封装 Executor 的资源状态,如 RPC 地址、主机地址、可用 CPU 核数和满配 CPU 核数等等,它相当于是对 Executor 做的“资源画像”。
WorkerOffer 封装了 Executor ID、主机地址和 CPU 核数,它用来表示一份可用于调度任务的空闲资源。
对于给定的 WorkerOffer,TaskScheduler 是按照任务的本地倾向性,来遴选出 TaskSet 中适合调度的 Tasks。
像上面这种定向到计算节点粒度的本地性倾向,Spark 中的术语叫做 NODE_LOCAL。除了定向到节点,Task 还可以定向到进程(Executor)、机架、任意地址,它们对应的术语分别是 PROCESS_LOCAL、RACK_LOCAL 和 ANY。
对于倾向 PROCESS_LOCAL 的 Task 来说,它要求对应的数据分区在某个进程(Executor)中存有副本;而对于倾向 RACK_LOCAL 的 Task 来说,它仅要求相应的数据分区存在于同一机架即可。ANY 则等同于无定向,也就是 Task 对于分发的目的地没有倾向性,被调度到哪里都可以。
image.png
总结
任务调度分为如下 5 个步骤:

  1. DAGScheduler 以 Shuffle 为边界,将开发者设计的计算图 DAG 拆分为多个执行阶段 Stages,然后为每个 Stage 创建任务集 TaskSet。
  2. SchedulerBackend 通过与 Executors 中的 ExecutorBackend 的交互来实时地获取集群中可用的计算资源,并将这些信息记录到 ExecutorDataMap 数据结构。
  3. 与此同时,SchedulerBackend 根据 ExecutorDataMap 中可用资源创建 WorkerOffer,以 WorkerOffer 为粒度提供计算资源。
  4. 对于给定 WorkerOffer,TaskScheduler 结合 TaskSet 中任务的本地性倾向,按照 PROCESS_LOCAL、NODE_LOCAL、RACK_LOCAL 和 ANY 的顺序,依次对 TaskSet 中的任务进行遍历,优先调度本地性倾向要求苛刻的 Task。
  5. 被选中的 Task 由 TaskScheduler 传递给 SchedulerBackend,再由 SchedulerBackend 分发到 Executors 中的 ExecutorBackend。Executors 接收到 Task 之后,即调用本地线程池来执行分布式任务。
  6. 一个job由action算子来触发,每个job又会根据shuffle情况划分出多个stage,每个stage中又会划分出多个task,再根据taskScheduler分配到各个Excecutor。

Shuffle

Shuffle 文件的生成,是以 Map Task 为粒度的,Map 阶段有多少个 Map Task,就会生成多少份 Shuffle 中间文件。
image.png
shuffle文件包括两个文件,**一个是记录(Key,Value)键值对的 data 文件,另一个是记录键值对所属 Reduce Task 的 index 文件。(典中典的列式存储)**换句话说,index 文件标记了 data 文件中的哪些记录,应该由下游 Reduce 阶段中的哪些 Task(简称 Reduce Task)消费。
假设 Reduce 阶段有 N 个 Task,这 N 个 Task 对应着 N 个数据分区,那么在 Map 阶段,每条记录应该分发到哪个 Reduce Task,是由下面的公式来决定的。

P = Hash(Record Key) % N

shuffle生成过程
image.png
在生成中间文件的过程中,**Spark 会借助一种类似于 Map 的数据结构,来计算、缓存并排序数据分区中的数据记录。**这种 Map 结构的 Key 是(Reduce Task Partition ID,Record Key),而 Value 是原数据记录中的数据值,如图中的“内存数据结构”所示。
对于数据分区中的数据记录,Spark 会根据我们前面提到的公式 1 逐条计算记录所属的目标分区 ID,然后把主键(Reduce Task Partition ID,Record Key)和记录的数据值插入到 Map 数据结构中。当 Map 结构被灌满之后,Spark 根据主键对 Map 中的数据记录做排序,然后把所有内容溢出到磁盘中的临时文件,如图中的步骤 1 所示。
随着 Map 结构被清空,Spark 可以继续读取分区内容并继续向 Map 结构中插入数据,直到 Map 结构再次被灌满而再次溢出,如图中的步骤 2 所示。就这样,如此往复,直到数据分区中所有的数据记录都被处理完毕。
到此为之,磁盘上存有若干个溢出的临时文件,而内存的 Map 结构中留有部分数据,Spark 使用归并排序算法对所有临时文件和 Map 结构剩余数据做合并,分别生成 data 文件、和与之对应的 index 文件,如图中步骤 4 所示。Shuffle 阶段生成中间文件的过程,又叫 Shuffle Write。

数据聚合

groupbykey的全量shuffle开销很大(不做map端聚合,只做reduce端聚合),因此普遍使用 reduceByKey、aggregateByKey 和 combineByKey而不是groupbykey。

  • reduceByKey 在落盘与分发之前,会先在 Shuffle 的 Map 阶段做初步的聚合计算。在 Map 阶段,reduceByKey 把 Key 同为 Streaming 的两条数据记录聚合为一条,聚合逻辑就是由函数 f 定义的、取两者之间 Value 较大的数据记录,这个过程我们称之为“Map 端聚合”。相应地,数据经由网络分发之后,在 Reduce 阶段完成的计算,我们称之为“Reduce 端聚合”。reduceByKey 算子的局限性,在于其 Map 阶段与 Reduce 阶段的计算逻辑必须保持一致,这个计算逻辑统一由聚合函数 f 定义。当一种计算场景需要在两个阶段执行不同计算逻辑的时候,reduceByKey 就爱莫能助了。
  • aggregateByKey可以自定义map和reduce端聚合,是更加灵活的聚合算子

内存管理和存储系统

Shuffle 中间文件消耗的是节点磁盘,而广播变量主要占用节点的内存空间,RDD Cache 则是“脚踏两条船”,既可以消耗内存,也可以消耗磁盘。
image.png
Execution Memory 用来执行分布式任务。分布式任务的计算,主要包括数据的转换、过滤、映射、排序、聚合、归并等环节,而这些计算环节的内存消耗,统统来自于 Execution Memory。
Storage Memory 用于缓存分布式数据集,比如 RDD Cache、广播变量等等。RDD Cache 指的是 RDD 物化到内存中的副本。在一个较长的 DAG 中,如果同一个 RDD 被引用多次,那么把这个 RDD 缓存到内存中,往往会大幅提升作业的执行性能。
image.png
存储系统主要是由BlockManager模块负责:
image.png
BlockManager 的核心职责,在于管理数据块的元数据(Meta data),这些元数据记录并维护数据块的地址、位置、尺寸以及状态。
image.png

Cache

image.png
cache 函数实际上会进一步调用 persist(MEMORY_ONLY)来完成计算

数据的准备、重分配和持久化

这部分相关的算子如下:
image.png
首先,在数据准备阶段,union 与 sample 用于对不同来源的数据进行合并与拆分。
我们从左往右接着看,接下来是数据预处理环节。较为均衡的数据分布,对后面数据处理阶段提升 CPU 利用率更有帮助,可以整体提升执行效率。那这种均衡要怎么实现呢?没错,这时就要 coalesce 与 repartition 登场了,它们的作用就是重新调整 RDD 数据分布。
在数据处理完毕、计算完成之后,我们自然要对计算结果进行收集。Spark 提供了两类结果收集算子,一类是像 take、first、collect 这样,把结果直接收集到 Driver 端;另一类则是直接将计算结果持久化到(分布式)文件系统,比如咱们这一讲会提到的 saveAsTextFile。

  • RDD 的 sample 算子用于对 RDD 做随机采样,从而把一个较大的数据集变为一份“小数据”。相较其他算子,sample 的参数比较多,分别是 withReplacement、fraction 和 seed。因此,要在 RDD 之上完成数据采样,你需要使用如下的方式来调用 sample 算子:sample(withReplacement, fraction, seed)。
  • 开发者可以使用 repartition 算子随意调整(提升或降低)RDD 的并行度,而 coalesce 算子则只能用于降低 RDD 并行度。repartition和coalesce相比较,repartition由于引入了shuffle机制,对数据进行打散,混洗,重新平均分配,所以repartition操作较重,但是数据分配均匀。而coalesce只是粗力度移动数据,没有平均分配的过程,会导致数据分布不均匀,在计算时出现数据倾斜。

image.png

广播变量和累加器

  • 广播变量的分发不以task为粒度,而是以Executor为粒度,这样就减少了变量分发的开销
  • 累加器用于存储全局变量

配置项

image.png

Catalyst

Catalyst 优化器,它的职责在于创建并优化执行计划,它包含 3 个功能模块,分别是创建语法树并生成执行计划、逻辑阶段优化和物理阶段优化。
在 Catalyst 优化环节,Spark SQL 首先把用户代码转换为 AST 语法树,又叫执行计划,然后分别通过逻辑优化和物理优化来调整执行计划。逻辑阶段的优化,主要通过先验的启发式经验,如谓词下推、列剪枝,对执行计划做优化调整。而物理阶段的优化,更多是利用统计信息,选择最佳的执行机制、或添加必要的计算节点。

Tungsten

Tungsten 用于衔接 Catalyst 执行计划与底层的 Spark Core 执行引擎,它主要负责优化数据结果与可执行代码。
Tungsten 设计并实现了一种叫做 Unsafe Row 的二进制数据结构。Unsafe Row 本质上是字节数组,它以极其紧凑的格式来存储 DataFrame 的每一条数据记录,大幅削减存储开销,从而提升数据的存储与访问效率。

相关文章:

Spark: a little summary

转眼写spark一年半了,从之前写机器学习组件、做olap到后面做图计算,一直都是用的spark,惭愧的是没太看过里面的源码。这篇文章的目的是总结一下Spark里面比较重要的point,重点部分会稍微看一下源代码,因为spark是跟cli…...

018—pandas 生成笛卡尔积排列组合合并多列字符串数据

思路: 本需求需要将给定的几列数据,生成一个排列组合形式的数据列,利用到 Pandas 多层索引生成的笛卡尔积的方法。 二、使用步骤 1.引入库 代码如下(示例): import pandas as pd2.读入数据 代码如下&…...

【算法与数据结构】链表、哈希表、栈和队列、二叉树(笔记二)

文章目录 四、链表理论五、哈希表理论五、栈和队列理论5.1 单调栈 六、二叉树理论6.1 树的定义6.2 二叉树的存储方式6.3 二叉树的遍历方式6.4 高度和深度 最近博主学习了算法与数据结构的一些视频,在这个文章做一些笔记和心得,本篇文章就写了一些基础算法…...

bugku3

前女友 md5 进去又是讴歌乱进的东西 源代码 看到code.txt,访问一下 <?php if(isset($_GET[v1]) && isset($_GET[v2]) && isset($_GET[v3])){$v1 $_GET[v1];$v2 $_GET[v2];$v3 $_GET[v3];if($v1 ! $v2 && md5($v1) md5($v2)){if(!strcmp($v3,…...

相机的白平衡

相机的白平衡是指相机根据拍摄环境的光源色温&#xff0c;调整图像中白色看起来应该是白色的功能。白平衡的设置对于确保图像中的颜色准确性非常重要&#xff0c;因为不同光源的色温会使白色看起来有不同的色调。 通常&#xff0c;相机提供了一些预设的白平衡模式&#xff0c;…...

刷题日记-Day2- Leedcode-977. 有序数组的平方,209. 长度最小的子数组,59. 螺旋矩阵 II-Python实现

刷题日记Day2 977 有序数组的平方209. 长度最小的子数组59. 螺旋矩阵 II 977 有序数组的平方 链接&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/description/ 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组…...

Linux命令-chcon命令(修改对象(文件)的安全上下文)

说明 chcon命令 是修改对象&#xff08;文件&#xff09;的安全上下文&#xff0c;比如&#xff1a;用户、角色、类型、安全级别。也就是将每个文件的安全环境变更至指定环境。使用 --reference 选项时&#xff0c;把指定文件的安全环境设置为与参考文件相同。chcon命令位于 /…...

【漏洞复现】大华DSS视频管理系统信息泄露漏洞

Nx01 产品简介 大华DSS数字监控系统是一个在通用安防视频监控系统基础上设计开发的系统&#xff0c;除了具有普通安防视频监控系统的实时监视、云台操作、录像回放、报警处理、设备治理等功能外&#xff0c;更注重用户使用的便利性。 Nx02 漏洞描述 大华DSS视频管理系统存在信…...

websocket了解下

websocket请求长啥样 GET /chat HTTP/1.1 Host: example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ Sec-WebSocket-Version: 13 啥是websocket websocket是http的一种&#xff0c;服务器可以主动向客户端推送信息&#xff0c;…...

docker install private registry 【docker 安装 registry 仅证书认证】

预备条件&#xff1a; 安装docker 我们设定镜像仓库域名为registry01.dev.com 配置/etc/hosts 192.168.23.51 registry01.dev.com安装 registry #!/bin/bashreg_ip$1 reg_n$2 reg_port$3if [ $# -eq 0 ]; thenecho "Usage: $0 [reg_ip] [registry_name]"echo &q…...

JavaWeb——004Maven SpringBootWeb入门

一、Maven 1、什么是maven&#xff1f; 2、Maven的作用是什么&#xff1f;&#xff08;3种&#xff09; 1.1、方便的依赖管理 依赖管理&#xff1a;有了Maven&#xff0c;我们就不用再手动导入Jar包了&#xff0c;我们只需要在配置文件当中&#xff0c;简单描述一下项目所需要…...

数据结构与算法-常用排序算法

一、常用排序说明 当涉及排序算法时&#xff0c;理解每个算法的工作原理、时间复杂度和空间复杂度是至关重要的。下面对常用排序算法进行详细说明&#xff1a; 1、冒泡排序&#xff08;Bubble Sort&#xff09;&#xff1a; 工作原理&#xff1a;比较相邻的元素并交换&am…...

链表之“无头单向非循环链表”

目录 ​编辑 1.顺序表的问题及思考 2.链表 2.1链表的概念及结构 2.2无头单向非循环链表的实现 1.创建结构体 2.单链表打印 3.动态申请一个节点 3.单链表尾插 4.单链表头插 5.单链表尾删 6.单链表头删 7.单链表查找 8.单链表在pos位置之前插入x 9.单链表删除pos位…...

一休哥助手网页版如何使用

一休哥助手网页版可以使用GPT4提问了&#xff0c;具体操作流程如下&#xff1a; 1.登录网页版一休哥助手&#xff08;首次打开页面时&#xff0c;初始化久一点&#xff0c;请耐心等一下&#xff09; https://www.fudai.fun 2.登录后就可以使用GPT4了 3.你还可以自定义系统角色…...

个人博客系统测试

文章目录 一、项目介绍二、测试1. 功能测试2. 自动化测试&#xff08;1&#xff09;添加相关依赖&#xff08;2&#xff09;新建包并在报下创建测试类&#xff08;3&#xff09;亮点及难点 一、项目介绍 个人博客系统采用前后端分离的方法来实现&#xff0c;同时使用了数据库来…...

智慧应急的未来:物联网技术引领智慧应急发展新趋势

一、引言 随着社会的快速发展&#xff0c;各类突发事件频繁发生&#xff0c;对社会的安全稳定构成了严重威胁。传统的应急管理模式已难以满足现代社会对安全保障的需求&#xff0c;急需探索新型的应急管理手段。在这个背景下&#xff0c;智慧应急应运而生&#xff0c;以其高效…...

字符串摘要(C语言)

题目描述 给定一个字符串的摘要算法&#xff0c;请输出给定字符串的摘要值。 去除字符串中非字母的符号。如果出现连续字符&#xff08;不区分大小写&#xff09;&#xff0c;则输出&#xff1a;该字符&#xff08;小写&#xff09; 连续出现的次数。如果是非连续的字符&…...

Linux进一步研究权限-----------ACL使用

一、使用情况 1.1、场景: 某个大公司&#xff0c;在一个部门&#xff0c;有一个经理和手下有两个员工&#xff0c;在操控一个Linux项目,项目又分为三期做&#xff0c;然而一期比较重要&#xff0c;经理带着员工做完了&#xff0c;公司就觉得技术难点已经做完攻克了&#xff0…...

剪辑视频调色软件有哪些 剪辑视频软件哪个最好 剪辑视频怎么学 剪辑视频的方法和步骤 会声会影2024 会声会影视频制作教程

看了很多调色教程&#xff0c;背了一堆调色参数&#xff0c;可最终还是调不出理想的效果。别再怀疑自己了&#xff0c;不是你的剪辑技术不行&#xff0c;而是剪辑软件没选对。只要掌握了最基本的调色原理&#xff0c;一款适合自己的视频剪辑软件是很容易出片的。 有关剪辑视频…...

【Linux进阶之路】Socket —— “UDP“ “TCP“

文章目录 一、再识网络1. 端口号2. 网络字节序列3.TCP 与 UDP 二、套接字1.sockaddr结构2.UDP1.server端1.1 构造函数1.2 Init1.3 Run 2.客户端1.Linux2.Windows 3.TCP1. 基本接口2. 客户端3. 服务端1.版本12.版本23.版本34.版本4 三、守护进程尾序 一、再识网络 1. 端口号 在…...

一些用 GPT 翻译的计算机科学/人工智能 PDF 讲义

3D成像.pdf3D成像技术.pdf3D点云分析.pdfAAAI 2019 笔记.pdfCMU 10.708 概率图模型讲义.pdfCMU 15-312 编程语言基础讲义.pdfCMU 15-411 编译器设计讲义.pdfCMU 15-819 同伦类型论讲义.pdfCMU 15-819O 程序分析讲义.pdfCUNY CSci335 软件设计与分析 3 讲义.pdfDixie IT4500 信息…...

重大更新:GPT-4 API 现全面向公众开放!

重大更新&#xff1a;GPT-4 API 现全面向公众开放&#xff01; 在 AIGC&#xff08;人工智能生成内容&#xff09;领域内&#xff0c;我们一直致力于跟踪和分析如 OpenAI、百度文心一言等大型语言模型&#xff08;LLM&#xff09;的进展及其在实际应用中的落地情况。我们还专注…...

【Python笔记-设计模式】对象池模式

一、说明 用于管理对象的生命周期&#xff0c;重用已经创建的对象&#xff0c;从而减少资源消耗和创建对象的开销 (一) 解决问题 主要解决频繁创建和销毁对象所带来的性能开销问题。如数据库连接、线程管理、网络连接等&#xff0c;对象的创建和销毁成本相对较高&#xff0c…...

反序列化 [NPUCTF2020]ReadlezPHP1

打开题目 直接查看源代码 打开源代码发现了个./time.php?source 访问一下 审计代码&#xff1a; 现存在反序列化语句&#xff1a;$ppp unserialize($_GET["data"]);和执行漏洞&#xff1a;echo $b($a); 发现在__destruct()方法里面有 echo $b($a); 这个是php的…...

AI技术那些事儿:揭开潜伏在你生活中的高科技小能手

你有没有发现&#xff0c;现在的生活里有些“看不见”的聪明家伙&#xff0c;它们时时刻刻在帮咱们忙活呢&#xff1f;从早上用语音命令打开窗帘、播报新闻&#xff0c;到晚上喊一声关灯睡觉&#xff0c;这些都离不开人工智能&#xff08;简称AI&#xff09;的助攻。今天咱就掰…...

使用向量数据库pinecone构建应用06:日志系统异常检测 Anomaly Detection

Building Applications with Vector Databases 下面是这门课的学习笔记&#xff1a;https://www.deeplearning.ai/short-courses/building-applications-vector-databases/ Learn to create six exciting applications of vector databases and implement them using Pinecon…...

抽象工厂模式 Abstract Factory

1.模式定义: 提供一个创建一系列相关或互相依赖对象的接口&#xff0c;而无需指定它们具体的类 2. 应用场景: 程序需要处理不同系列的相关产品&#xff0c;但是您不希望它依赖于这些产品的 具体类时&#xff0c; 可以使用抽象工厂 3.优点: 1.可以确信你从工厂得到的产品彼…...

掌握 Android 中的 RecyclerView 优化

掌握 Android 中的 RecyclerView 优化 一、RecyclerView Pool以及何时使用它二、onCreateViewHolder 和 onBindViewHolder三、优化 RecyclerView 的不同方法四、视图无效与请求布局五、ViewHolder模式六、默认的废料和脏视图类型七、结论 RecyclerView 是 Android 中一个功能强…...

Android platform tool中d8.bat不生效

d8.bat因找不到java_exe文件&#xff0c;触发EOF d8.bat中之前代码为&#xff1a; set java_exe if exist "%~dp0..\tools\lib\find_java.bat" call "%~dp0..\tools\lib\find_java.bat" if exist "%~dp0..\..\tools\lib\find_java.bat" …...

WSL安装Ubuntu22.04,以及深度学习环境的搭建

安装WSL 安装 WSL 2 之前&#xff0c;必须启用“虚拟机平台”可选功能。 计算机需要虚拟化功能才能使用此功能。 以管理员身份打开 PowerShell 并运行&#xff1a; dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart下载 Linux 内核更…...