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

分布式协议与算法——Paxos算法

目录

    • Paxos算法
      • Basic Paxos算法
        • 三种角色
        • 如何达成共识(协商过程)
        • 小结:
      • Multi-Paxos算法
        • 关于 Multi-Paxos 的思考
        • 领导者
        • 优化Basic Paxos
        • Chubby 的 Multi-Paxos 实现
        • 小结
      • 参考

Paxos算法

Paxos论文 Paxos Made Simple 、author:Leslie Lamport(兰伯特)

Paxos算法是一种共识算法,一些常用的共识算法都是基于它改进的,如Fast Paxos算法、Cheep Paxos算法、Raft算法等。Paxos算法包含2个部分:

  1. Basic Paxos算法,描述的是多节点之间如何就某个值(提案 value)达成共识。
  2. Multi-Paxos算法,描述的是执行多个Basic Paxos实例,就一系列值达成共识。

Basic Paxos算法

实现一个分布式集群,这个集群由多个组成。现有多个客户端(客户端1、客户端2)访问这个集群,试图创建同一个只读变量(如X),客户端1试图创建值为3的X,客户端2试图创建值为7的X。那如何达成共识,实现各节点上X值的一致呢?使用Paxos算法

Paxos算法中有一些独有而且比较重要的概念:提案、准备请求、接受请求、角色等。其中角色是对Basix Paxos中最核心三个功能的抽象。

三种角色

在Basic Paxos中,有提议者(Proposer)、接受者(Acceptor)、学习者(Learner)三种角色。

  • 提议者:提议一个值,用于投票表决。在绝大多数场景下,集群中收到客户端的请求的节点是提议者(而不是客户端作为提议者),这样做的好处是对业务代码没有入侵性(不需要在业务代码中实现算法逻辑)。
  • 接受者:对每个提议的值进行投票、并存储接受的值。一般来说,集群中所有节点都在扮演接受者的角色,参与共识协商,并接受和存储数据。
  • 学习者:被告知投票的结果,接受达成共识的值,存储保存,不参与投票的过程。一般来说,学习者是数据备份的节点,被动地接受数据,容灾备份。

一个节点可以身兼多种角色。例如一个3节点的集群,1个节点收到了客户端的请求,那么该节点将作为提议者发起二阶段提交,然后这个节点和另外两个节点一起作为接受者进行共识协商。

这三种角色,本质上代表的是三种功能:

  • 提议者代表的是接入和协调功能,收到客户端请求后,发起二阶段提交,进行共识协商。
  • 接受者代表投票协商和存储数据,对提议的值进行投票,并接受达成共识的值,存储保存。
  • 学习者代表存储数据,不参与共识协商,只接受达成共识的值,存储保存。

如何达成共识(协商过程)

在Basic Paxos中,使用提案代表一个提议。在提案中,除了提案编号,还包含了提议值。如[n,v]表示一个提案,其中n为提案编号,v为提议值。

假设客户端1的提案编号为1,客户端2的提案编号为5;节点A、B先收到来自客户端1的准备请求,节点C先收到来自客户端2的准备请求。

提议者 一般由收到客户端请求的节点担任,这里为了便于理解,将客户端作为了提议者。你可以这样理解:每个客户端对应一个节点,其所对应的节点即担任提议者又担任接受者。所以下述的客户端1、2可以看成节点A、C。

准备(Prepare)阶段

第一个阶段是准备阶段。首先客户端1、2作为提议者,分别向所有接受者发送包含提案编号的准备请求。
image-20230807000539518

在准备请求的时候不需要指定提议的值,只需要携带提案编号。

随后,节点A、B收到提案编号为1的准备请求,节点C收到提案编号为5的准备请求,进行以下处理。

  • 由于之前没有通过任何提案,所以节点 A、B 将返回一个 “尚无提案”的响应。也就是说节点 A 和 B 在告诉提议者,我之前没有通过任何提案呢,并承诺以后不再响应提案编号小于等于 1 的准备请求,不会通过编号小于 1 的提案。
  • 节点 C 也是如此,它将返回一个 “尚无提案”的响应,并承诺以后不再响应提案编号小于等于 5 的准备请求,不会通过编号小于 5 的提案。
    image-20230807000600904

随后,当节点A、B收到提案编号为5的准备请求,节点C收到提案编号为1的准备请求的时候,进行以下处理。

  • 当节点 A、B 收到提案编号为 5 的准备请求的时候,因为提案编号 5 大于它们之前响应的准备请求的提案编号 1,而且两个节点都没有通过任何提案,所以它将返回一个 “尚无提案”的响应,并承诺以后不再响应提案编号小于等于 5 的准备请求,不会通过编号小于 5 的提案。
  • 当节点 C 收到提案编号为 1 的准备请求的时候,由于提案编号 1 小于它之前响应的准备请求的提案编号 5,所以丢弃该准备请求,不做响应。
    image-20230807000621641

🌟🌟🌟

如果节点收到准备请求中的提案编号,大于之前响应的准备请求的提案编号,并且已经通过了之前的提案,那么接受者会在请求的响应中包含已经通过的最大编号的提案信息(也就是说接受者会将其通过的最大编号的提案信息发送给提议者),而不是“尚无提案”的响应。

接受(Accept)阶段

第二个阶段也就是接受阶段,首先客户端 1、2 在收到大多数节点的准备响应之后,会分别发送接受请求:

当客户端 1 收到**大多数的接受者(节点 A、B)**的准备响应后,根据响应中提案编号最大的提案的值,设置接受请求中的值。因为该值在来自节点 A、B 的准备响应中都为空(也就是“尚无提案”),所以就把自己的提议值 3 作为提案的值,发送接受请求[1, 3]。

当客户端 2 收到大多数的接受者的准备响应后(节点 A、B 和节点 C),根据响应中提案编号最大的提案的值,来设置接受请求中的值。因为该值在来自节点 A、B、C 的准备响应中都为空(也就是图 5 和图 6 中的“尚无提案”),所以就把自己的提议值 7 作为提案的值,发送接受请求[5, 7]。
image-20230807000634385

当节点 A、B、C 收到接受请求[1, 3]的时候,由于提案的提案编号 1 小于三个节点承诺能通过的提案的最小提案编号 5,所以提案[1, 3]将被拒绝。

当节点 A、B、C 收到接受请求[5, 7]的时候,由于提案的提案编号 5 不小于三个节点承诺能通过的提案的最小提案编号 5,所以就通过提案[5, 7],也就是接受了值 7,三个节点就 X 值为 7 达成了共识。
image-20230807000704484

🌟🌟🌟

如果节点的准备响应中包含了提案信息而不是“尚无提案”,那么提议者会将响应的提案编号最大的提案所对应的值,作为接受请求中的值,而不是将自己的提议值作为提案值。这样就保证了大多数节点就某个值达成共识后,这个值就不会改变了,哪怕有新的提案这个值也不会改变了。

如果集群中有学习者,当接受者通过一个提案时,就通知给所有学习者。当学习者发现大多数的接受者都通过了提案,那么它也通过该提案,接受该提案的值。

除了共识之外,Basic Paxos还实现了容错,这个容错能力,源自**“大多数”**的约定(大多数接受者准备响应)。可以理解为:当少于一半的节点出现故障的时候,共识协商仍能正常工作。

🤔🤔🤔

如果节点 A、B 已经通过了提案[5, 7],节点 C 未通过任何提案,那么当客户端 3 提案编号为 9 时,通过 Basic Paxos 执行“SET X = 6”,最终三个节点上 X 值是多少呢?

准备阶段:

当节点A、B收到提案编号为9的准备请求的时候,因为提案编号9大于之前响应的准备请求的提案编号5,并且这两个节点已经通过了之前的提案[5,7],接受者A、B会在准备请求的响应中,包含已经通过的最大编号的提案信息[5,7],并承诺以后不再响应提案编号小于9,不会通过编号小于9的提案;由于节点C之前没有通过任何提案,所以节点C将返回一个“尚无提案”的响应,并承诺以后不再响应议案编号小于等于9的准备请求,不会通过编号小于9的提案。

接受阶段:

当客户端3收到大多数的接受者的准备请求后(节点A、B和C),根据响应中提案编号最大的提案的值,来设置请求的值,即来自A、B节点的准备响应的提案[5,7]。因此就把A、B响应值7作为提案的值,发送接受请求[9,7]。当节点A、B、C收到接受请求[9,7]后,由于提案的提案编号不小于三个节点承诺的能通过的提案的最小提案编号9,所以就通过提案[9,7]。三个节点就达成了共识。最后的值为7。

大多是值就某个节点达成共识了,值就不变了。哪怕有新的提案,这个值也能保证不再变了。

小结:

  1. Basic Paxos 是通过二阶段提交的方式来达成共识的。二阶段提交是达成共识的常用方式。
  2. 除了共识,Basic Paxos 还实现了容错,在少于一半的节点出现故障时,集群也能工作。它不像分布式事务算法那样,必须要所有节点都同意后才提交操作,因为“所有节点都同意”这个原则,在出现节点故障的时候会导致整个集群不可用。
  3. 本质上而言,提案编号的大小代表着优先级,你可以这么理解,根据提案编号的大小,接受者保证三个承诺,具体来说:
    • 如果准备请求的提案编号,小于等于接受者已经响应的准备请求的提案编号,那么接受者将承诺不响应这个准备请求;
    • 如果接受请求中的提案的提案编号,小于接受者已经响应的准备请求的提案编号,那么接受者将承诺不通过这个提案;
    • 如果接受者之前有通过提案,那么接受者将承诺,会在准备请求的响应中,包含已经通过的最大编号的提案信息。

Multi-Paxos算法

Basic Paxos 只能就单个值(Value)达成共识,一旦遇到为一系列的值实现共识的时候,它就不管用了。可以通过多次执行 Basic Paxos 实例(比如每接收到一个值时,就执行一次 Basic Paxos 算法)实现一系列值的共识。

Multi-Paxos 是一种思想,不是算法。而 Multi-Paxos 算法是一个统称,它是指基于 Multi-Paxos 思想,通过多个 Basic Paxos 实例实现一系列值的共识的算法(比如 Chubby 的 Multi-Paxos 实现、Raft 算法等)。

关于 Multi-Paxos 的思考

Basic Paxos 是通过二阶段提交来达成共识的。在第一阶段,也就是准备阶段,接收到大多数准备响应的提议者,才能发起接受请求进入第二阶段(也就是接受阶段)
image-20230805155046671

如果我们直接通过多次执行 Basic Paxos 实例,来实现一系列值的共识,就会存在这样几个问题:

  • 如果多个提议者同时提交提案,可能出现因为提案编号冲突,在准备阶段没有提议者接收到大多数准备响应,协商失败,需要重新协商。
  • 2 轮 RPC 通讯(准备阶段和接受阶段)往返消息多、耗性能、延迟大。

可以通过引入领导者优化 Basic Paxos 执行来解决上面的两个问题。

领导者

领导者节点作为唯一提议者,这样就不存在多个提议者同时提交提案的情况,也就不存在提案冲突的情况了。
image-20230805155410820

在论文中,并没有说如何选举领导者,需要我们在实现 Multi-Paxos 算法的时候自己实现如在 Chubby 中,领导者节是通过执行 Basic Paxos 算法,进行投票选举产生的。

优化Basic Paxos

可以采用**“当领导者处于稳定状态时,省掉准备阶段,直接进入接受阶段”**这个优化机制,优化 Basic Paxos 执行。也就是说,领导者节点上,序列中的命令是最新的,不再需要通过准备请求来发现之前被大多数节点通过的提案,领导者可以独立指定提案中的值。这时,领导者在提交命令时,可以省掉准备阶段,直接进入到接受阶段:
image-20230805155543344

和重复执行 Basic Paxos 相比,Multi-Paxos 引入领导者节点之后,因为只有领导者节点一个提议者,只有它说了算,所以就不存在提案冲突。另外,当主节点处于稳定状态时,就省掉准备阶段,直接进入接受阶段,所以在很大程度上减少了往返的消息数,提升了性能,降低了延迟。

💡💡💡

感觉Multi-Paxos 的实现需要执行多轮的 Basic Paxos,但Multi-Paxos 对每一轮 Basic Paxos进行了上述优化。

Chubby 的 Multi-Paxos 实现

  • 通过引入主节点,实现了论文中提到的领导者(Leader)节点的特性。也就是说,主节点作为唯一提议者,这样就不存在多个提议者同时提交提案的情况,也就不存在提案冲突的情况了。主节点是通过执行 Basic Paxos 算法,进行投票选举产生的,并且在运行过程中,主节点会通过不断续租的方式来延长租期(Lease)。
  • Chubby 中实现了论文提到的,“当领导者处于稳定状态时,省掉准备阶段,直接进入接受阶段”这个优化机制。
  • 在 Chubby 中,实现了成员变更(Group membership),以此保证节点变更的时候集群的平稳运行。
  • 在 Chubby 中,为了实现了强一致性,读操作也只能在主节点上执行。 也就是说,只要数据写入成功,之后所有的客户端读到的数据都是一致的。(所有的读请求和写请求都由主节点来处理)

💡💡💡

读写请求都在主节点上了,主节点的压力就很大了呀!!!

小结

  1. 兰伯特提到的 Multi-Paxos 是一种思想,不是算法,而且还缺少算法过程的细节和编程所必须的细节,比如如何选举领导者等,这也就导致了每个人实现的 Multi-Paxos 都不一样。而 Multi-Paxos 算法是一个统称,它是指基于 Multi-Paxos 思想,通过多个 Basic Paxos 实例实现一系列数据的共识的算法(比如 Chubby 的 Multi-Paxos 实现、Raft 算法等)。
  2. Chubby 实现了主节点(也就是兰伯特提到的领导者),也实现了兰伯特提到的 “当领导者处于稳定状态时,省掉准备阶段,直接进入接受阶段” 这个优化机制,省掉 Basic Paxos 的准备阶段,提升了数据的提交效率,但是所有写请求都在主节点处理,限制了集群处理写请求的并发能力,约等于单机。
  3. 在 Chubby 的 Multi-Paxos 实现中,也约定了“大多数原则”,也就是说,只要大多数节点正常运行时,集群就能正常工作,所以 Chubby 能容错(n - 1)/2 个节点的故障。
  4. 本质上而言,“当领导者处于稳定状态时,省掉准备阶段,直接进入接受阶段”这个优化机制,是通过减少非必须的协商步骤来提升性能的。这种方法非常常用,也很有效。比如,Google 设计的 QUIC 协议,是通过减少 TCP、TLS 的协商步骤,优化 HTTPS 性能。

参考

  • 分布式协议与算法实战 学习笔记

相关文章:

分布式协议与算法——Paxos算法

目录 Paxos算法Basic Paxos算法三种角色如何达成共识(协商过程)小结: Multi-Paxos算法关于 Multi-Paxos 的思考领导者优化Basic PaxosChubby 的 Multi-Paxos 实现小结 参考 Paxos算法 Paxos论文 Paxos Made Simple 、author:Lesli…...

Spring中的Websocket身份验证和授权

目录 一、需要了解的事项二、依赖三、WebSocket 配置3.1 、简单的消息代理3.2 、Spring安全配置 一、需要了解的事项 http和WebSocket的安全链和安全配置是完全独立的。SpringAuthenticationProvider根本不参与 Websocket 身份验证。将要给出的示例中,身份验证不会…...

【果树农药喷洒机器人】Part7:静态PWM变量喷药实验

📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...

C++ 网络编程项目fastDFS分布是文件系统(一)

目录 1.项目架构图 1. 项目架构图 1.1 一些概念 1.2 项目架构图 2. 分布式文件系统 2.1 传统文件系统 2.2 分布式文件系统 3. FastDFS 3.1 fastDFS介绍 3.2 fastDFS安装 3.3 fastDFS配置文件 3.4 fastDFS的启动 4. fastDFS状态检测 4.1 对file_id的解释 4. 2上传…...

PoseiSwap 开启“Poseidon”池,治理体系或将全面开启

PoseiSwap 曾在前不久分别以 IDO、IEO 的方式推出了 POSE 通证,但 PoseiSwap DEX 中并未向除 Zepoch 节点外的角色开放 POSE 资产的交易。而在前不久,PoseiSwap 推出了全新的“Poseidon”池,该池将向所有用户开放,并允许用户自由的…...

【C/C++】重载运算符特性

重载运算符是 C 中的一个重要特性,它允许程序员自定义类类型的运算符行为。重载运算符的使用场景包括: 使类类型的对象能够像内置类型一样进行运算:例如,可以重载加号运算符,使两个对象相加时能够像两个整数相加一样。…...

HTML+JavaScript构建一个将C/C++定义的ANSI字符串转换为MASM32定义的DWUniCode字符串的工具

公文一键排版系统基本完成,准备继续完善SysInfo,增加用户帐户信息,其中涉及到Win32_Account结构,其C定义如下: [Dynamic, Provider("CIMWin32"), UUID("{8502C4CC-5FBB-11D2-AAC1-006008C78BC7}"…...

24届近3年南京信息工程大学自动化考研院校分析

今天给大家带来的是南京信息工程大学控制考研分析 满满干货~还不快快点赞收藏 一、南京信息工程大学 学校简介 南京信息工程大学位于南京江北新区,是一所以大气科学为特色的全国重点大学,由江苏省人民政府、中华人民共和国教育部、中国气…...

【LeetCode】1572.矩阵对角线元素的和

题目 给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例 1: 输入:mat [[1,2,3],[4,5,6],[7,8,9]] 输出:25 解释:对角线的和为&a…...

2023-08-08 Ubuntu 挂载U盘 fdisk -l 、sudo mount /dev/sdb1 /mnt/mydisk

一、基本命令 1、插入U盘,查看U盘是否被系统识别: 打开终端,输入: sudo fdisk -l 查看系统是否识别U盘,如果识别,会显示U盘的相关信息,如果没有识别,则说明系统没有识别U盘。 2…...

make/makefile/cmake/nmake

最近,有没有被make、cmake、makefile... ... 这些东西绕晕了,看看下面的文章,也许就可以理解清楚了。 1. gcc 它是GNU Compiler Collection(就是GNU编译器套件),也可以简单认为是编译器,它可以…...

实用的开源应用全新开源源码Vue3+TS的前后台分离的开发平台源码开源技术社区平台

开源全新开源源码Vue3TS的前后台分离的开发平台源码。创意、新奇、有趣、实用的开源应用、系统、软件、硬件及技术,一个探索、发现、分享、使用与互动交流的开源技术社区平台。致力于打造活力开源社区,共建开源新生态! 功能简介 个人办公&a…...

C++复习笔记——primer第五版

文章目录 一、引用和指针1.引用2.指针2.1利用指针访问对象2.2指针的值或指针所指对象的值的改变 3.赋值和指针4.指向指针的引用 二、String1.初始化String对象的方式2. string对象上的操作3.使用getline读取一整行4.字面值和字符串相加5.使用for循环改变字符串中的字符 三、Vec…...

ElasticSearch:项目实战(2)

ElasticSearch: 项目实战 (1) 需求&#xff1a; 新增文章审核通过后同步数据到es索引库 1、文章服务中添加消息发送方法 在service层文章新增成功后&#xff0c;将数据通过kafka消息同步发送到搜索服务 Autowiredprivate KafkaTemplate<String,String> kafkaTemplate;/…...

Eleastisearch5.2.2利用镜像迁移构建实例后ES非健康状态

正常迁移完成后启动服务&#xff0c;查看ES非健康状态 此时观察ES集群状态&#xff1a;curl -XGET -u elastic:xxx localhost:9200/_cluster/health?pretty 注意到"active_shards_percent_as_number" : 88.8888 该项的值不产生变化;集群状态"status" : “…...

sealos安装k8s

一、前言 1、我前面文章有写过使用 kubeadm 安装的方式&#xff0c;大家可以去参考 &#xff08;二&#xff09;k8s集群安装&#xff0c;有一系列的k8s文章说明 2、安装k8s的方式有很多 kubeadmsealoskubespray等等 3、关于sealos来安装 k8s &#xff0c;也是非常建议大家去…...

经典贪吃蛇游戏 - 用 C 语言实现控制台版

在本篇博客中&#xff0c;我们将一起来实现经典的贪吃蛇游戏&#xff0c;使用 C 语言编写&#xff0c;并在控制台中运行。这个小游戏会让你回忆起童年的经典游戏体验。我们将从游戏的初始化开始&#xff0c;逐步实现游戏的各个功能&#xff0c;包括蛇的移动、食物的生成、得分的…...

安灯Andon系统的应用与优势

安灯系统是一款与硬件相结合&#xff0c;实时了解机台与工位状态&#xff0c;让异常的信息得到快速、高效的解决的系统软件&#xff0c;同时记录每次异常报警的种类、响应时间和处理问题用时&#xff0c;提供改善生产管理和人员考核的数据参考&#xff0c;实现透明、快速的生产…...

2023年的C++基础笔记

C 基本语法 对象 - 对象具有状态和行为。例如&#xff1a;一只狗的状态 - 颜色、名称、品种&#xff0c;行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说&#xff0c;一个方法表示一种行为。一个类可以包含多个…...

综合能源系统(6)——综合能源综合评估技术

综合能源系统关键技术与典型案例  何泽家&#xff0c;李德智主编 综合能源系统是多种能源系统非线性耦合的、多时间与空间尺度耦合的“源-网-荷一储”一体化系统&#xff0c;通过能源耦合、多能互补&#xff0c;能够实现能源的高效利用&#xff0c;并提高新能源的利用水平。对…...

pygame开发的坦克大战

使用Python和Pygame开发的精美坦克大战游戏。这个游戏包含玩家控制的坦克、敌方坦克、各种障碍物、爆炸效果和完整的游戏机制。 游戏说明 这个坦克大战游戏包含以下功能&#xff1a; 游戏特点 玩家控制&#xff1a;使用方向键移动坦克&#xff0c;空格键射击 敌人AI&#x…...

构建 MCP 服务器:第 2 部分 — 使用资源模板扩展资源

该图像是使用 AI 图像创建程序创建的。 这个故事是在多位人工智能助手的帮助下写成的。 这是构建MCP 服务器教程&#xff08;共四部分&#xff09;的第二部分。在第一部分中&#xff0c;我们使用基本资源创建了第一个 MCP 服务器。现在&#xff0c;我们将使用资源模板扩展服务…...

Kafka 快速上手:安装部署与 HelloWorld 实践(一)

一、Kafka 是什么&#xff1f;为什么要学&#xff1f; ** 在大数据和分布式系统的领域中&#xff0c;Kafka 是一个如雷贯耳的名字。Kafka 是一种分布式的、基于发布 / 订阅的消息系统&#xff0c;由 LinkedIn 公司开发&#xff0c;后成为 Apache 基金会的顶级开源项目 。它以…...

计算机网络领域所有CCF-A/B/C类期刊汇总!

本期小编统计了【计算机网络】领域CCF推荐所有期刊的最新影响因子&#xff0c;分区、年发文量以及投稿经验&#xff0c;供大家参考&#xff01; CCF-A类 1 IEEE Journal on Selected Areas in Communications 【影响因子】13.8 【期刊分区】JCR1区&#xff0c;中科院1区TOP …...

【Fiddler抓取手机数据包】

Fiddler抓取手机数据包的配置方法 确保电脑和手机在同一局域网 电脑和手机需连接同一Wi-Fi网络。可通过电脑命令行输入ipconfig查看电脑的本地IP地址&#xff08;IPv4地址&#xff09;&#xff0c;手机需能ping通该IP。 配置Fiddler允许远程连接 打开Fiddler&#xff0c;进入…...

服务器租用:高防CDN和加速CDN的区别

CDN全称为内容分发网络&#xff0c;其主要的作用原理能够加快网站的数据传输的速度&#xff0c;随着技术的快速发展&#xff0c;CDN也分为高防CDN和加速CDN两种不同的类型&#xff0c;本文将为大家介绍一下高防CDN和加速CDN两者之间的区别有哪些&#xff1f; 高防CDN能够有效抵…...

<2>-MySQL库的操作

目录 一&#xff0c;创建数据库 二&#xff0c;查看字符集和校验规则 三&#xff0c;修改数据库 四&#xff0c;删除数据库 五&#xff0c;备份和恢复数据库 六&#xff0c;查看连接 一&#xff0c;创建数据库 创建一个名为bin_db的数据库&#xff0c;并设置字符集为utf8…...

文档处理组件Aspose.Words 25.5全新发布 :六大新功能与性能深度优化

在数字化办公日益普及的今天&#xff0c;文档处理的效率与质量直接影响到企业的运营效率。Aspose.Words 作为业界领先的文档处理控件&#xff0c;其最新发布的 25.5 版本带来了六大新功能和多项性能优化&#xff0c;旨在为开发者和企业用户提供更强大、高效的文档处理能力。 六…...

C#中的路由事件(Routed Events)

路由事件的基本概念 路由事件是WPF中特有的事件系统&#xff0c;它允许事件在可视化树中"路由"传递&#xff0c;具有以下特点&#xff1a; 事件路由方向&#xff1a; 冒泡(Tunneling)&#xff1a;从事件源向根元素传递 隧道(Bubbling)&#xff1a;从根元素向事件源…...

STM32:CAN总线精髓:特性、电路、帧格式与波形分析详解

声明&#xff1a;此博客是我的学习笔记&#xff0c;所看课程是江协科技的CAN总线课程&#xff0c;知识点都大同小异&#xff0c;我仅进行总结并加上了我自己的理解&#xff0c;所引案例也都是课程中的案例&#xff0c;希望对你的理解有所帮助&#xff01; 知识点1【CAN总线的概…...