分布式数据库难题(四):单机事务

2023-05-16

1. ACID的含义 

     在数据库中,“事务”是由多个操作构成的序列。1970 年詹姆斯 · 格雷(Jim Gray)提出了事务的 ACID 四大特性,将广义上的事务一致性具化到了原子性、一致性、隔离性和持久性这 4 个方面。我们先来看一下他在 Transaction Processing Concepts and Techniques 中给出的定义:

  • 原子性:事务中的所有变更要么全部发生,要么一个也不发生。
  • 隔离性:多事务并行执行所得到的结果,与串行执行(一个接一个)完全相同。
  • 持久性:一旦事务提交,它对数据的改变将被永久保留,不应受到任何系统故障的影响。
  • 一致性:事务要保持数据的完整性,即数据库处于应用程序所期待的“预期状态”。

    虽然 ACID 名义上并列为事务的四大特性,但它们对于数据库的重要程度并不相同。 

   

(1)原子性

    数据库区别于其他存储系统的重要标志。在单体数据库时代,原子性问题已经得到妥善解决,但随着向分布式架构的转型,在引入不可靠的网络因素后,原子性又成为一个新的挑战。要在分布式架构下支持原子性并不容易,所以不少 NoSQL 产品都选择绕过这个问题,聚焦到那些对原子性不敏感的细分场景。例如,大名鼎鼎的 Google BigTable 甚至是不支持跨行事务的。但是,这种妥协也造成了 NoSQL 的通用性不好。分布式数据库是在分布式架构上实现的关系型数据库,那么就必须支持事务,首先就要支持原子性。原子性,在实现机制上较为复杂,目标却很简单,和分成多个级别的隔离性不同,原子性就只有支持和不支持的区别。

(2)隔离性

    它是事务中最复杂的特性。隔离性分为多个隔离级别,较低的隔离级别就是在正确性上做妥协,将一些异常现象交给应用系统的开发人员去解决,从而获得更好的性能。可以说,事务模型的发展过程就是在隔离性和性能之间不断地寻找更优的平衡点,甚至可以说事务的核心就是隔离性。而不同产品在事务一致性上的差别,也完全体现在隔离性的实现等级上,所以我们必须搞清楚隔离等级具体是指什么。

(3)持久性

    它不仅是对数据库的基本要求。如果你仔细琢磨下持久性的定义,就会发现它的核心思想就是要应对系统故障。怎么理解系统故障呢?我们可以把故障分为两种。

  • 存储硬件无损、可恢复的故障。这种情况下,主要依托于预写日志(Write Ahead Log, WAL)保证第一时间存储数据。WAL 采用顺序写入的方式,可以保证数据库的低延时响应。WAL 是单体数据库的成熟技术,NoSQL 和分布式数据库都借鉴了过去。
  • 存储硬件损坏、不可恢复的故障。这种情况下,需要用到日志复制技术,将本地日志及时同步到其他节点。实现方式大体有三种:第一种是单体数据库自带的同步或半同步的方式,其中半同步方式具有一定的容错能力,实践中被更多采用;第二种是将日志存储到共享存储系统上,后者会通过冗余存储保证日志的安全性,亚马逊的 Aurora 采用了这种方式,也被称为 Share Storage;第三种是基于 Paxos/Raft 的共识算法同步日志数据,在分布式数据库中被广泛使用。无论采用哪种方式,目的都是保证在本地节点之外,至少有一份完整的日志可用于数据恢复。

(4)一致性

    ACID中的一致性主要是指对数据有特定的预期状态,任何数据更改必须满足这些状态约束(或者恒等条件)。例如,对于一个账单系统,账户的贷款余额应和借款余额保持平衡。如果事务从一个有效的状态开始,并且事务中任何更新操作都没有违背约束,那么最后的结果依然符合有效状态。这种一致性本质上要求应用层来维护状态一致,应用程序有责任正确地定义事务来保持一致性。这不是数据库可以保证的事情:即如果提供的数据修改违背了恒等条件,数据库很难检测进而阻止该操作。

    原子性、隔离性和持久性是数据库自身的属性,而ACID中的一致性更多的是应用层属性。应用程序可能借助数据库提供的原子性和隔离性,以达到一致性。    

2. 弱隔离级别

2.1 读-提交

    读-提交时最基本的事务隔离级别,它只提供以下两个保证:

(1)防止“脏读”:读数据时,只能看到已成功提交的数据

    以下需求时,需要防止脏读:1)事务需要更新多个对象,脏读意味着另一个事务可能会看到部分更新,而非全部;2)如果事务发生终止,则所有写入的操作都要回滚。

(2)防止“脏写”:写数据时,只会覆盖已成功提交的数据

    防止脏写可以避免以下并发问题,如果事务需要更新多个对象,脏写会带来非预期的错误结果。

  如何实现读-提交?

    防止脏写:数据库通常采用行级锁来实现,当事务想修改某个对象时,它必须首先获得该对象的锁,然后一直持有锁直到事务提交。

    防止脏读:对于每个待更新的对象,数据库都会维护其旧值和当前持锁事务将要设置的新值两个版本,在事务提交之前,所有其他读操作都读取旧值,仅当写事务提交后,才会切换到读取新值。

2.2 快照隔离级别与可重复读

(1)不可重复读或读倾斜

    Alice 在银行有 1000 美元的储蓄,分为两个账户,每个 500 美元。现在有一笔事务从她的一个账户2转移了 100 美元到另一个账户1。如果她非常不幸地在事务处理的过程中查看其账户余额列表,她可能会在收到付款之前先看到一个账户的余额(收款账户1,余额仍为 500 美元),在发出转账之后再看到另一个账户的余额(付款账户2,新余额为 400 美元)。对 Alice 来说,现在她的账户似乎总共只有 900 美元 —— 看起来有 100 美元已经凭空消失了。

    这种异常现象被称为不可重复读或者读倾斜。快照隔离级别是解决上述问题最常见的手段。其总体想法是:每个事务都从数据库的一致性快照中读取,事务一开始所看到是最近提交的数据,即使数据随后可能被另一个事务更改,但保证每个事务都只看到该特定时间点的旧数据。 

(2)实现快照隔离级别

    与读-提交隔离类似,快照隔离级别的实现通常采用写锁来防止脏写,这意味着正在进行写操作的事务会阻止同一对象上的其他事务。

    为了实现可重复读,数据库保留了对象多个不同的提交版本,这种技术因为也被称为多版本并发控制技术(Multi-Version Concurrent Control,MVCC)。如果只是为了提供读-提交隔离级别,而不是完整的快照隔离级别,则只保留对象的两个版本旧足够了。所以,支持快照隔离级别的存储引擎往往直接采用MVCC机制来实现读-提交隔离。典型做法是:在读-提交级别下,对一个事务中每一个不同的查询单独创建一个快照;而快照隔离级别则是使用一个快照来运行整个事务。

2.3 防止更新丢失

(1)防止更新丢失是什么

    读-提交和快照隔离级别都是为了解决只读事务遇到并发写时可以看到什么,总体而言我们还没有触及到另一种情况,即两个事务并发,而脏读只是写并发的一个特例。

    更新丢失可能发生在这样一个操作场景中:应用程序从数据库读取某些值,根据应用逻辑做出修改,然后写回新值(读取 - 修改 - 写入序列)。当有两个事务在同样的数据对象上执行类似的操作时,由于隔离性,第二个写操作并不包括第一个事务修改后的值,最终会导致第一个事务的修改值可能丢失。

(2)可行的解决方案

    1)原子写操作:数据库自身提供了原子更新操作,以避免应用层代码完成“读-修改-写回”操作,如果支持的话,通常这就是最好的解决方案。原子操作通常对读取对象加独占锁的方式来实现,这样在更新被提交之前其他事务不会读它。另一种实现方式是强制所有的原子操作都在单线程上执行。

    2)显示加锁:如果数据库不支持原子锁操作,另一种防止丢失更新的方法是由应用程序显式锁定待更新的对象。然后,应用程序可以执行“读-修改-写回”这样的操作序列。

    3)自动检测更新丢失:原子操作和锁都是通过强制“读-修改-写回”操作序列串行执行来防止丢失更新。另一种思路是先让他们并发执行,但是如果事务管理器检测到了更新丢失风险,则会终止当前事务,并强制回退到安全的“读-修改-写回”方式。

2.4 写倾斜与幻读

(1)什么是写倾斜

    首先,设想这样一个例子:你正在开发一个应用程序来帮助医生管理医院的轮班。通常,医院会安排多个医生值班,医生也可以申请调整班次,但是前提是确保至少一位医生还在该班次中值班。

    现在的情况是,Alic和Bob是两位值班医生,两人碰巧都身体不适,因而都决定请假,不幸的是,他们几乎同一时刻点击了调班按钮,如下图所示:

     每笔事务总是首先检查是否至少有两名医生目前在值班。如果是的话,则有一名医生可以安全离开。由于数据库正在使用快照隔离级别,两个检查都返回有两名医生,所以两个事务都安全地进入到下一阶段。接下来Alic更新自己的值班记录为离开,同样,Bob也更新自己的记录。两个事务都成功提交,最后的结果却是没有任何医生在值班,显然这违背了至少一名医生值班的业务要求。

    这种异常情况称为写倾斜,可以将写倾斜视为一种更为广义的更新丢失问题。即如果两个事务读取相同的一组对象,然后更新其中一部分:不同事务可能更新不同的对象,则可能发生写倾斜;不同事务如果更新的是同一对象,则可能发生脏写或丢失更新。

(2)为何产生写倾斜

   写倾斜的例子都遵循以下类似的模式:

  1)首先输入一些匹配条件,即采用select查询所有满足条件的行

  2)根据查询结果,应用层代码决定下一步操作

  3)如果应用程序决定继续执行,它将发起数据库写入(insert、update或delete)并提交事务。而这个写操作会改变步骤2做出决定的前提条件。

    这种在一个事务中的写入改变了另一个事务查询结果的现象,称为幻读。快照隔离级别可以避免只读查询的幻读,但是对于我们上面提到的读-写事务,它却无法解决棘手的写倾斜问题。

3. 强隔离级别——可串行化

    可串行化隔离通常被认为是最强的隔离级别,它保证即使事务可能会并行执行,但最终的结果与每次一个即串行执行结果相同。这意味着,如果事务在单独运行时表现正常,那么它们在并发运行时结果仍然正确。目前大多数提供可串行化的数据库都使用了以下三种技术之一:严格串行化执行、两阶段加锁和乐观并发技术。

3.1 实际串行执行

(1)单线程执行

    最简单的方法时避免并发,即在一个线程上按顺序方式每次只执行一个事务,其对应的隔离级别一定是严格串行化的。单线程执行有时可能会比支持并发的系统更高效,尤其是可以避免锁开销,但是其吞吐量上限是单个CPU核的吞吐量。

(2)存储过程封装事务

  对于交互式事务,例如应用程序提交查询,读取结果,可能会根据前一个查询的结果来进行其他查询。交互式事务大量时间花费在应用程序和数据库之间的网络通信,如果不允许并发,而是一次仅处理一个,那么吞吐量将非常低。

    出于这个原因,采用单线程串行执行的系统往往不支持交互式的多语句事务,应用程序必须提交整个事务代码作为存储过程打包发送到数据库。把事务所需的所有数据全部加载到内存中,使存储过程高效执行,而无需等待网络或磁盘IO。

(3)分区

    串行执行所有事务使得并发控制变得更加简单,但是数据库的吞吐量被限制在单机单个CPU核。为了扩展到多个CPU和多节点,可以对数据进行分区。如果能找到一个方法对数据集进行分区,使得每个事务只在单个分区内读写数据,这样每个分区都可以有自己的事务处理线程且独立运行。

    但是,对于跨分区事务,数据库必须在涉及的所有分区之间协调事务。存储过程需要跨越所有分区加锁执行,以确保整个系统的可串行化。

3.2 两阶段加锁

    近三十年来,可以说数据库只有一种被广泛使用的串行化算法,那就是两阶段加锁(two-phase locking,2PL)。可以使用加锁的方法来防止脏写,即如果两个事务同时尝试写入同一个对象时,以加锁的方式来确保第二个写入等待前面的事务完成。两阶段加锁的方法类似,但锁的强制性更高。多个事务可以同时读取同一对象,但只要出现任何写操作,则必须加锁以独占访问。

(1)实现两阶段加锁

    目前2PL已经用于MySQL和SQL Server中的“可串行化执行”。此时数据库的每个对象都有一个读写锁来隔离读写操作,即锁可以处于共享模式或者独占模式。基本用法如下:

  • 如果事务要读取对象,必须先以共享模式获得锁
  • 如果事务要修改对象,必须以独占模式获取锁
  • 如果事务首先读取对象,然后尝试写入对象,则需要将共享锁升级为独占锁
  • 事务获得锁之后,一直持有锁直到事务结束(包括提交或者中止)

    使用这么多锁机制,很容易出现死锁。数据库系统会自动检测事务之间的死锁情况,并强行中止其中的一个以打破僵局,这样另一个可以继续向前执行。而被中止的事务需要由应用层来重试。

(2)两阶段加锁的性能

    两阶段加锁的缺点主要在于性能:其事务吞吐量和查询响应时间相比于其他弱隔离级别下降非常多。部分原因在于锁的获取和释放本身的开销,但更重要的是其降低了事务的并发性。

    两个并发事务如果试图做任何可能导致竞争条件的事情,其中一个必须等待对方完成,最终结果是,当一个事务还需要等待另一个事务时,那么最终的等待时间几乎是没有上限的。即使可以保证自己的事务足够简短、高效,但一旦出现多个事务同时访问一个对象,会形成一个等待队列,事务就必须等待队列前面所有其他事务完成之后才能继续。

(3)谓词锁

    对于写倾斜和幻读问题,可串行化隔离液必须防止幻读问题。以会议室预定为例,如果事务在查询某个时间段内一个房间的预定情况,则另一个事务不能同时去插入或更新同一个时间段内该房间的预定情况,但它可以修改其他房间的预定情况。

    如何实现呢,可以引入一种谓词锁,它的作用类似与共享锁或者排他锁,而区别在于,它并不属于某个特定的对象,如表的某一行,而是作用于满足某些搜索条件的所有查询对象。谓词锁会限制如下访问:

  • 如果事务A想要读取某些满足匹配条件的对象,例如采用select查询,它必须以共享模式获得查询条件的谓词锁。如果另外一个事务B正在持有任何一个匹配对象的互斥锁,那么A必须等到B释放了锁之后才能继续执行查询。
  • 如果事务A想要插入、更新或删除任何对象,则必须首先检查所有旧值和新值是否与现有的任何谓词锁匹配。如果事务B持有这样的谓词锁,那么A必须等待B完成提交后才能继续。

   这里的谓词锁可以保护数据库中那些尚不存在但可能马上会被插入的对象。将2PL和谓词锁结合使用,数据库可以防止所有写形式的写倾斜以及其他竞争条件,隔离变得真正可串行化。

(4)索引区间锁

    不幸的是,谓词锁性能不佳。因此,大多数使用2PL的数据库实际上实现的是索引区间锁(或next locking),本质上它是对谓词锁的简化或者近似。

    简化谓词锁的方式是将其保护的对象扩大化。例如,如果一个谓词锁保护的查询条件是:房间123,时间段是中午至下午1点,则一种方式是通过扩大时间段来简化,即保护123房间的所有时间段;或者另一种方式是扩大房间,即保护中午至下午之间的所有房间(而不是123房间)。对于房间的预定,通常会在root_id列上创建索引,或在start_time和end_time上有索引,否则前面的查询在大型数据库上会很慢。

    无论哪种方式,查询条件的近似值都附加到某个索引上。接下来,如果另外一个事务想要插入、更新或删除一个房间或重叠时间段的预定,则肯定需要更新这些索引,一定会与共享锁冲突,因此会自动处于等待状态直到共享锁释放。

3.3 可串行化的快照隔离

    2PL虽然可以保证串行化,但性能差强人意且无法扩展,弱隔离级别虽然性能不错,但容易引发各种边界冲突。串行化隔离与性能是不是从根本上就是互相冲突而无法兼得吗?

    最近有一种称为可串行化的快照隔离(SSI)算法看起来让人眼前一亮,它提供了完整的可串行化保证,而性能相比于快照隔离损失很小。SSI是基于快照隔离,也就是说,事务中所有的读取操作都是基于数据库的一致性快照。在快照隔离的基础上,SSI新增了相关算法来检测写入之间的串行化冲突从而决定中止哪些事务。SSI和2PL的区别如下:

  • 2PL是一种典型的悲观并发机制。它基于这样的设计原则:如果某些操作可能出错,那么直接放弃,采用等待方式直到绝对安全,这和多线程编程中互斥锁是一致的。
  • SSI是一种乐观并发机制,在这种情况,如果可能发生潜在冲突,事务会继续执行而不是中止,寄希望一切相安无事;而当事务提交时,数据库会检查是否确实发生了冲突,如果是的话,中止事务并接下来重试。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分布式数据库难题(四):单机事务 的相关文章

  • 程序员读书和练习的方法(个人观点)

    lt 传送门 gt 针对本文的交流探讨 gt 总宗旨 xff1a 打好计算机通用理论基础 通用实战能力 xff0c 便于需要时对各领域的无障碍深钻 时间宝贵 xff0c 不要为了学习而学习 计算机通用理论基础 xff1a 计算机各领域理论基
  • 从零开始的Ubuntu 16.04下PX4编译环境的搭建

    近来入手了一块pixhawk xff0c 想进行一些基于已有代码的二次加工 xff0c 于是到官网https dev px4 io 上看教程 官网上的教程是分为中文 英文以及韩文的版本 很多人肯定第一反应就是看中文的版本 但是这样做弊端真的
  • 驱动程序开发:SPI设备驱动

    目录 Linux下SPI驱动简介SPI架构概述SPI适配器 xff08 控制器 xff09 SPI设备驱动spi driver注册示例SPI 设备和驱动匹配过程编写imc20608六轴传感器SPI驱动设备树编写操作具体的imc20608驱动
  • 操作系统知识点(二)

    文章目录 内存管理程序执行过程内存保护 连续分配非连续分配基本分页存储管理方式基本分段存储管理方式段页式存储管理方式 虚拟内存局部性原理请求分页存储管理 内存管理 内存管理 Memory Management 是操作系统设计中最重要和最复杂
  • VR行业发展的前景和现状?

    标题 VR行业发展的前景和现状 xff1f 1 一个新事物的产生 xff0c 总是伴随着看好和唱衰两种声音 这两种态度自然有其可以理解的地方 xff0c 因为摆在我们面前的是未知 xff0c 而坐在餐桌前的两拨人 xff0c 站在不同的角度
  • 头文件与库的区别

    昨天突然问了一下什么是头文件 xff0c 我一听就傻了 xff0c 虽然上课的时候老师在讲编译的四个过程的时候说了一下 xff0c 但是还是不太理解 xff0c 我们知道编译过程中的预处理阶段会进行头文件展开 xff0c 宏替换以及条件编译
  • 进程、线程

    线程 xff08 thread xff09 线程其实是操作系统能够进行运算调度的最小单位 它是被包含在进程之中的 xff0c 是进程中的实际运作单位 一条线程指的是进程中一个单一顺序的控制流 xff0c 一个进程中可以并发多个线程 xff0
  • 基于Zynq7020双千兆以太网的数字信号处理板设计

    一 背景 背景 Xilinx公司在2010年发布了可扩展的处理器平台Zynq7000系列 xff0c 它采用了28nm工艺 xff0c 将FPGA与ARM cortex A9集成在一颗芯片上 xff0c 实现了高性能 高集成度 低功耗 Zy
  • 深入理解JS中的变量作用域

    在 JS 当中一个变量的作用域 xff08 scope xff09 是程序中定义这个变量的区域 变量分为两类 xff1a 全局 xff08 global xff09 的和局部的 其中全局变量的作用域是全局性的 xff0c 即在 JavaSc
  • 硬件工程师,从零开始无人机开发。

    毕业已经五年了 xff0c 一直在杭州某大厂 xff0c 做无人机硬件开发 无人机这块 xff0c 我进去的时候大厂刚开始 做 xff0c 有幸参与到整个无人机的硬件开发 我这个刚毕业的技术小白 xff0c 在这五年间成长了很多 无奈 今年
  • 个人总结:板球控制系统之串级PID整定方法,速度环与位置环,40S任务10S完成

    其实单环我们先出了所有题目 xff0c 但是效果显然没有串级PID的效果好 xff0c 有人需要的话可以把程序包发出来 xff0c 板球运行视屏也有 另外 xff1a 天下舵机参差不齐 xff08 哪怕型号相同 xff09 xff0c 想要
  • 树莓派3B+踩坑记录:一、安装Ubuntu Mate

    树莓派3B 43 踩坑记录 xff1a 一 安装Ubuntu Mate 树莓派 xff0c Ubuntu xff0c ROS硬件准备软件准备系统烧录安装Ubuntu Mate更换国内源网络配置开启ssh远程其他彩虹屏解决方案XShell和X
  • PointNet代码详解

    PointNet代码详解 最近在做点云深度学习的机器人抓取 xff0c 这篇博客主要是把近期学习PointNet的一些总结的知识点汇总一下 PointNet概述详见以下网址和博客 xff0c 这里也就不再赘述了 三维深度学习之pointne
  • 卡尔曼滤波通俗易懂的解释

    关于卡尔曼滤波 xff0c 网上的资料很多 xff0c 但是有很大一部分都是不断堆叠公式 xff0c 然后用各种晦涩难懂的专业术语进行解释 xff0c 说实话我刚开始看的时候也是云里雾里 xff0c 因此写下这篇博客是为了照顾和我一样的萌新
  • STM32通过PWM控制ESC30C电调

    最近在搞一个水下推进器 xff0c 这东西的控制其实跟四旋翼的螺旋桨控制差不多 但我也是第一次用STM32板子来控制电调驱动桨叶旋转 xff0c 因此踩了很多坑 网上找了很多资料 xff0c 但是很多都写的不是很清楚 xff0c 这边稍微记
  • STM32F7同一定时器多路输出PWM波通道之间相互影响问题

    2020 8 12更新 这次用Cube直接生成PWM控制代码 xff0c 然后再RT Thread Studio上编写程序 xff0c 发现可实现TIM1和TIM8的8路PWM波调控 xff0c 因此上面论述的问题可能是自己在写底层时有某些
  • Ardusub源码解析学习(一)——Ardusub主程序

    APM Sub源码解析学习 xff08 一 xff09 Ardusub主程序 前言一 准备工作二 Ardusub cpp解析2 1 scheduler table2 2 schedulerget scheduler tasks setup
  • Ardusub源码解析学习(二)——电机库

    Ardusub源码解析学习 xff08 二 xff09 电机库学习 一 RC输入与输出1 1 RC Input1 2 RC Output 二 电机库学习2 1 setup motors 2 2 add motor raw 6dof 2 3
  • Ardusub源码解析学习(三)——车辆类型

    APM Sub源码解析学习 xff08 三 xff09 车辆类型 一 前言二 class AP HAL HAL三 class AP Vehicle3 1 h3 2 cpp 四 class Sub4 1 h4 2 cpp 五 总结 一 前言
  • 年度回忆录(2012.10----2013.01)

    寒假结束了 xff0c 年也过完了 xff0c 提前回来一天就开始着手补上这迟到的年终总结 xff0c 写了一个多星期还觉得有些东西没有写出来 xff0c 无奈 xff0c 点到为止吧 2012 年的后半年经历了很多 xff0c 收获了很多

随机推荐

  • Ardusub学习——飞行模式

    参考资料 xff1a Ardusb官方手册 Sub Rework joystick input and pilot input in general Flight Modes Ardusub支持多种飞行模式 xff0c 但是其中一部分需要有
  • Ardusub源码解析学习(五)——从manual model开始

    Ardusub源码解析学习 xff08 五 xff09 从manual model开始 manual init manual run 从本篇开始 xff0c 将会陆续对Ardusub中各种模式进行介绍 xff0c stabilize mod
  • 重读Ardupilot中stabilize model+MAVLINK解包过程

    APM源码和MAVLINK解析学习 重读stabilize stabilize modelinit run handle attitude MAVLINK消息包姿态信息传输过程 之前写的模式都是基于master版本的 xff0c 这次重读s
  • QGC添加自定义组件和发送自定义MAVLINK消息

    QGC添加自定义组件和发送自定义MAVLINK消息 一 添加自定义组件1 1 在飞行界面添加组件1 2 实现组件事件1 3 在MOCK模拟链接中实现验证1 4 验证 二 自定义MAVLINK消息的一些预备知识三 QGC自定义MAVLINK消
  • MAVLINK消息在Ardupilot中的接收和发送过程

    MAVLINK消息在Ardupilot中的接收和发送过程 SCHED TASKupdate receive update send 由于现在网上很多的都是APM旧版本的解释 xff0c 因此把自己的一些学习所得记录下来 截至写博客日期 xf
  • Ardupilot姿态控制器 PID控制流程

    Ardupilot姿态控制器 PID控制流程 一 PID姿态控制器1 1 Copter姿态控制官方原图1 2 ArduCopter V4 X STABILIZE 二 姿态控制器类实现2 1 类成员解析2 1 1 类成员变量2 1 2 类成员
  • APM姿态旋转理论基础

    APM姿态旋转理论基础 一 坐标系1 1 NED坐标系1 2 机体坐标系 二 欧拉角姿态变化率与机体角速度的关系 三 旋转矩阵3 1 基本公式3 2 矩阵作差3 3 旋转矩阵与变换矩阵的区别 四 DCM五 轴角法5 1 基本概念5 2 与旋
  • 详解APM的开方控制器sqrt_controller

    前言 前面说过 xff0c sqrt controller是对P项进行整定用途的 xff0c 目的就是让P项的控制响应 软 下来 xff0c 实际上就是一个经过改进的P控制器 读懂了sqrt controller xff0c 那么你对APM
  • Ardupilot前馈及平滑函数input_euler_angle_roll_pitch_yaw解析

    Ardupilot前馈及平滑函数input euler angle roll pitch yaw解析 源码解析这个函数做了什么部分细节euler accel limit input shaping angle 姿态变化率与机体角速度之间的关
  • Ardupilot倾转分离函数thrust_heading_rotation_angles

    Ardupilot倾转分离函数thrust heading rotation angles 什么是轴角分离源码分析一些细节补充效果显示及进一步修改 本文主要写一下自己对于APM倾转分离 xff08 轴角分离 xff09 函数的一些学习笔记及
  • Spring IOC原理解析

    首先恭喜守宏同学找到了自己心仪的工作 xff0c 入职的事情终于尘埃落定 xff0c 也算是一个新的开始吧 和守宏聊天的时候也说了很多有关工作的事情 xff0c 畅想了以后美好的未来 xff0c 也想到了今后的种种困难 不说别的就是单单在北
  • Ardupilot四元数姿态控制函数attitude_controller_run_quat解析

    Ardupilot四元数姿态控制函数attitude controller run quat解析 源码解析细节讲解thrust heading rotation angles update ang vel target from att e
  • Ardupilot速率控制器rate_controller_run解析

    Ardupilot速率控制器rate controller run解析 PID速率控制器源码解析rate controller run PID运算积分限制update i get ff set xxx 内容补充 xff1a 函数中陀螺仪数据
  • muduo网络库学习总结:基本架构及流程分析

    muduo网络库学习 xff1a 基本架构及流程分析 基本架构Basic ReactorMutiple Reactor 43 ThreadPool muduo库的基本使用基本结构介绍EventLoop类Poller类Channel类TcpC
  • push_back和emplace_back比较以及vector扩容

    push back和emplace back比较以及vector扩容 push back和emplace back的比较使用测试类测试过程将实体类对象传入将右值数字传入将实体类对象move 转右值之后传入 vector扩容过程 关于这部分内
  • 在ubuntu 11.04下编写驱动程序

    在ubuntu11 04下直接就可以编写驱动程序 xff0c 并进行编译 hello c include 34 linux init h 34 include 34 linux module h 34 static int hello in
  • ROS的优势与不足(除了ROS 机器人自主定位导航还能怎么做?)

    导读 xff1a 随着这两年国内机器人的升温 xff0c 自主定位导航技术作为机器人智能化的第一步正不断引起行业内的重视 为了实现这一功能 xff0c 不少厂家选择采用机器人操作系统ROS xff08 Robot Operation Sys
  • C++版本发展史

    1 C 43 43 98 2 C 43 43 03 3 C 43 43 11 3 1 nullptr 3 2 auto 3 3 decltype 3 4 初始化列表 3 5 范围for循环 3 6 右值引用 3 7 字符串字面量 3 8 n
  • 分布式数据库难题(三):数据一致性

    1 什么是数据一致性 一直以来 xff0c 在 分布式系统 和 数据库 这两个学科中 xff0c 一致性 xff08 Consistency xff09 都是重要概念 xff0c 但它表达的内容却并不相同 对于分布式系统而言 xff0c 一
  • 分布式数据库难题(四):单机事务

    1 ACID的含义 在数据库中 xff0c 事务 是由多个操作构成的序列 1970 年詹姆斯 格雷 xff08 Jim Gray xff09 提出了事务的 ACID 四大特性 xff0c 将广义上的事务一致性具化到了原子性 一致性 隔离性和