分布式数据库难题(三):数据一致性

2023-05-16

1. 什么是数据一致性

     一直以来,在“分布式系统”和“数据库”这两个学科中,一致性(Consistency)都是重要概念,但它表达的内容却并不相同。对于分布式系统而言,一致性是在探讨当系统内的一份逻辑数据存在多个物理的数据副本时,对其执行读写操作会产生什么样的结果,这也符合 CAP 理论对一致性的表述。而在数据库领域,“一致性”与事务密切相关,又进一步细化到 ACID 四个方面。其中,I 所代表的隔离性(Isolation),是“一致性”的核心内容,研究的就是如何协调事务之间的冲突。因此,当我们谈论分布式数据库的一致性时,实质上是在谈论数据一致性事务一致性两个方面。这一点,从 Google Spanner 对其外部一致性(External Consistency)的论述中也可以得到佐证。

    包括分布式数据库在内的分布式存储系统,为了避免设备与网络的不可靠带来的影响,通常会存储多个数据副本。逻辑上的一份数据同时存储在多个物理副本上,自然带来了数据一致性问题。讨论数据一致性还有一个前提,就是同时存在读操作和写操作,否则也是没有意义的。把两个因素加在一起,就是多副本数据上的一组读写策略,被称为“一致性模型”(Consistency Model)。一致性模型数量很多,让人难以分辨。为了便于你理解,我先建立一个简单的分析框架。这里,我要借用论文“The many faces of consistency”中的两个概念,状态一致性(State Consistency)和操作一致性(Operation Consistency)。不要慌,这不是新的一致性模型,它们只是观察数据一致性的两个视角。

  • 状态一致性:指的是数据所处的客观、实际状态所体现的一致性;
  • 操作一致性:指的是外部用户通过协议约定的操作,能够读取到的数据一致性。

2. 状态一致性

2.1 强一致性:MySQL 全同步复制

     现在有一个 MySQL 集群,由一主两备三个节点构成,那么在全同步复制(Fully Synchronous Replication)模式下,用户与 MySQL 交互的过程是这样的。        

    在该模式下,主库与备库同步 binlog 时,主库只有在收到两个备库的成功响应后,才能够向客户端反馈提交成功。显然,用户获得响应时,主库和备库的数据副本已经达成一致,所以后续的读操作肯定是没有问题的,但这种模式的副作用非常大,体现在以下两点。

  •  第一,性能差。主库必须等到两个备库均返回成功后,才能向用户反馈提交成功。图中由于网络阻塞,“备库 2”稍晚于“备库 1”返回响应,增加了数据库整体的延时。而下一次,拖后腿的可能变成“备库 1”。总之,主库的响应时间取决于两个备库中延时最长的那个。
  •  第二,可用性问题。我们在第 1 讲提到过可用性概念,任何设备都有可能出现故障,尤其是 x86 这样的通用商业设备,故障率会更高。但在全同步复制模式下,集群中的三个节点被串联起来,如果单机可用性是 95%,那么集群整体的可用性就是 85.7%(95%*95%*95%=85.7%),

    跟单机相比反而降低了。集群规模越大,这些问题就越严重,所以全同步复制模式在生产系统中也很少使用。更进一步说,在工程实践中,实现状态视角的强一致性需要付出的代价太大,尤其是与可用性有无法回避的冲突,所以很多产品选择了状态视角的弱一致性。

2.2 弱一致性:NoSQL 最终一致性

    NoSQL 产品是应用弱一致性的典型代表,但对弱一致性的接受仍然是有限度的,这就是 BASE 理论中的 E 所代表的最终一致性(Eventually Consistency),弱于最终一致性的产品就几乎没有了。对于最终一致性,你可以这样理解:在主副本执行写操作并反馈成功时,不要求其他副本与主副本保持一致,但在经过一段时间后这些副本最终会追上主副本的进度,重新达到数据状态的一致。

3. 操作一致性

    最终一致性,在语义上包含了很大的不确定性,所以很多时候并不是直接使用,而是加入一些限定条件,也就衍生出了若干种一致性模型。因为它们是在副本不一致的情况下,进行操作层面的封装来对外表现数据的状态,所以都可以纳入操作视角。

3.1 写后读一致性

    许多应用让用户提交一些数据,然后查看他们提交的内容。可能是用户数据库中的记录,也可能是对讨论主题的评论,或其他类似的内容。提交新数据时,必须将其发送给主库,但是当用户查看数据时,可以通过从库进行读取。如果数据经常被查看,但只是偶尔写入,这是非常合适的。但对于异步复制,问题就来了。如下图所示:如果用户在写入后马上就查看数据,则新数据可能尚未到达副本。对用户而言,看起来好像是刚提交的数据丢失了,所以他们不高兴是可以理解的。 

    这种情况下,我们需要“写后读一致性”(Read after Write Consistency),它也称为“读写一致性”,或“读自己写一致性”(Read My Writes Consistency)。你可能觉得最后一个名字听上去有些奇怪,但它却最准确地描述了这种一致性模型的使用效果。

    已写入成功的任何数据,下一刻一定能读取到,其内容保证与自己最后一次写入完全一致,这就是“读自己写一致性”名字的由来。当然,从旁观者角度看,可以称为“读你写一致性”(Read Your Writes Consistency),有些论文确实采用了这个名称。假定系统可以通过某种策略由写入节点的主副本负责后续的读取操作,这样就实现了写后读一致性,

    如何在基于领导者的复制系统中实现写后读一致性?有各种可能的技术,这里说一些:

  • 对于用户可能修改过的内容,总是从主库读取;这就要求得有办法不通过实际的查询就可以知道用户是否修改了某些东西。举个例子,社交网络上的用户个人资料信息通常只能由用户本人编辑,而不能由其他人编辑。因此一个简单的规则就是:总是从主库读取用户自己的档案,如果要读取其他用户的档案就去从库。

  • 如果应用中的大部分内容都可能被用户编辑,那这种方法就没用了,因为大部分内容都必须从主库读取(读伸缩就没效果了)。在这种情况下可以使用其他标准来决定是否从主库读取。例如可以跟踪上次更新的时间,在上次更新后的一分钟内,从主库读。还可以监控从库的复制延迟,防止向任何滞后主库超过一分钟的从库发出查询。

  • 客户端可以记住最近一次写入的时间戳,系统需要确保从库在处理该用户的读取请求时,该时间戳前的变更都已经传播到了本从库中。如果当前从库不够新,则可以从另一个从库读取,或者等待从库追赶上来。这里的时间戳可以是逻辑时间戳(表示写入顺序的东西,例如日志序列号)或实际的系统时钟(在这种情况下,时钟同步变得至关重要)。

如果你的副本分布在多个数据中心(为了在地理上接近用户或者出于可用性目的),还会有额外的复杂性。任何需要由主库提供服务的请求都必须路由到包含该主库的数据中心。

3.2 单调读一致性

    如果用户从不同从库进行多次读取,就可能发生这种情况。例如,下图显示了用户 2345 两次进行相同的查询: 

    首先查询了一个延迟很小的从库,然后是一个延迟较大的从库(如果用户刷新网页时每个请求都被路由到一个随机的服务器,这种情况就很有可能发生)。第一个查询返回了最近由用户 1234 添加的评论,但是第二个查询不返回任何东西,因为滞后的从库还没有拉取到该写入内容。实际上可以认为第二个查询是在比第一个查询更早的时间点上观察系统。如果第一个查询没有返回任何内容,那问题并不大,因为用户 2345 可能不知道用户 1234 最近添加了评论。但如果用户 2345 先看见用户 1234 的评论,然后又看到它消失,这就会让人觉得非常困惑了。

    单调读(monotonic reads)可以保证这种异常不会发生。这是一个比强一致性(strong consistency)更弱,但比最终一致性(eventual consistency)更强的保证。当读取数据时,你可能会看到一个旧值;单调读仅意味着如果一个用户顺序地进行多次读取,则他们不会看到时间回退,也就是说,如果已经读取到较新的数据,后续的读取不会得到更旧的数据。

    实现单调读一致性的方式,可以是将用户与副本建立固定的映射关系,比如使用哈希算法将用户 ID 映射到固定副本上,这样避免了在多个副本中切换,也就不会出现上面的异常了。

3.3 前缀一致性

    这天小明去看 CBA 总决赛,刚开球小明就拍了一张现场照片发到朋友圈,想要炫耀一下。小红也很喜欢篮球,但临时有事没有去现场,就在评论区问小明:“现在比分是多少?”小明回复:“4:2。”小明的同学,远在加拿大的小刚,却看到了一个奇怪的现象,评论区先出现了小明的回复“4:2。”,而后才刷到小红的评论“现在比分是多少?”。难道小明能够预知未来吗?这是什么原因呢?我们还是看图说话:

    小明和小红的评论分别写入了节点 N1 和 N2,但是它们与 N3 同步数据时,由于网络传输的问题,N3 节点接收数据的顺序与数据写入的顺序并不一致,所以小刚是先看到答案后看到问题。显然,问题与答案之间是有因果关系的,但这种关系在复制的过程中被忽略了,于是出现了异常。保持这种因果关系的一致性,被称为前缀读或前缀一致性(Consistent Prefix)。它的意思是说:如果一系列写入按某个顺序发生,那么任何人读取这些写入时,也会看见它们以同样的顺序出现。

    一种解决方案是,确保任何因果相关的写入都写入相同的分区,但在一些应用中可能无法高效地完成这种操作。还可以考虑在原有的评论数据上增加一种显式的因果关系,这样系统可以据此控制在其他进程的读取顺序。

3.4 线性一致性

    在“前缀一致性”的案例中,问题与答案之间存在一种显式声明,但在现实中,多数场景的因果关系更加复杂,也不可能要求全部做显式声明。比如对于分布式数据库来说,它无法要求应用系统在每次变更操作时附带声明一下,这次变更是因为读取了哪些数据而导致的。那么,在显式声明无法奏效的情况下,如何寻找因果关系呢?

    不知道你有没有听过这句话,“你所经历的一切,造就了现在的你。”是不是有一点哲学的味道?一切对原因的推测都是主观的,之前发生的一切都可能是原因。所以,更可靠的方式是将自然语意的因果关系转变为事件发生的先后顺序。线性一致性(Linearizability)就是建立在事件的先后顺序之上的。在线性一致性下,整个系统表现得好像只有一个副本,所有操作被记录在一条时间线上,并且被原子化,这样任意两个事件都可以比较先后顺序。这些事件一起构成的集合,在数学上称为具有“全序关系”的集合,而“全序”也称为“线性序”。我想,线性一致性大概就是因此得名。

    但是,集群中的各个节点不能做到真正的时钟同步,这样节点有各自的时间线。那么,如何将操作记录在一条时间线上呢?这就需要一个绝对时间,也就是全局时钟。从产品层面看,主流分布式数据库大多以实现线性一致性为目标,在设计之初或演进过程中纷纷引入了全局时钟,比如 Spanner、TiDB、OceanBase、GoldenDB 和巨杉等等。

    工程实现上,多数产品采用单点授时(TSO),也就是从一台时间服务器获取时间,同时配有高可靠设计; 而 Spanner 以全球化部署为目标,因为 TSO 有部署范围上的限制,所以 Spanner 的实现方式是通过 GPS 和原子钟实现的全局时钟,也就是 TrueTime,它可以保证在全球范围内任意节点能同时获得的一个绝对时间,误差在 7 毫秒以内。但是,对于线性一致性,学术界其实是有争议的。反对者的论据来自爱因斯坦的相对论的一个重要结论,“时间是相对的”。没有绝对时间,也就不存在全序的事件顺序,不同的观察者可能对于哪个事件先发生是无法达成一致的。因此,线性一致性是有局限性的。当然,从工程角度看,因为我们的应用场景都在经典物理学适用范围内,所以线性一致性也是适用的。

3.5 因果一致性

    既然线性一致性不够完美,那么有没有不依赖绝对时间的方法呢?当然是有的,这就是因果一致性(Causal Consistency)。因果一致性的基础是偏序关系,也就是说,部分事件顺序是可以比较的。至少一个节点内部的事件是可以排序的,依靠节点的本地时钟就行了;节点间如果发生通讯,则参与通讯的两个事件也是可以排序的,接收方的事件一定晚于调用方的事件。基于这种偏序关系,Leslie Lamport 在论文“Time, Clocks, and the Ordering of Events in a Distributed System”中提出了逻辑时钟的概念。借助逻辑时钟仍然可以建立全序关系,当然这个全序关系是不够精确的。因为如果两个事件并不相关,那么逻辑时钟给出的大小关系是没有意义的。

    多数观点认为,因果一致性弱于线性一致性,但在并发性能上具有优势,也足以处理多数的异常现象,所以因果一致性也在工业界得到了应用。具体到分布式数据库领域,CockroachDB 和 YugabyteDB 都在设计中采用了逻辑混合时钟(Hybrid Logical Clocks),这个方案源自 Lamport 的逻辑时钟,也取得了不错的效果。因此,这两个产品都没有实现线性一致性,而是接近于因果一致性,其中 CockroachDB 将自己的一致性模型称为“No Stale Reads”。

3.6 一致性模型强度排序

    本文介绍的几种一致性模型,用一致性强度来衡量的话:线性一致性强于因果一致性;而写后读一致性、单调读一致性、前缀一致性弱于前两者,但这三者之间无法比较强弱。综上所述,我们提到的一致性模型强度排序如下:

    线性一致性 > 因果一致性 > { 写后读一致性,单调一致性,前缀一致性 }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分布式数据库难题(三):数据一致性 的相关文章

  • python函数(变量,参数)

    函数的变量 1 xff0c 全局变量 定义在最外层的变量 xff0c 对于所有的内函数都能调用 2 xff0c 局部变量 定义在函数内的变量叫做局部变量 xff0c 在函数外是不能访问局部变量 注 xff1a 全局变量不能直接在函数内部进行
  • 程序员读书和练习的方法(个人观点)

    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 一