Apache IoTDB 分布式架构三部曲(三)副本与共识算法

7eed52405936a0c73fceb0206fb0da2d.jpeg

IoTDB 首创并应用的共识协议统一框架,为用户提供了灵活选择不同共识算法的可能性。

对于一个分布式集群而言,为了使得海量数据场景下集群能够横向扩展,集群需要按照一定的规则将全部数据分成多个子集存储在不同的节点上,从而能够更加充分地利用到集群中各个节点的存算资源。对于集群中的任何一个分片而言,为了满足高可用的需求,需要将数据在多个物理节点上冗余存储多个副本,进而避免单点故障的出现。

由于同一份数据有多个副本,可能会出现不同副本间数据不一致的现象。现有的分布式系统一般通过共识算法来处理多个副本间的数据一致性问题。

然而,不同的业务场景对共识算法的一致性、可用性等要求不同。比如对于应用监控场景,Google 的时序数据库 Monarch 就明确指出对于监控场景的时序数据其会更关注可用性而不是一致性。不过对于数据分区等关键元信息,其依然使用了保证外部一致性的 Spanner 数据库进行管理。

对于专为物联网场景而生的分布式时序数据库 IoTDB 而言,针对时序数据,往往可以根据场景选择可用性更好的共识算法;而针对分区信息和元数据等核心信息,往往可以选择一致性较强的共识算法。

本文将从共识算法讲起,深入解析 IoTDB 对于共识算法一致性、可用性和性能等方面的选择与取舍,并介绍 IoTDB 独有的共识算法框架,帮助您理解并掌握 IoTDB 的多种共识策略,从而根据您的业务需要对共识算法进行灵活的选择与配置。

01

共识算法

(1)为什么需要共识算法

前面一期(分布式架构三部曲(二))提到,分布式系统通过将数据进行分片,并在多个物理节点冗余存储为多个副本的横向扩展方式来提升系统整体的可用性和性能。IoTDB 采取横向扩展的分布式架构,如下图所示。

e21a3096863fccb593111b533adaf4e9.png

尽管分布式系统的多副本设计大大增加了系统的可用性和性能,但这种横向扩展的思路也给系统带来了挑战,例如:

  • 不同副本如何保证数据是一致的?

  • 不同副本同时接收不同的写入,以谁为准?

  • 一个节点挂掉后,如何在其他节点恢复上面的副本?

  • 查询哪个副本的数据会更好?

共识算法即为解决上述挑战而设计的机制。让对外的用户既能享受到高可用和性能,也感知不到多副本的存在。

(2)共识算法的概念与分类

共识算法是分布式系统中的一种关键机制,用于在多个参与节点之间达成一致决策,即使在存在网络延迟、节点故障或恶意攻击的情况下,也能确保系统的一致性和可靠性。在分布式系统中,各个节点的副本可能存在不一致状态,而共识算法的目标就是确保所有节点最终达成一致,形成一个统一的决策,从而维持系统的整体一致性。

共识算法经过近半个世纪的发展,种类繁多,流程复杂。不同的共识算法的复制模式和一致性级别往往不同。一般来说,我们可以根据共识算法的复制模式和一致性保证对其进行分类。

根据共识算法的复制模式,可以将共识算法分为三个大类别:

  • 单主复制:客户端将所有写入操作发送到单个节点(主库),该节点将数据更改事件流发送到其他副本(从库)。读取可以在任何副本上执行,但从库的读取结果可能是陈旧的。

  • 多主复制:客户端将每个写入发送到几个主库节点之一,其中任何一个主库都可以接受写入。主库将数据更改事件流发送给彼此以及任何从库节点。

  • 无主复制:客户端将每个写入发送到几个节点,并从多个节点并行读取,以检测和纠正具有陈旧数据的节点。

20098d70dc1a68ae0a1723c8ecf9881c.png

而根据共识算法的一致性保证,可以大致将共识算法分为两个大类别:

  • 强一致性共识算法:能够对外提供线性一致性或顺序一致性的保证。线性一致性是最强的一致性级别,顺序一致性比线性一致性稍弱。如果共识算法提供强一致性,那么当一个数据写入操作完成后,任何后续的读操作都能读取到最新的数据值。强一致性保证了数据的一致性,但通常会付出一定的性能代价,因为它通常需要确保每一个写入操作在大多数相关节点上都被确认并完成。

  • 弱一致性共识算法:通常只提供最终一致性的保证,包括因果一致性、单调读一致性、读己之所写一致性、会话一致性等。如果共识算法提供弱一致性,那么系统将允许在某些条件下节点之间的数据状态不同步,直到某个时间点或某个条件满足后,系统才会最终达到一致性。弱一致性在设计上更加灵活,可以提高系统的性能和可用性,但在一定程度上牺牲了一致性。

713802b9b61fbeb27b025f00c05ad378.png

对于大多数共识算法,我们都可以根据上文的介绍识别它对应的复制模式和一致性保证。对于不同的共识算法,它们通常在性能、可用性和一致性保证等方面各不相同。通常情况下,提供更高级别的一致性级别会导致性能和可用性的下降。

(3)主流共识算法简介

通过前文的介绍,相信读者已经对共识算法的概念、作用和分类有了一定了解,接下来让我们简单了解两个著名共识算法,并感受不同共识算法在可用性、一致性、性能和存储成本等方面的区别。

1. Raft:Raft 是一种基于领导者的强一致性共识算法。Raft 算法将共识过程分解为几个关键的子过程:领导者选举、日志复制和安全性保证等。通过将共识过程结构化,Raft 算法不仅易于理解,而且便于实现,工业界已经有多种 codebase 的 Raft 算法成熟实现。

    • Raft 协议的易理解性使得开发者能够快速实现和调试分布式系统,同时其强一致性的保证提高了系统的可靠性和可维护性。

    • 作为强一致性算法, Raft 对于每次写入都要求大多数节点(半数以上)响应,并且需要持久化日志。因此性能相比弱一致性算法有一定差距,并且在大多数节点宕机时无法提供服务,可用性较差。此外,Raft 额外的持久化日志也带来了更高的存储成本。

2. Quorum:Quorum 是最出名的无主共识算法。在 Quorum 中,分布式系统的每一份数据拷贝对象都被赋予一票,只有每一个读操作获得的票数大于最小读票数,每个写操作获得的票数大于最小写票数时才能读或者写。在节点间数据不一致时,其通过读修复和反熵来保证数据间的最终一致性。Quorum 通常只能提供最终一致的弱一致性保证。

    • 由于 Quorum 一致性级别较低,无法满足很多应用场景对一致性的需求,Cassandra 目前已经使用了 Paxos 算法来管理其轻量事务。

    • Quorum 的读写最小票数可以用来作为系统在读、写性能方面的一个可调节参数。写票数 V(w) 越大,则读票数 V(r) 越小,这时候系统读的开销就小。反之则写的开销就小。由于 Quorum 读写都只需要对部分副本操作,因此可以根据读写需求平衡读写最小票数来获得更好的性能。

(4)共识算法统一框架

共识算法是分布式系统中数据读写关键链路的核心组成部分。如果所有共识算法都各自独立地实现其接口,一方面,这将不可避免地导致其他模块需要对各种共识算法进行大量的特殊处理和适配,从而对系统的迭代效率和维护成本产生负面影响。另一方面,这也将给未来系统接入新共识算法的扩展性带来挑战。

因此,为了提高系统架构演进的可扩展性和可维护性,某些分布式系统会考虑设计一种支持不同共识算法实现并对外提供统一接口的共识算法统一框架

接下来,让我们简单了解 OSDI 2020 Best Paper 提出的共识算法统一框架,感受共识算法统一框架带来的好处。后文也会详细介绍 IoTDB 的共识算法统一框架~

Facebook 的 Delos 通过共享日志抽象出了虚拟共识服务,其不仅能够对应用层透明且允许在虚拟共识服务底层实现不同的共识算法,并且还能够支持不停机更换共识算法。这些优质特性使得其统一了 Facebook 内部的所有元数据管理方案。

f0151b5f4f58550f47f76e002fca4c23.png

如上图所示,Delos 框架将多种复杂的共识算法进行了封装,它通过统一的 VirtualLog API 向上提供接口,并向下集成了多种共识算法。每个 VirtualLog 的一段被称为一个 Loglets,每个 Loglets 可以使用不同的共识算法实现。

Delos 实现了动态维护 Loglets 的功能,从而支持动态更换共识算法。值得一提的是,Delos 项目一开始实现了一个非常简单的基于 Zookeeper 的共识方案 ZKLoglets。仅仅 8 个月后,它就成功地动态更换了所有线上环境的共识算法,从 ZKLoglets 到自研的 NativeLoglets,实现了十倍的性能提升。

02

IoTDB 共识算法框架

上文介绍了共识算法和共识算法统一框架的相关概念,接下来,让我们深入 IoTDB 内部的共识算法框架,了解 IoTDB 所支持的共识算法。

(1)概念与示例

  • Node 对应一个进程,可以是一个物理节点,也可以是一个容器运行时环境。

  • ConsensusGroup 定义了一个共识组,对应分片技术的一个分片,其逻辑上存在于副本数个 Node 上,共同维护一份数据的多个副本。

  • Peer 对应 ConsensusGroup 在一个 Node 上的逻辑单元,一个 ConsensusGroup 在一个 Node 上对应一个 Peer,其在副本数个 Node 上共拥有副本数个 Peer。

  • IStateMachine 是共识组管理底层存储引擎数据的结构,用于维护数据的一份本地副本,每个 IStateMachine 逻辑上被一个 Peer 所拥有,存在于一个 Node 上。

  • IConsensus 是共识层对外提供服务的入口,管理了该 Node 中的所有 Peer,提供增删共识组、共识组成员变更、读写共识组数据等功能。开发者可以在创建 IConsensus 时通过配置参数来指定不同一致性级别的共识算法实现(例如弱一致性共识算法 IoTConsensus 和强一致性共识算法 RatisConsensus)。

如下图所示,在 IoTDB 的共识算法统一框架中,用户的一份数据将会被一个共识组 ConsensusGroup 管理,这个共识组由多个 Peer 组成,每个 Peer 通过用户自定义的 IStateMachine 管理该数据的一份本地副本。IConsensus 管理本进程中所有属于不同的共识组 PeersIConsensus 是共识层对外提供服务的入口,包括创建共识组、共识组成员变更、读写共识组数据等功能。

f79fa0a605603e0bd3ce668622f9baf6.png

对于一个 4 节点 3 副本的集群,假设集群将所有数据均分分成了 2 个分片,则示意图如下:

07e5e4aa78f43d42b4206f66c496c95c.jpeg

在上图中可以明确如下信息:

  • 整个集群共存在 4 个 Node,每个 Node 上存在一个 IConsensus 实例。

  • 整个集群共有 2 个分片,即有 2 个 ConsensusGroup。ConsensusGroup1 存在于 Node1,Node2 和 Node3 上,ConsensusGroup2 存在于 Node2,Node3 和 Node4 上。

  • Node1 的 IConsensus 管理了 ConsensusGroup1 的 Peer1,对应了 1 个 IStateMachine 实例,拥有集群的一半数据。

  • Node2 的 IConsensus 管理了 ConsensusGroup1 的 Peer2 和 ConsnesusGroup2 的 Peer1,对应了 2 个 IStateMachine 实例,拥有集群的全量数据。

  • Node3 的 IConsensus 管理了 ConsensusGroup1 的 Peer3 和 ConsnesusGroup2 的 Peer2,对应了 2 个 IStateMachine 实例,拥有集群的全量数据。

  • Node4 的 IConsensus 管理了 ConsensusGroup2 的 Peer3,对应了 1 个 IStateMachine 实例,拥有集群的一半数据。

(2)当前支持共识算法

目前共识层支持三种不同的共识算法,它们分别是:

  • SimpleConsensus单副本强一致性共识算法。专为单副本场景优化。

  • RatisConsensus多副本单主强一致性共识算法。基于 Java 语言的 Raft 算法工业实现 Apache Ratis。

2e555f4ec12e85f87d6a58913057fda9.png

  • IoTConsensus多副本多主弱一致性共识算法。这是一种为 IoT 场景设计的自研共识算法,使用 2 副本即可实现高可用。通过异步复制和大量工程优化,实现了近乎实时的同步性能。在物联网场景下,不同设备的写入操作通常是独立进行的,因此并发写入请求之间基本不存在写写冲突。基于这一特性,IoTConsensus 能够提供最终一致性甚至会话一致性的语义。

2d19e682bda132b72c8b8867282f2537.png

(3)如何配置 IoTDB 共识算法

对于 IoTDB,我们可以通过修改 iotdb-system.properties 中下面的配置项对共识算法进行配置。

共识算法选择

  • config_node_consensus_protocol_class:ConfigNode 使用的共识算法,可选择 SimpleConsensus 或者  RatisConsensus。

  • schema_region_consensus_protocol_class:元数据使用的共识算法,可选择 SimpleConsensus 或者 RatisConsensus。

  • data_region_consensus_protocol_class:普通数据使用的共识算法,可选择 SimpleConsensus 或者RatisConsensus 或者 IoTConsensus。

副本数

副本数标识了数据分片冗余存储的个数。通常来说,副本数越多,系统可用性越强,但会占用更多的存算资源。

  • schema_replication_factor:元数据副本数

  • data_replication_factor:普通数据副本数

负载均衡

Leader balance 是指让 leader 均匀分布在各个节点上,从而对于写流量进行负载均衡。我们可以选择对于 RatisConsensus 和 IoTConsensus 是否打开 leader balance。

  • enable_auto_leader_balance_for_ratis_consensus:对 RatisConsensus 开启 leader balance。

  • enable_auto_leader_balance_for_iot_consensus:对 IoTConsensus 开启 leader balance。

(4)如何选择 IoTDB 共识算法

1. SimpleConsensus:SimpleConsensus 是一种轻量级的单副本共识算法。在关注硬件成本的用户场景中,为了节约资源和成本,一些用户倾向于使用单副本的方式部署集群。SimpleConsensus 的设计旨在为用户提供一种经济的选择,以适应对扩展性要求较高而对可用性要求较低的场景。通常被用在单副本部署的场景中

2. RatisConsensus:RatisConsensus 是 Raft 协议的工业实现,为一款支持 Multi-Raft 的强一致性共识算法。通常被用在 ConfigNode 和元数据的管理场景中。值得一提的是,IoTDB 社区联合 Ratis 社区对 RatisConsensus 进行了大量工程优化,使得 RatisConsensus 在提供强一致性保证的同时,拥有相对理想的性能。

3. IoTConsensus:IoTConsensus 是由 IoTDB 团队自研的弱一致性多主共识算法。该算法结合了 IoT 场景的业务特性,进行了大量针对性的架构和工程优化,因此不仅性能更优,而且具有更强的可用性。与 RatisConsensus 需要 3 副本才能实现高可用相比,IoTConsensus 仅需 2 副本即可实现高可用,常配置两副本,这也使得其存储成本更低。该算法通常用于时序数据的管理场景

03

总结

分布式系统通过横向拓展,将数据冗余存储在多个物理节点,实现了高可用和高性能。在这个过程中,共识算法用于协调多个节点的行为,从而保证集群整体的一致性。

与业界其他时序数据库相比,Apache IoTDB 是第一个也是唯一一个提出并应用共识协议统一框架的系统。用户可以根据性能、可用性、一致性和存储成本等需求,灵活选择不同的共识算法。

值得一提的是,对于 IoTDB 社区专为 IoT 场景自研的多主弱一致性共识算法 IoTConsensus,尽管其已经拥有较高的性能和可用性,但由于使用 WAL 进行副本同步,仍然存在性能和可用性的优化空间。近期,IoTDB 团队通过使用自研数据文件 TsFile 进行数据同步,从而与 WAL 解耦,进一步优化了 IoTConsensus 的性能和可用性,从而提出了新的 FastIoTConsensus 共识算法。该新共识算法正在内测中,即将上线,敬请期待~

本文是 Apache IoTDB 分布式三部曲中的最后一篇。通过 Apache IoTDB 分布式三部曲对集群、分片与负载均衡、副本与共识算法的介绍,相信您已经深入了解了 IoTDB 的整体分布式架构与设计思想,期望三部曲系列能帮助您合理运用 IoTDB 的共识算法、负载均衡等分布式策略来应对复杂的物联网数据管理挑战!

5a1c243086ea70fff3b9b0f27e36b3d9.gif

b5d3eeb393e4daa7817f437f3fd21271.jpeg

b062305706510f935725ddd570c4bc11.jpeg

2be0f8a4fefdefa6cb74d0f5d67a8ba3.jpeg

4f7841bab47a11e4332f6a03bcb00d51.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/25041.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CNN简介与实现

CNN简介与实现 导语整体结构卷积层卷积填充步幅三维卷积立体化批处理 实现 池化层特点实现 CNN实现可视化总结参考文献 导语 CNN全称卷积神经网络,可谓声名远扬,被用于生活中的各个领域,也是最好理解的神经网络结构之一。 整体结构 相较于…

GUI编程-01

组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 Java提供了丰富的图形用户界面(Graphics User Interface,GUI)的类库,基于这些类库可以编写窗口程序。 Java关于图形界面的类库主要放在…

171.二叉树:二叉树的所有路径(力扣)

代码解决 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr, right(nullptr) {}* Tree…

LabVIEW伺服电机测控系统

LabVIEW伺服电机测控系统 开发了一个基于LabVIEW的伺服电机测控系统。系统主要用于精确控制电机的运动,以达到高效率和高精度的要求。通过使用LabVIEW软件和配套的硬件,开发者能够实现对伺服电机的实时监控和控制,进而提高整个系统的性能和可…

【Linux系统编程】进程地址空间

目录 前言 进程虚拟地址空间的引入 进程地址空间的概念 进一步理解进程地址空间 为什么需要进程地址空间? 系统层面理解malloc/new内存申请 前言 首先,在我们学习C语言的时候一定会见过如下这张图。(没见过也没关系,接下来…

【JavaScript对象详解】 Day05

JavaScript对象详解 JavaScript 基础 - 第5天对象语法对象属性对象使用属性-查属性-改属性-增属性-删 (了解) 方法和调用遍历对象遍历数组对象null 内置对象Math属性方法生成任意范围随机数 综合案例随机点名案例猜数字游戏猜数字游戏设定次数生成随机颜…

运维 之 DNS域名解析

前言 我们每天打开的网站,他是如何来解析,并且我们怎么能得到网站的内容反馈的界面呢?那什么是DNS呢(DNS(DomainNameservice,域名服务,主要用于因特网上作为域名和IP地址相互映射)那…

React的表单学习

react的表单的双向绑定 // userState实现计数实例 import {useState} from react// 1.声明一个react的状态 -useState// 2.核心绑定流程//1.通过value属性绑定react状态//2.绑定onChange事件,通过事件参数e拿到输入框最新的值,反向修改到react状态 func…

机器学习与数据挖掘知识点总结(二)之常用的分类算法

目录 1、什么是数据挖掘 2、为什么要有数据挖掘 3、数据挖掘用在分类任务中的算法 朴素贝叶斯算法 svm支持向量机算法 PCA主成分分析算法 k-means算法 决策树 1、什么是数据挖掘 数据挖掘是从大量数据中发现隐藏在其中的模式、关系和规律的过程。它利用统计学、机器学…

Kafka监控系统efak的安装

下载地址Kafka Eaglehttp://download.kafka-eagle.org/下载地址连接不稳定,可以多次尝试直到成功连接下载 1.解压安装包并重命名 tar -zxvf kafka-eagle-bin-3.0.1.tar.gz 查看到解压后包含一个安装包,再解压 tar -zxvf efak-web-3.0.1-bin.tar.gz 移…

【Nacos 2.3.3支持Postgre SQL数据源配置】

Nacos 2.3.3支持Postgre SQL数据源配置 1、Nacos下载2、 插件下载:3、SQL脚本获取、nacos数据库创建、插件编译4、Nacos 集群搭建方式: 1、Nacos下载 下载地址: https://download.nacos.io/nacos-server/nacos-server-2.3.2.zip 或者自行在官…

1.Vue2使用ElementUI-初识及环境搭建

目录 1.下载nodejs v16.x 2.设置淘宝镜像源 3.安装脚手架 4.创建一个项目 5.项目修改 代码地址:source-code: 源码笔记 1.下载nodejs v16.x 下载地址:Node.js — Download Node.js 2.设置淘宝镜像源 npm config set registry https://registry.…

SpringCloud-OpenFeign拓展-连接池、最佳使用方法、日志输出

目录 1 OpenFeign连接池 1.1 常见连接类型 1.2 连接池使用方法 1.2.1 引入依赖 1.2.2 开启连接池功能 1.2.3 配置完成,重启实例即可,底层将更改设置。 2 OpenFeign最佳使用方法 2.1 每个微服务都是单独的project,内部有三个独立模块 …

Docker:认识镜像仓库及其命令

文章目录 Docker Registry什么是Docker Registry 镜像仓库工作机制使用流程实际使用方法仓库的拉取机制 常用的镜像仓库---DockerHub什么是DockerHub私有仓库 镜像仓库命令docker logindocker pulldocker pushdocker searchdocker logout Docker Registry 什么是Docker Regist…

编译遇到找不到pcap.so 问题

1.locate 定义pcap.so locate pcap.so 如果存在则打印所有路径 使用软连接将pcap.so 的实际位置连接到编译的lib 目录下 ln -s /usr/lib/x86_64-linux-gnu/libpcap.so /usr/lib/libpcap.so 编译 提示 说明程序中编译的目标程序需要的库与现有的不兼容,一般都是3…

Mysql使用中的性能优化——单次插入和批量插入的性能差异

一般Mysql的客户端和服务端不在一台机器上,所以它们之间的通信需要通过网络进行。我们本次实验,希望抛开网络的影响,测试不同SQL方案在Mysql服务器上的执行效率的对比。于是我们使用“存储过程”来辅助测试。 结论 先上结论: 批…

Servlet基础(续集)

Servlet原理 Servlet是由Web服务器调用&#xff0c;Web服务器在收到浏览器请求之后&#xff0c;会&#xff1a; Mapping问题 一个Servlet可以指定一个映射路径 <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pa…

vue3 实现自定义指令封装 --- 通俗易懂

1、局部自定义指令 1.1 在<script setup>定义组件内的指令&#xff0c;任何以v开头的驼峰式命名的变量都可以被用作一个自定义指令 <template><div><h3>使用自定义指令</h3><div>########################## start 局部自定义指令</d…

Docker大学生看了都会系列(八、Dokcerfile部署go项目)

系列文章目录 第一章 Docker介绍 第二章 2.1 Mac通过Homebrew安装Docker 第二章 2.2 CentOS安装Docker 第三章 Docker常用命令 第四章 常用命令实战 第五章 Docker镜像详解 第六章 Docker容器数据卷 第七章 Dockerfile详解 第八章 Dokcerfile部署go项目 文章目录 一、前言二、环…

解决Android Studio Iguana版本不显示原创的GradleTask问题

问题描述&#xff1a; 下面是我的AndroidStudio版本号&#xff0c;升级后我发现项目里面自定义的gradletask找不到了&#xff1f;&#xff1f;&#xff1f; 解决方案&#xff1a; 1、去setting里面把下面红框里面的选项勾选一下&#xff0c;缺点就是sync的时候会慢一些。 2、…