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

《Elasticsearch 源码解析与优化实战》第5章:选主流程

《Elasticsearch 源码解析与优化实战》第5章:选主流程 - 墨天轮

一、简介

Discovery 模块负责发现集群中的节点,以及选择主节点。ES 支持多种不同 Discovery 类型选择,内置的实现称为Zen Discovery
,其他的包括公有云平台亚马逊的EC2、谷歌的GCE等。

本章讨论内置的 Zen Discovery 实现。Zen Discovery 封装了节点发现(Ping)、选主等实现过程,现在我们先讨论选主流程,在后面的章节中整体性介绍Discovery模块。

二、设计思想

所有分布式系统都需要以某种方式处理一致性问题。一般情况下,可以将策略分为两组

  • 试图避免不一致

  • 及定义发生不一致之后如何协调它们。后者在适用场景下非常强大,但对数据模型有比较严格的限制。因此这里研究前者,以及如何应对网络故障。

三、为什么使用主从模式

除主从(Leader/Follower) 模式外,另一种选择是分布式哈希表(DHT),可以支持每小时数千个节点的离开和加入,其可以在不了解底层网络拓扑的异构网络中工作,查询响应时间大约为4到10跳(中转次数),例如,Cassandra 就使用这种方案。但是在相对稳定的对等网络中,主从模式会更好。

ES的典型场景中的另一个简化是集群中没有那么多节点。通常,节点的数量远远小于单个节点能够维护的连接数,并且网络环境不必经常处理节点的加入和离开。这就是为什么主从模式更合适ES。

四、选举算法

在主节点选举算法的选择上,基本原则是不重复造轮子。最好实现一个众所周知的算法,这样的好处是其中的优点和缺陷是已知的。ES的选举算法的选择上主要考虑下面两种。

4.1、Bully算法

Leader 选举的基本算法之一。它假定所有节点都有一个唯一的 ID,使用该ID对节点进行排序。任何时候的当前Leader都是参与集群的最高ID节点。 该算法的优点是易于实现。但是,当拥有最大ID的节点处于不稳定状态的场景下会有问题。例如,Master 负载过重而假死,集群拥有第二大ID的节点被选为新主,这时原来的Master恢复,再次被选为新主,然后又假死......

ES通过推迟选举,直到当前的Master 失效来解决上述问题,只要当前主节点不挂掉,就不重新选主。但是容易产生脑裂(双主),为此,再通过“法定得票人数过半”解决脑裂问题。

4.2、Paxos算法

Paxos非常强大,尤其在什么时机,以及如何进行选举方面的灵活性比简单的Bully算法有很大的优势,因为在现实生活中,存在比网络连接异常更多的故障模式。但Paxos实现起来非常复杂。

五、相关配置

与选主过程相关的重要配置有下列几个,并非全部配置。

discovery.zen.minimum_master_nodes
:最小主节点数,这是防止脑裂、防止数据丢失的极其重要的参数。这个参数的实际作用早已超越了其表面的含义。除了在选主时用于决定“多数”,还用于多处重要的判断,至少包含以下时机:

  • 触发选主: 进入选主的流程之前,参选的节点数需要达到法定人数。

  • 决定Master: 选出临时的Master之后,这个临时Master需要判断加入它的节点达到法定人数,才确认选主成功。

  • gateway选举元信息: 向有 Master 资格的节点发起请求,获取元数据,获取的响应数量必须达到法定人数,也就是参与元信息选举的节点数。

  • Master发布集群状态: 发布成功数量为多数。

为了避免脑裂,它的值应该是半数以上(quorum):(master_eligible_nodes 2)+1

例如:如果有3个具备Master资格的节点,则这个值至少应该设置为(3/2) + 1=2。该参数可以动态设置:
PUT _cluster/settings
{"persistent" : {"discovery.zen.minimum master_nodes" : 2}
}

discovery.zen.ping.unicast.hosts
:**集群的种子节点列表,构建集群时本节点会尝试连接这个节点列表,那么列表中的主机会看到整个集群中都有哪些主机。**可以配置为部分或全部集群节点。可以像下面这样指定:

discovery.zen.ping.unicast.hosts:-192.168.1.10:9300-192.168.1.11-seeds.mydomain.com

默认使用9300端口,如果需要更改端口号,则可以在IP后手工指定端口。也可以设置一个域名,让该域名解析到多个IP地址,ES会尝试连接这个IP列表中的全部地址。

  • discovery.zen.ping.unicast.hosts.resolve_timeout: DNS
    解析超时时间,默认为5秒。

  • discovery.zen.join_timeout
    : 节点加入现有集群时的超时时间,默认为ping_ timeout的20倍。

  • discovery.zen.join_retry_attemptsjoin_timeout
    :超时之后的重试次数,默认为3次。

  • discovery.zen.join_retry_delayjoin_timeout
    :超时之后,重试前的延迟时间,默认为100毫秒。

  • discovery.zen.master_election.ignore_non_master_ pings
    :设置为true时,选主阶段将忽略来自不具备Master资格节点(node.master: false)的ping请求,默认为false。

  • discovery.zen.fd.ping_interval
    :故障检测间隔周期,默认为1秒。

  • discovery.zen.fd.ping_timeout
    :故障检测请求超时时间,默认为30秒。

  • discovery.zen.fd.ping_retries
    :故障检测超时后的重试次数,默认为3次。

六、流程分析

6.0、流程概述

6.0.1、ZenDiscovery的选主过程如下:

  • 每个节点计算最小的已知节点 ID,该节点为临时Master。向该节点发送领导投票

  • 如果一个节点收到足够多的票数,并且该节点也为自己投票,那么它将扮演领导者的角色,开始发布集群状态

  • 所有节点都会参与选举,并参与投票,但是,只有有资格成为Master的节点(node.maste为true)的投票才有效。

获得多少选票可以赢得选举胜利,就是所谓的法定人数。在ES中,法定大小是一个可配置的参数。配置项: discovery.zen.minimum master_ nodes
。为了避免脑裂,最小值应该是有Maste资格的节点数n/2+1

6.0.2、整体流程可以概括为:

  • 选举临时Master;

  • 投票-确认Master,如果本节点当选,则等待确立Master,如果其他节点当选,则尝试加入集群,然后启动节点失效探测器;

  • 失效节点探测;

具体如下图所示。

执行本流程的线程池: generic。

下面我们具体分析每个步骤的实现。

6.1、选举临时Master

选举过程的实现位于ZenDiscovery#findMaster
。该函数查找当前集群的活跃Master,或者从候选者中选择新的Master。如果选 主成功,则返回选定的Master,否则返回空。

为什么是临时Master?因为还需要等待下一个步骤,该节点的得票数足够时,才确立为真正的Master。

临时Master的选举过程如下:

  • "ping"所有节点,获取节点列表 fullPingResponses, ping结果不包含本节点,把本节点单独添加到fullPingResponses中。

  • 构建两个列表。

    • activeMasters列表: 存储集群当前活跃Master列表。

    • masterCandidates列表: 存储master候选者列表

activeMasters列表:存储集群当前活跃Master列表。 遍历第一步 获取的所有节点,将每个节点所认为的当前Master节点加入activeMasters 列表中(不包括本节点)。在遍历过程中,如果配置了discovery.zen.master_election.ignore_non_master_pings
为true ( 默认为false),而节点又不具备Master资格,则跳过该节点。

具体流程如下图所示。

在这里插入图片描述

这个过程是将集群当前已存在的Master加入activeMasters列表,正常情况下只有一个。如果集群已存在Master,则每个节点都记录了当前Master是哪个,考虑到异常情况下,可能各个节点看到的当前Master不同。在构建activeMasters列表过程中,如果节点不具备Master资格,则可以通过ignore_non_master_pings
选项忽略它认为的那个Master。

masterCandidates列表:存储master候选者列表。 遍历第一步获取列表,去掉不具备Maste资格的节点,添加到这个列表中。如果activeMasters为空,则从masterCandidates中选举,结果可能选举成功,也可能选举失败。如果不为空,则从activeMasters中选择最合适的作为Master。

整体流程如下图所示。

在这里插入图片描述

6.1.1、从masterCandidates
中选主

与选主的具体细节实现封装在 ElectMasterService 类中,例如,判断候选者是否足够,选择具体的节点作为Master等。

从 masterCandidates 中选主时,首先需要判断当前候选者人数是否达到法定人数,否则选主失败。

public boolean hasEnoughCandidates (Collection<MasterCandidate> candidates) {//候选者为空,返回失败if (candidates.isEmpty()) {returnfalse;}//默认值为-1, 确保单节点的集群可以正常选主if (minimumMasterNodes < 1) {returntrue;}return candidates .size () >= minimumMasterNodes;
}

当候选者人数达到法定人数后,从候选者中选一个出来做Master:

public MasterCandidate electMaster (Collection<MasterCandidate> candidates) {List<MasterCandidate> sortedCandidates = new ArrayList<> (candidates);//通过自定义的比较函数对候选者节点从小到大排序sortedCandidates.sort (MasterCandidate :: compare);//返回最新的作为Masterreturn sortedCandidates.get(0);
}

可以看出这里只是将节点排序后选择最小的节点作为Master。但是排序时使用自定义的比较函数MasterCandidate::compare,早期的版本中只是对节点ID进行排序,现在会优先把集群状态版本号高的节点放在前面。

使用默认比较函数的情况下,sort结果为从小到大排序。参考Long类型的比较函数的实现:

public static int compare (1ong X,long y) {return(x<y)?-1:((x==y)?0:1);
}自定义比较函数的实现:
public static int compare(MasterCandidate cl, MasterCandidate c2) {//先比较集群状态版本,注意此处c2在前,c1在后int ret = Long.compare(c2.clusterStateVersion, c1.clusterStateVersion);//如果版本号相同,则比较节点IDif(ret==0){ret = compareNodes (c1.getNode(),c2.getNode());}return ret;
}

节点比较函数compareNodes的实现: 对于排序效果来说

  • 如果传入的两个节点中,有一个节点具备Master资格,而另一个不具备,则把有Master资格的节点排在前面。

  • 如果都不具备Master资格,或者都具备Master资格,则比较节点ID。

但是,masterCandidates 列表中的节点都是具备Master资格的。compareNodes 比较函数的两个if判断是因为在别的函数调用中会存在节点列表中可能存在不具备Master资格节点的情况。因此此处只会比较节点ID。

private static int compareNodes (DiscoveryNode o1, DiscoveryNode o2) {//两个if处理两节点中一个具备Master资格而另一个不具备的情况if (o1.isMasterNode() && !o2.isMasterNode () ) {return -1;}if (!o1.isMasterNode() && o2.isMasterNode()) {return1;}//通过节点ID排序return o1.getId().compareTo(o2.getId());
}

从 activeMasters 列表中选择列表存储着集群当前存在活跃的Master,从这些已知的Master节点中选择一个作为选举结果。选择过程非常简单,取列表中的最小值,比较函数仍然通过compareNodes实现,activeMasters 列表中的节点理论情况下都是具备Master资格的。

public DiscoveryNode tieBreakActiveMasters (Collection<DiscoveryNode> activeMasters)return activeMasters.stream().min(ElectMasterService ::compareNodes).get();
}

6.1.2、投票与得票的实现

在ES中,发送投票就是发送加入集群(JoinRequest)请求。得票就是申请加入该节点的请求的数量。收集投票,进行统计的实现在ZenDiscovery#handleJoinRequest
方法中,收到的连接被存储到ElectionContext#joinRequestAccumulator
中。当节点检查收到的投票是否足够时,就是检查加入它的连接数是否足够,其中会去掉没有Master资格节点的投票。

public synchronized int getPendingMasterJoinsCount() {int pendingMasterJoins = 0;//遍历当前收到的join请求for (DiscoveryNode node : joinReques tAccumulator .keySet()) {//过滤不具备master资格的节点if (node. isMasterNode()) {pendingMasterJoins++;}}return pendingMasterJoins;
}

6.1.3、确立Master或加入集群

选举出的临时Master 有两种情况:该临时Master是本节点或非本节点。为此单独处理。现在准备向其发送投票。

6.1.3.1、如果临时Master是本节点:

  • 等待足够多的具备Master资格的节点加入本节点(投票达到法定人数),以完成选举。超时(默认为30秒,可配置)后还没有满足数量的join请求,则选举失败,需要进行新一轮选举。

  • 成功后发布新的clusterState。

6.1.3.2、如果其他节点被选为Master:

  • 不再接受其他节点的join请求。

  • 向Master发送加入请求,并等待回复。超时时间默认为1分钟(可配置),如果遇到异常,则默认重试了3次(可配置)。这个步骤在joinElectedMaster方法中实现。

  • 最终当选的Master会先发布集群状态,才确认客户的join请求,因此, joinElectedMaster返回代表收到了join请求的确认,并且已经收到了集群状态。本步骤检查收到的集群状态中的Master节点如果为空,或者当选的Master不是之前选择的节点,则重新选举。

6.2、节点失效检测

到此为止,选主流程已执行完毕,Master 身份已确认,非Master节点已加入集群。节点失效检测会监控节点是否离线,然后处理其中的异常。失效检测是选主流程之后不可或缺的步骤,不执行失效检测可能会产生脑裂(双主或多主)。在此我们需要启动两种失效探测器:

  • 在Master节点,   启动 NodesFaultDetection
    ,简称NodesFD。定期探测加入集群的节点是否活跃。

  • 在非Master节点,启动MasterFaultDetection
    ,简称MasterFD。定期探测Master节点是否活跃。

NodesFaultDetection和MasterFaultDetection都是通过定期(默认为1秒)发送的ping请求探测节点是否正常的,当失败达到一定次数(默认为3次),或者收到来自底层连接模块的节点离线通知时,开始处理节点离开事件。

6.2.1、NodesFaultDetection 事件处理

检查一下当前集群总节点数是否达到法定节点数(过半),如果不足,则会放弃Master身份,重新加入集群。 为什么要这么做?设想下面的场景,如下图所示。

在这里插入图片描述

假设有5台机器组成的集群产生网络分区,2台组成一组,另外3台组成一组,产生分区前,原Master为Node1。此时3台一组的节点会重新选举并成功选取Noded3作为Master,会不会产生双主? NodesFaultDetection
就是为了避免上述场景下产生双主。

对应事件处理主要实现如下:在ZenDiscovery#handleNodeFailure
中执行NodeRemoval-ClusterStateTaskExecutor#execute

public ClusterTasksResult<Task> execute (final ClusterState currentState, final List<Task> tasks) throws Exception {//判断剩余节 点是否达到法定人数if (electMasterService.hasEnoughMasterNodes (remainingNodesClusterState.nodes()) == false) {finalint masterNodes = electMas terService.countMasterNodes(remainingNodesClusterState.nodes());rejoin.accept(LoggerMessageFormat.format("not enough master nodes(has \[{}\], but needed \[{}\])", masterNodes, electMasterService.minimumMasterNodes()));return resultBuilder .build (currentState) ;} else {return resultBuilder.build (allocationService.deassociateDeadNodes(remainingNodesClusterState, true, describeTasks(tasks)));}
}

主节点在探测到节点离线的事件处理中,如果发现当前集群节点数量不足法定人数,则放弃Master身份,从而避免产生双主。

6.2.2、MasterFaultDetection事件处理


**探测Master离线的处理很简单,重新加入集群。**本质上就是该节点重新执行一遍选主的流程。对应事件处理主要实现如下: ZenDiscovery#handleMasterGone

private void handleMasterGone (final DiscoveryNode masterNode, final Throwable cause, final String reason) {synchronized(stateMutex) {if (localNodeMaster() == false && masterNode.equals (committedState.get().nodes ().getMasterNode())) {pendingStatesQueue.failAllStatesAndClear (new ElasticsearchException("master left\[\[)\]", reason));//重新加入集群rejoin ("master left (reason = " + reason + ")");}}
}

小结

选主流程在集群中启动,从无主状态到产生新主时执行,同时集群在正常运行过程中,Master探测到节点离开,非Master节点探测到Master离开时都会执行。

相关文章:

《Elasticsearch 源码解析与优化实战》第5章:选主流程

《Elasticsearch 源码解析与优化实战》第5章&#xff1a;选主流程 - 墨天轮 一、简介 Discovery 模块负责发现集群中的节点&#xff0c;以及选择主节点。ES 支持多种不同 Discovery 类型选择&#xff0c;内置的实现称为Zen Discovery ,其他的包括公有云平台亚马逊的EC2、谷歌…...

Spring Cloud Alibaba - Nacos源码分析(三)

目录 一、Nacos客户端服务订阅的事件机制 1、监听事件的注册 2、ServiceInfo处理 serviceInfoHolder.processServiceInfo 一、Nacos客户端服务订阅的事件机制 Nacos客户端订阅的核心流程&#xff1a;Nacos客户端通过一个定时任务&#xff0c;每6秒从注册中心获取实例列表&…...

DOCKER镜像和容器

1.前言 ​ 初见DOCKER&#xff0c;感觉和我们常用的虚拟机&#xff08;VMware&#xff0c;viurebox&#xff09;类似&#xff0c;是一个独立于宿主机的模块&#xff0c;可以解决程序在各个系统间的移植&#xff0c;但它真的仅仅是这样嘛&#xff1f; 2.容器的优缺点 1.1.容器…...

探索网页原型设计:构建出色的用户体验

在当今数字化时代&#xff0c;用户对网页体验的要求日益提高。在网页设计过程中&#xff0c;扮演着至关重要的角色。通过网页原型设计&#xff0c;产品经理能够更好地展示和传达网页的整体布局、导航结构、元素位置和交互效果&#xff0c;从而使团队成员更清晰地了解设计意图&a…...

48,排序算法merge

功能描述&#xff1a; 两个容器元素合并&#xff0c;并储存到另一容器中 函数原型&#xff1a; merge(iterator beg1,iterator end1,iterator beg2,iterator end2,iterator dest); //容器元素合并&#xff0c;并存储到另一个容器中 //注意&#xff1a;两个容器必须是有序的…...

【MySQL】复合查询

复合查询目录 一、基本查询二、多表查询三、自连接四、子查询4.1 单行子查询4.2 多行子查询4.3 多列子查询4.4 在from子句中使用子查询4.5 合并查询4.5.1 union4.5.2 union all 五、实战OJ 一、基本查询 --查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的…...

JavaScript中的this指向及绑定规则

在JavaScript中&#xff0c;this是一个特殊的关键字&#xff0c;用于表示函数执行的上下文对象&#xff0c;也就是当前函数被调用时所在的对象。由于JavaScript的函数调用方式多种多样&#xff0c;this的指向也因此而变化。本文将介绍JavaScript中this的指向及绑定规则&#xf…...

css中预编译理解,它们之间区别

css预编译&#xff1f; css预编译器用一种专门的编程语言&#xff0c;它可以对web页面样式然后再编译成正常css文件&#xff0c;可以更加方便和高效的编写css代表。主要作用就是为css提供了变量&#xff0c;函数&#xff0c;嵌套&#xff0c;继承&#xff0c;混合等功能&#…...

如何使用Java处理JSON数据?

在Java中&#xff0c;您可以使用许多库来处理JSON数据。以下是使用一种常见的库 Gson 的示例&#xff1a; 首先&#xff0c;确保您已经将 Gson 库添加到您的项目中。您可以在 Maven 中添加以下依赖项&#xff1a; <dependency><groupId>com.google.code.gson<…...

java设计模式-观察者模式

什么是观察者模式 观察者模式&#xff08;Observer&#xff09;是软件设计中的一种行为模式。 它定义了对象之间的一对多关系&#xff0c;其中如果一个对象改变了状态&#xff0c;所有依赖它的对象都会自动被通知并更新。 这种模式包含了两种主要的角色&#xff0c;即被观察…...

HiveSQL SparkSQL中常用知识点记录

目录 0. 相关文章链接 1. hive中多表full join主键重复问题 2. Hive中选出最新一个分区中新增和变化的数据 3. Hive中使用sort_array函数解决collet_list列表排序混乱问题 4. SQL中对小数位数很多的数值转换成文本的时候不使用科学计数法 5. HiveSQL & SparkSQL中炸裂…...

mac不识别移动硬盘导致无法拷贝资源

背景 硬盘插入到Mac电脑上之后&#xff0c;mac不识别移动硬盘导致无法拷贝资源。 移动硬盘在Mac上无法被识别的原因可能有很多&#xff0c;多数情况下&#xff0c;是硬盘的格式与Mac电脑不兼容。 文件系统格式不兼容 macOS使用的文件系统是HFS或APFS&#xff0c;如果移动硬盘是…...

Opencv的Mat内容学习

来源&#xff1a;Opencv的Mat内容小记 - 知乎 (zhihu.com) 1.Mat是一种图像容器&#xff0c;是二维向量。 灰度图的Mat一般存放<uchar>类型 RGB彩色图像一般存放<Vec3b>类型。 (1)单通道灰度图数据存放样式&#xff1a; (2)RGB三通道彩色图存放形式不同&#x…...

MySQL~数据库的设计

二、数据库的设计 1、多表之间的关系 1.1 三种分类 一对一&#xff1a; 分析&#xff1a;一个人只有一个身份证&#xff0c;一个身份证只能对应一个人 如&#xff1a;人和身份证 一对多&#xff1a; 如&#xff1a;部门和员工 分析&#xff1a;一个部门有多个员工&#xff…...

开源了!最强原创图解八股文面试网来袭

强烈推荐 Github上业内新晋的一匹黑马—Java图解八股文面试网—Java2Top.cn&#xff0c;图解 Java 大厂面试题&#xff0c;深入全面&#xff0c;真的强烈推荐~ 这是一个二本逆袭阿里的大佬根据自己秋招上岸所看过的相关专栏&#xff0c;面经&#xff0c;课程&#xff0c;结合自…...

微信小程序开发6

一、分包-基础概念 1.1、什么是分包 分包指的是把一个完整的小程序项目&#xff0c;按照需求划分为不同的子包&#xff0c;在构建时打包成不同的分包&#xff0c;用户在使用时按需进行加载。 1.2、分包的好处 对小程序进行分包的好处主要有以下两点&#xff1a; 可以优化小程序…...

JS 根据身份证号获取年龄、性别、出生日期

先说一代身份证和二代身份证的区别: 1.编号位数不同&#xff0c;第一代身份证为15位号码&#xff0c;第二代证是18位号码 2.编码规则不同&#xff0c;第一代身份证在前6位号码后没有完整出生年份&#xff0c;而二代的有完整的出生年份&#xff0c;一代身份证将年份前二位省略…...

Python+Mongo+LSTM(GTP生成)

下面是一个简单的示例来展示如何使用Python和MongoDB来生成LSTM预测算法。 首先&#xff0c;我们需要安装pymongo和tensorflow库&#xff0c;可以使用以下命令进行安装&#xff1a; pip install pymongo tensorflow接下来&#xff0c;我们连接到MongoDB数据库并获取需要进行预…...

关于idea如何成功运行web项目

导入项目 如图 依次选择 file - new - Project from Existing Sources 选择存放的项目目录地址 如图 导入完成 点击ok 如图 依次选择 Create project from existing sources 点击next如图 &#xff0c;此处默认即可 点击 next如图 点击next有该提示 是因为之前导入过…...

python读取json文件

import json# 文件路径(同目录文件名即可,不同目录需要绝对路径) path 1.json# 读取JSON文件 with open(path, r, encodingutf-8) as file:data json.load(file)#data为字典 print(data) print(type(data))...

迁移学习、微调、计算机视觉理论(第十一次组会ppt)

@TOC 数据增广 迁移学习 微调 目标检测和边界框 区域卷积神经网络R—CNN...

特殊矩阵的压缩存储

1 数组的存储结构 1.1 一维数组 各数组元素大小相同&#xff0c;且物理上连续存放。第i个元素的地址位置是&#xff1a;a[i] LOC i*sizeof(ElemType) (LOC为起始地址) 1.2 二维数组 对于多维数组有行优先、列优先的存储方法 行优先&#xff1a;先行后列&#xff0c;先存储…...

【网络原理】 (1) (应用层 传输层 UDP协议 TCP协议 TCP协议段格式 TCP内部工作机制 确认应答 超时重传 连接管理)

文章目录 应用层传输层UDP协议TCP协议TCP协议段格式TCP内部工作机制确认应答超时重传 网络原理部分我们主要学习TCP/IP协议栈这里的关键协议(TCP 和 IP),按照四层分别介绍.(物理层,我们不涉及). 应用层 我们需要学会自定义一个应用层协议. 自定义协议的原因? 当前的软件(应用…...

【SQL语句】

目录 一、SQL语句类型 1.DDL 2.DML 3.DLL 4.DQL 二、数据库操作 1.查看 2.创建 2.1 默认字符集 2.2 指定字符集 3.进入 4.删除 5.更改 5.1 库名称 5.2 字符集 三、数据表操作 1.数据类型 1.1 数值类型&#xff08;常见&#xff0c;下同&#xff09; 1.1.1 T…...

自动驾驶和机器人学习和总结专栏汇总

汇总如下&#xff1a; 一. 器件选型心得&#xff08;系统设计&#xff09;--1_goldqiu的博客-CSDN博客 一. 器件选型心得&#xff08;系统设计&#xff09;--2_goldqiu的博客-CSDN博客 二. 多传感器时间同步方案&#xff08;时序闭环&#xff09;--1 三. 多传感器标定方案&…...

【C++初阶】C++基础(下)——引用、内联函数、auto关键字、基于范围的for循环、指针空值nullptr

目录 1. 引用 1.1 引用概念 1.2 引用特性 1.3 常引用 1.4 使用场景 1.5 传值、传引用效率比较 1.6 引用和指针的区别 2. 内联函数 2.1 概念 2.2 特性 3.auto关键字&#xff08;C11&#xff09; 3.1 类型别名思考 3.2 auto简介 3.3 auto的使用细则 3.4 auto不能推…...

OSI 7层模型 TCPIP四层模型

》Ref&#xff1a; 1. 这个写的嘎嘎好&#xff0c;解释了为啥4层7层5层&#xff0c;还有数据包封装的问题:数据包在网络中的传输过程详解_数据包传输_张孟浩_jay的博客-CSDN博客 2. HTTP协议 与 TCP协议 的区别&#xff0c;作为web程序员必须要懂 - 知乎 (zhihu.com) 3. 数据…...

iOS-持久化

目的 1.快速展示&#xff0c;提升体验 已经加载过的数据&#xff0c;用户下次查看时&#xff0c;不需要再次从网络&#xff08;磁盘&#xff09;加载&#xff0c;直接展示给用户 2.节省用户流量&#xff08;节省服务器资源&#xff09; 对于较大的资源数据进行缓存&#xf…...

PC音频框架学习

1.整体链路 下行播放&#xff1a; App下发音源→CPU Audio Engine 信号处理→DSP数字信号处理→Codec DAC→PA→SPK 上行录音&#xff1a; MIC拾音→集成运放→Codec ADC→DSP数字信号处理→CPU Audio Engine 信号处理→App 2.硬件 CPU PCH DSP(可选) Codec PA SPKbox MIC…...

机器学习:提取问题答案

模型BERT 任务&#xff1a;提取问题和答案 问题的起始位置和结束位置。 数据集 数据集 DRCDODSQA 先分词&#xff0c;然后tokenize 文章长度是不同的&#xff0c;bert的token的长度有限制&#xff0c;一般是512&#xff0c; self-attention的计算量是 O ( n 2 ) O(n^2) O(n…...