Cassandra 浅析

Cassandra 是一个开源的、分布式的、无中心的、弹性可扩展的、高可用的、容错的、一致性可调的、面向行的数据库,它基于 Amazon Dynamo 的分布式设计和 Google Bigtable 的数据模型,由 Facebook 创建,在一些最流行的网站中得到应用。

Cassandra 可以方便管理分布在很多商业服务器节点上的非常大量的结构化数据,同时提供无单点失效的高可用服务。Cassandra目标是在几百个基础节点上运行(可能分布在不同的数据中心)。在这个规模上,大大小小的组件经常失效。Cassandra对这些失败持久状态的管理方式促使软件系统的可靠性和扩展性依赖这一服务。虽然在许多方面Cassandra类似于一个数据库,并且共享很多设计和相关实现策略,但Cassandra并不支持完整的关系数据模型;相反,它为客户提供了一个支持动态控制数据布局并且格式简单数据模型。Cassandra系统设计目标是:运行在廉价商业硬件上,高写入吞吐量处理,同时又不用以牺牲读取效率为代价。

Facebook 是世界上最大的社交网络平台,高峰时期有数以万计分布在世界各地的服务器为数百万用户提供服务。Facebook 平台在性能、可靠性、效率以及支持持续增长平台所需的高扩展性等方面对操作有着严格的要求。我们的标准操作模式是在由几千个组件组成的基础设施上进行故障处理;任何时候都总有一些小型但非常重要的服务器或网络组件会发生故障。因此,软件系统需要建立处理故障(在这种情况下故障是一种常态而非异常)的机制。为了满足上述可靠性和可扩展性的需要,Facebook 研发了 Cassandra。

相关研究

分布式数据的性能、可用性和耐受性在文件系统和数据库方面已经得到了广泛的研究。同仅支持命名空间的 P2P 存储系统相比,分布式文件系统通常都支持层级结构命名空间。像 Ficus 和 Coda 之类的系统以牺牲一致性为代价来获取高可用性。更新冲突通常使用专门的冲突解决流程来进行管理。Farsite 是一个分布式文件系统,没有使用中央服务器,通过复制来达到高可用性和扩展性。Google 文件系统(GFS)是另一个分布式文件系统,用来管理 Google 内部应用的托管状态。GFS 使用了一种简单的设计,以一个主服务器来存储所有的元数据,其余数据被分成块存储到各个块服务器上。然而 GFS 主服务器现在使用了 Chubby 抽象来进行容错处理。Bayou 是一个分布式关系数据库系统,允许断开连接下的操作并且提供最终数据一致性。在这些系统中 Bayou, Coda 和 Ficus 允许断开连接下的操作并且可以弹性处理网络中断、停电之类的问题。这些系统的冲突解决流程各有差别。例如,Coda 和 Ficus 平台提供系统级别冲突解决方案,Bayou 提供应用级别的解决方案。所有的这些都是为了保证数据的最终一致性。同这些文件系统一样,Dynamo 即使当网络断开的时候也允许读写操作的继续,并且通过不同冲突解决机制(某些是由客户端驱动的)来解决更新冲突。传统复制关系数据库的系统专注于保证复制数据强一致性的问题。虽然强一致性为应用开发者提供了一个方便的编程模型,但是这些系统在扩展性和可用性上却被限制了。这些系统不能够处理网络中断的问题,因为他们通常都提供了强一致性的保证。

Dynamo 是一个 Amazon 的存储系统,用来存储和检索用户的购物车。Dynamo 的 Gossip 基于成员算法来帮助每个节点保持其他的每个几点的信息。

Dynamo可以定义为在大多数单跳请求路由的结构化覆盖。Dynamo 使用向量时钟计划用来检测新的冲突,但偏向于一个客户端解决冲突的机制。在 Dynamo 中的一个写操作同样需要读操作进行向量时间戳的管理。这在系统需要处理高吞吐量的环境中非常受限。Bigtable 提供了结构和数据的分布式,但是依赖于一个分布式文件系统用来做持久化。

Hbase 是一种基于分布式系统的关系型数据库,而 Cassandra 是一个高性能、可靠和可扩展的列存储数据库。它们的主要区别在于数据结构和查询处理方式的不同。HBase 上的查询需要通过网络进行分布式的并行计算,而 Cassandra 则使用本地节点之间的消息传递来完成查询任务。

系统架构

Cassandra 依赖于Dynamo 分布式存储键值系统的一些技术。Dynamo系统中的每个节点都有三个主要组成部分:

  • 在分区的数据集上请求协调
  • 环状成员和故障检测
  • 本地持久化存储引擎

对分区数据集的请求协调是指在 Dynamo 系统中,每个节点都负责处理一部分数据,而这些数据是通过哈希函数进行分区的。当客户端发出请求时,Dynamo 会根据请求中的键值来确定哪个节点负责处理该请求,并将请求转发给相应的节点进行处理。这样,Dynamo 系统就能够通过多个节点协同工作来处理大量的客户端请求,从而实现高吞吐量和低延迟。

Cassandra主要使用前两个集群组件,同时使用基于日志结构合并树(LSM)的存储引擎。特别地,Cassandra 基于 Dynamo 改进了:

  • 使用一致哈希的数据集分区
  • 使用版本化数据和可调一致性的多主(multi-master)复制
  • 通过 gossip 协议进行分布式集群成员和故障检测
  • 商用硬件的增量横向扩展

Cassandra 以这种方式设计,可以满足大规模(PB级数据)关键业务存储要求。

Cassandra 不仅吸收了 Dynamo 论文中的如何做分布式,如何做副本复制,故障容错等方面成功的经验,又吸取了 Google Bigtable 中的 LSM 单机引擎层面精华。

本地持久化

Cassandra 的数据持久化需要依赖本地文件系统。数据用一种高效读取格式存放在硬盘上。出于耐受性和可恢复性考虑,通常写操作将会涉及到提交日志写入并且更新到一个内存数据结构中。写入内存数据结构仅仅在写入提交日志成功后才会进行。我们每台机器上都有个专门磁盘用来提交日志,因为所有写入提交日志是连续的,所以可以最大限度的利用磁盘吞吐量。当内存数据结构大小(根据数据大小和数量计算得出)超过一定阈值,它将转储到磁盘上。这个写操作是在每台机器配备的许多廉价磁盘中的一个上进行的。所有写入操作写入到磁盘都是有序的,并且生成了一个基于行键可进行快速检索的索引。这些索引通常是数据文件在一起持久化的。随着时间的推移,在磁盘上可能会存在很多这样的文件,后台会有一个合并进程将这些文件合并成一个文件。这个进程和 Bigtable 系统中的压缩进程非常相似。

一个典型的读取操作在读取磁盘上文件之前首先将查询内存数据结构。文件是以文件的新旧来进行排序的。当进行磁盘检索时,我们可能需要检索磁盘上的多个文件的关键字。为了避免查找到不包含关键字的文件,我们用布隆过滤器来汇总文件中的关键字,它同样也存储在每个数据文件中并常驻内存。(检索时)首先将咨询布隆过滤器来检查搜索的关键字是否在给定的文件中。一个列簇中的关键字可能会包含很多列。所以当检索的列距离键较远时还需要利用一些特殊的索引。为了防止搜索时搜索磁盘上的每一列,我们维护列索引来帮组我们直接跳到磁盘上所取列的正确块上。由于指定键的列已经被序列化并写入到磁盘,所以我们按照每块 256K 的范围来生成索引。边界的大小是可以配置的,但是我们发现在实际产品负载环境下中,256K 大小工作良好。

数据分区

一致性哈希数据分区

Cassandra 通过使用哈希函数对存储在系统中的所有数据进行分区,实现了横向可扩展性。每个分区都被复制到多个物理节点上,通常跨越故障域,如机架甚至数据中心。由于每个副本都可以独立地接受它所拥有的每个密钥的突变,每个密钥都必须是版本的。在最初的 Dynamo 论文中,确定性的版本和矢量时钟被用来协调对一个键的并发更新,与此不同的是,Cassandra 使用了一个更简单的最后写入获胜的模型,每个突变都有时间戳(包括删除),然后数据的最新版本是 “获胜 “值。从形式上讲,Cassandra 为每条 CQL 行使用一个 Last-Write-Wins Element-Set 无冲突复制数据类型,或 Conflict-free replicated data type,以解决复制集上冲突的突变。

Cassandra 一个重要的设计特性就是持续扩展的能力。这要求动态将数据分区到集群中各个节点(即存储主机)的能力。Cassandra 整个集群上的数据分区用的是一致性哈希,但是使用了保序哈希函数来达到这一点。在一致性哈希算法中,一个散列函数输出范围被当作一个固定的圆形空间或‘环’来对待(即最大散列值之后为最小散列值)。系统中的每一个节点被赋予一个在这一空间内表示其圆环的位置的随机值。每一个数据项通过键来标识,通过散列数据项的键来确定环上的位置,然后分配到圆环上第一个离大于该条目位置最近的节点。这个节点被视为此键的坐标。应用对此键进行特化处理并且 Cassandra 使用它来进行请求路由。因此,每个节点只需对圆环上它与前任节点之间的区域负责。一致性哈希最主要的优点是离开或到达一个节点只会影响期直接毗邻节点,而其他节点不受影响。基础的一致性散列算法面临一些挑战。首先,每个节点圆环上随机位置的分配导致数据和负载分布的不均匀。第二,基础算法无视节点性能的不均匀性。通常解决这个问题有两个方法:一个是将一个节点分配给环中多个位置(就像 Dynamo 的做法),第二种就是对环上的负载信息进行分析,优先路由负载小的节点以减轻负载较重的节点负担。Cassandra 采用后一种方法,因为它能够使得设计和实现易于处理,并且有助于负载均衡做出确定的选择。

在朴素数据哈希中,通常通过将键的哈希模数除以桶数来将键分配给桶。例如,如果您想使用朴素哈希将数据分发到 100 个节点,则可能将每个节点分配到 0 到 100 之间的一个桶,将输入键模数除以 100,并将数据存储在关联的桶中。然而,在这种朴素方案中,添加一个节点可能会使几乎所有映射失效。

Cassandra 则将每个节点映射到连续哈希环上的一个或多个令牌,并通过将键散列到环上然后“沿着”环向一个方向行走来定义所有权,类似于 Chord 算法。一致性哈希与朴素数据哈希的主要区别在于,当要散列到的节点(桶)数量发生变化时,一致性哈希只需移动少量键。

例如,如果我们有一个具有均匀分布的令牌的8节点集群, 和复制因子 (RF) 为 3,然后查找键我们首先对该键进行哈希处理以生成令牌(这只是哈希的 key),然后我们以顺时针的方式“走”环,直到我们遇到三个不同的节点,此时我们已经找到了所有 该密钥的副本。此 8 节点群集示例具有 gRF=3 可以可视化如下:

Cassandra 浅析 2

物理节点与多个令牌

在 Cassandra 中,每个物理节点可以拥有多个令牌,这些令牌在哈希环上占据多个位置。这种方法称为“虚拟节点”,它通过为每个物理节点分配多个令牌来解决不平衡问题。通过允许单个物理节点在环中占据多个位置,我们可以使小集群看起来更大,因此即使添加单个物理节点,我们也可以使其看起来像添加了更多节点,从而在添加甚至单个节点时从更多环邻居那里获取更多较小的数据块。

Cassandra 引入了一些术语来处理这些概念:

  • 主机 ID:单个“物理”节点的唯一标识符,通常位于一个 gEndpoint 处并包含一个或多个 gTokens。
  • 虚拟节点(或 vnode):由同一物理节点拥有的哈希环上的 gToken,具有相同的 gHost ID。

令牌到端点的映射产生了令牌映射,在其中 Cassandra 跟踪哪些环位置映射到哪些物理端点。例如,在下图中,我们可以通过为每个节点分配两个令牌来表示仅使用 4 个物理节点的 8 个节点集群:

Cassandra 浅析 4

每个令牌最多引入2 x(rf -1)令牌环上的其他邻居,这意味着节点故障的组合有更多的组合,我们在某些令牌环中失去了可用性。您拥有的令牌越多,停电的可能性就越高。

整个群集维护操作通常会放慢速度。例如,随着每个节点的令牌数量的增加,群集必须增加的离散维修操作数量。

跨越令牌范围的操作的性能可能会受到影响。

请注意,在Cassandra 2.x中,唯一可用的令牌分配算法是选择随机令牌,这意味着要保持平衡每个节点的默认令牌数必须很高,在256处。共同增加了无法获得的风险。这就是为什么在3.x +中添加了新的确定性令牌分配器,该分配器巧妙地选择令牌,以使环具有最佳平衡,同时需要每个物理节点的令牌数量要少得多。

每个物理节点的多个令牌提供了以下好处:

  • 当添加新节点时,它从环中其他节点接受大约相等数量的数据,从而在整个集群中实现数据均匀分布。
  • 当一个节点被撤销时,它将数据大致均匀地丢失给环中其他成员,再次保持整个集群中数据的均匀分布。
  • 如果一个节点不可用,则查询负载(特别是令牌感知查询负载)会均匀地分布到许多其他节点上。

多主复制

Cassandra 将每个数据分区复制到集群中的许多节点,以保持高可用性和持久性。当发生变化时,协调器对分区键进行散列以确定数据所属的令牌范围,然后根据 Replication Strategy 将突变复制到该数据的副本。

所有复制策略都有复制因子( RF )的概念,它向Cassandra指示分区应该存在多少个副本。例如,使用 RF=3 keyspace,数据将被写入三个不同的副本。副本总是被选择为使得它们是不同的物理节点,这通过在需要时跳过虚拟节点来实现。复制策略还可以选择跳过存在于相同故障域(诸如机架或数据中心)中的节点,使得 Cassandra 集群可以容忍整个机架甚至节点的数据中心的故障。

Cassandra支持可插拔复制策略,该策略确定哪些物理节点充当给定令牌范围的副本。数据的每个键空间都有自己的复制策略。所有生产部署都应使用 NetworkTopologyStrategy ,而 SimpleStrategy 复制策略仅适用于测试尚不了解群集数据中心布局的群集。

NetworkTopologyStrategy 需要为群集中的每个数据中心指定复制因子。即使您的群集只使用单个数据中心,建议使用 NetworkTopologyStrategy 而不是 SimpleStrategy ,以便在需要时更容易将新的物理或虚拟数据中心添加到群集。

还有其它非常方便的复制策略。

数据版本

Cassandra 使用变化时间戳版本控制来保证数据的最终一致性。具体而言,进入系统的所有变化都是利用从客户端时钟提供的时间戳来进行的,或者在没有客户端提供的时间戳的情况下利用从协调器节点的时钟提供的时间戳来进行的。更新根据上次写入成功的冲突解决规则解决。Cassandra 的正确性取决于这些时钟,因此请确保运行正确的时间同步进程,如 NTP。

Cassandra 将单独的突变时间戳应用于 CQL 分区中的每一行的每一列。行通过主键保证是唯一的,并且行中的每一列根据最后写入成功冲突解决方案来解决并发变异。这意味着对分区内不同主键的更新实际上可以在没有冲突的情况下解决!此外,CQL 集合类型(如映射和集合)使用相同的无冲突机制,这意味着映射和集合的并发更新也可以保证解决。

复制副本同步

由于Cassandra中的副本可以独立地接受变化,因此某些副本可能具有比其他副本更新的数据。Cassandra有许多尽力而为的技术来驱动副本的收敛,包括读取路径中的 Replica read repair <read-repair> 和写入路径中的 Hinted handoff <hints> 。

然而,这些技术只是尽力而为,为了保证最终的一致性,Cassandra实现了 anti-entropy repair <repair> ,其中副本在其数据集上计算分层哈希树,称为Merkle树,然后可以在副本之间进行比较,以识别不匹配的数据。像最初的Dynamo论文一样,Cassandra支持完全修复,其中副本散列其整个数据集,创建Merkle树,将它们发送给彼此并同步任何不匹配的范围。

与原始的 Dynamo 论文不同,Cassandra 还实现了子范围修复和增量修复。子范围修复允许 Cassandra 通过创建仅跨越部分数据范围的大量树来提高哈希树的能力(可能降低到单个分区级别)。增量修复允许 Cassandra 只修复自上次修复以来发生更改的分区。

可调整的一致性

Cassandra 通过一致性级别支持一致性和可用性之间的每操作权衡。Cassandra 的一致性级别是Dynamo的 R + W > N 一致性机制的一个版本,其中操作员可以将必须参与读取( R )和写入( W )的节点数量配置为大于复制因子( N )。在 Cassandra 中,您可以从通用一致性级别菜单中选择,这允许操作员在不知道复制因子的情况下选择 R 和 W 行为。通常,当读取一致性级别包含足够的节点以保证与写入一致性级别的仲裁交集时,写入将对后续读取可见。

还允许很多不同的一致性级别。

故障检测

Cassandra 通过使用 Gossip 来实现分布式集群成员身份和故障检测。Gossip 是一种用于在分布式系统中传播节点信息的算法。在 Cassandra 中,每个节点都会定期与其他节点通信,以交换关于集群中其他节点的信息。这些信息包括节点的状态(如是否在线)、令牌分配情况以及其他元数据。

当一个节点与其他节点通信时,它会将自己所知道的关于集群中所有节点的信息发送给对方。接收到信息的节点会将其与自己所知道的信息进行比较,并更新自己的信息。这样,每个节点都能够通过与其他节点通信来获取关于集群中所有节点的最新信息。

如果一个节点在一段时间内未能与其他节点通信,则该节点会被标记为不可用,并且集群中的其他节点会停止将请求转发给该节点。这样,Cassandra 就能够快速检测到故障并将请求重新路由到可用的副本上,从而保证了系统的高可用性。

Gossip 是形成环成员资格的基础,但故障检测器最终决定节点是 UP 还是 DOWN 。Cassandra 中 的每个节点都运行 Phi Accrual Failure Detector 的一个变体,其中每个节点都在不断地独立决定其对等节点是否可用。该决定主要基于接收到的心跳状态。例如,如果一个节点在一定时间内没有看到来自节点的心跳增加,故障检测器就会“定罪”该节点,此时 Cassandra 将停止向其路由读取(写入通常会写入提示)。如果/当节点再次开始心跳时,Cassandra 将尝试联系并连接,如果它可以打开通信通道,它将标记该节点为可用。

商业上的扩展不重要,就不写了。

总结

Cassandra 的数据模型与传统的关系型数据库(RDBMS)有很大的不同,它没有固定的表结构,也没有预定义的约束和索引。Cassandra 的数据模型更加灵活和动态,可以根据业务需求随时添加或删除列,也可以支持复杂的数据类型,如列表、集合、映射等。但是,这种灵活性也带来了一些缺点,例如不支持联合查询、聚合、事务等等。在使用 Cassandra 时,需要根据应用场景进行合理的数据建模,并尽量避免产生大量稀疏或重复的数据。

Cassandra 是一种最终一致性(eventual consistency)的数据库,这意味着在某些情况下,不同节点上可能会存在不同版本的数据副本,并且需要一段时间才能达到一致状态。Cassandra 使用时间戳来解决数据冲突,并且允许用户在读写操作时指定不同级别的一致性要求。例如:

  • 读操作可以指定 ONE、QUORUM、ALL 等级别,表示至少需要从一个、过半数或所有节点读取到最新版本的数据才返回结果。
  • 写操作可以指定 ANY、ONE、QUORUM、ALL 等级别,表示至少需要向一个、过半数或所有节点写入成功才返回结果。

Cassandra 的最终一致性机制与强一致性(strong consistency)的数据库有很大的差异,它可以提供更高的可用性和可扩展性,并且适合处理海量并发请求。但是,这种机制也带来了一些缺点像是不能保证实时读取到最新版本的数据,在某些场景下可能会导致业务逻辑出错,等等。

本文正在参加「金石计划」

作者:Andy_Qin
链接:https://juejin.cn/post/7213651072144769085
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文内容由互联网用户自发贡献,该文观点仅代表作者本人。商机网仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 tenspace2022@163.com 举报,一经查实,本站将立刻删除。 本文链接:https://www.315965.com/n/54058.html 聚才发 母婴好物

(0)
上一篇 2023年4月9日 下午1:12
下一篇 2023年4月9日 下午1:13

相关推荐

  • cad教程入门基础免费(cad入门基础知识教程)

    CAD入门这个范围实在是太广了,如果简单理解为,掌握大部分绘图、修改命令的用法,这个倒是可以考虑去整理。 那今天,我们就一点点,从最简单的命令开始学起。 1、直线命令,快捷键L 执行命令后鼠标左键确定起点,再次点击鼠标左键确定终点。 注意:确定起点后,命令行提示了另外两种方式确定终点,角度A和长度L,就是说你可以通过输入A利用指定角度画出你要的直线,或者长度…

    2023年4月9日 下午1:12
    17
  • 象棋教程初学者(中国象棋教程入门篇)

    上篇文章已经介绍了象棋入门棋子该如何走法,今天分享一下入门初学者该如何下象棋。 象棋布局非常多,先手有中炮、先马局、飞相局、士角炮、过宫炮等,那么作为新手应该先学哪个呢?该如何走呢? 新手必先学的为中炮局,中炮攻势猛,思路清晰,是新手玩家用的最多的布局走法。若精通后,三天即可让人刮目相看了。 中炮开局 中炮走法口诀: 起炮在中宫,观棋气象雄。 马常守中卒,士…

    2023年4月9日 下午1:12
    17
  • word教程零基础教程(新手如何使用word文档)

    Hi!今天专门出一期,零基础也能快速掌握的“word”使用晓技巧,即便你已经是word“老司机”也推荐你一同往下看看哦! 虽然这些功能没有“花里胡哨”的复杂操作,但重实用性上看,妥妥是许多人日常需要用到的! (PS:结尾有惊喜哦!) 01、查找与替换 “查找与替换”作为word中有个比较基础的功能,虽然看起来平平无奇,但实际在检查文章,纠正用词,快速处理空格…

    2023年4月9日 下午1:12
    17
  • 二阶魔方教程新手公式(二阶魔方教程新手公式图解)

    面先法分为三步。首先拼好一面(任意颜色,本文以白色为例。)再拼好已拼好面的对面(如:绿对蓝 红对橙 白对黄)。当然在学习前要知道各个字母公式的含义。 R=Right (右面顺时针旋转90度) R 的含义 与R相对的是L L=Left(左面顺时针旋转90度) L 的含义 还有F,Front(前面顺时针旋转90度) F 的含义 与F相对的是B B=Back(后面…

    2023年4月9日 下午1:12
    17
  • 让我们看看jQuery 3.0有什么新玩意

    作为迄今为止最流行的 JavaScript 库,jQuery 为无数的 Web 开发者带来了福利。 jQuery 从 2006 年诞生至今,已经被许许多多的 Web 开发者运用在项目中,极大地方便了开发。 时间回到 2015 年 7 月, jQuery 3.0 发布了第一个测试版———这是长久以来的一次重要发布。让我们一起来看看 jQuery 中有什么新的东…

    2023年4月9日 下午1:12
    17
  • tp link路由器设置教程(tplink怎么设置wifi速度最快)

    网络时代,没有WiFi怎么活?手机流量这么贵,恐怕不少朋友只有到了有WiFi覆盖的区域,才敢肆意追剧,抓紧时间离线下载吧。那么对于无线小白用户来说,如何快速搭建家里的WiFi平台呢?下面就以流行的tp link无线路由器为例,向初级用户们分享下无线路由器的设置方法吧。 tp link无线路由器设置 tp link无线路由器设置|登陆篇 先将tp link无线…

    2023年4月9日 下午1:12
    17
  • 中国经济复苏步伐不断加快,各行各业都渐渐“忙了起来”

    今年一季度以来,我国经济开局良好,复苏的步伐不断加快。景区游人如织、交通运行繁忙,多措并举之下,各行各业都渐渐“忙起来”“热起来”了。我们先来看一看交通方面。

    2023年4月3日
    25
  • 还没用熟 TypeScript 社区已经开始抛弃了

    根据 rich-harris-talks-sveltekit-and-whats-next-for-svelte 这篇文章报道, Svelte 计划要把代码从 TS 换到 JS 了。 The team is switching the underlying code from TypeScript to JavaScript. That and the up…

    2023年4月9日 下午1:12
    17
  • App制作教程步骤(app制作入门教程)

    一、前言 移动web时代,手机的兴起使得大部分在手机上的应用开发变得如火如荼,然而传统的app开发需要掌握的知识点繁多,开发周期特别漫长,为了解决这个问题,webapp应运而生,它使得app开发的难度大幅度降低,只要你懂前端就可以开发app;然而由于技术的更迭,不光出现了app,还有小程序以及一些网站,于是,很多人瞄准了多端应用市场,所谓多端指的是一套代码多…

    2023年4月9日 下午1:12
    17
  • 幻灯片制作流程(幻灯片制作教程视频小白系列课程)

    正如工厂流水线生产汽车一样,PPT 制作同样存在流程,遵循合适的方法,不仅能够提高幻灯片的制作效率,更能够让你更加合理的分配 PPT 制作时间。 那么,从0到1.一套幻灯片是怎么被制作出来的呢?我在这里给大家分享一下我的个人经验。 假如说咱们现在就要做一套 关于 「PPT 制作流程」的幻灯片 。启动时都要做点啥呢? 1/ 首先,在我们开始动笔写文字稿之前,我…

    2023年4月9日 下午1:12
    17