Zookeeper选举算法与提案处理概览

共识算法(Consensus Algorithm)

共识算法即在分布式系统中节点达成共识的算法,提高系统在分布式环境下的容错性。
依据系统对故障组件的容错能力可分为:

  • 崩溃容错协议(Crash Fault Tolerant, CFT) : 无恶意行为,如进程崩溃,只要失败的quorum不过半即可正常提供服务
  • 拜占庭容错协议(Byzantine Fault Tolerant, BFT): 有恶意行为,只要恶意的quorum不过1/3即可正常提供服务

分布式环境下节点之间是没有一个全局时钟和同频时钟,故在分布式系统中的通信天然是异步的。
而在异步环境下是没有共识算法能够完全保证一致性(极端场景下会出现不一致,通常是不会出现)

In a fully asynchronous message-passing distributed system, in which at least one process may have a crash failure,
it has been proven in the famous 1985 FLP impossibility result by Fischer, Lynch and Paterson that a deterministic algorithm for achieving consensus is impossible.

另外网络是否可以未经许可直接加入新节点也是共识算法考虑的一方面,
未经许可即可加入的网络环境会存在女巫攻击(Sybil attack)

分布式系统中,根据共识形成的形式可分为

  • Voting-based Consensus Algorithms: Practical Byzantine Fault Tolerance、HotStuff、Paxos、 Raft、 ZAB …
  • Proof-based Consensus Algorithms: Proof-of-Work、Proof-of-Stake …

Zookeeper模型与架构

A Distributed Coordination Service for Distributed Applications:
ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.

Zookeeper(后简称zk)定位于分布式环境下的元数据管理,而不是数据库,zk中数据存在内存中,所以不适合存储大量数据。
zk以形如linux文件系统的树形层级结构管理数据,如下图所示:

在这里插入图片描述

每一个节点称为一个znode除了存放用户数据(一般为1KB以内)还包含变更版本、变更时间、ACL信息等统计数据(Stat Structure):

  • czxid: The zxid of the change that caused this znode to be created.
  • mzxid: The zxid of the change that last modified this znode.
  • pzxid: The zxid of the change that last modified children of this znode.
  • ctime: The time in milliseconds from epoch when this znode was created.
  • mtime: The time in milliseconds from epoch when this znode was last modified.
  • version: The number of changes to the data of this znode.
  • cversion: The number of changes to the children of this znode.
  • aversion: The number of changes to the ACL of this znode.
  • ephemeralOwner: The session id of the owner of this znode if the znode is an ephemeral node. If it is not an ephemeral node, it will be zero.
  • dataLength: The length of the data field of this znode.
  • numChildren: The number of children of this znode.

同时znode节点可设置为以下特性:

  • ephemeral: 和session生命周期相同
  • sequential: 顺序节点,比如创建顺序节点/a/b,则会生成/a/b/0000000001 ,再次创建/a/b,则会生成/a/b/0000000002
  • container: 容器节点,用于存放其他节点的节点,子节点无则它也无了,监听container节点需要考虑节点不存在的情况

Zookeeper集群中节点分为三个角色:

  • Leader:它负责 发起并维护与各 Follower 及 Observer 间的心跳。所有的写操作必须要通过 Leader 完成再由 Leader 将写操作广播给其它服务器。一个 Zookeeper 集群同一时间只会有一个实际工作的 Leader。
  • Follower:它会响应 Leader 的心跳。Follower 可直接处理并返回客户端的读请求,同时会将写请求转发给 Leader 处理,并且负责在 Leader 处理写请求时对请求进行投票。一个 Zookeeper 集群可能同时存在多个 Follower。
  • Observer:角色与 Follower 类似,但是无投票权。

为了保证事务的顺序一致性,ZooKeeper 采用了递增的zxid来标识事务,zxid(64bit)由epoch(32bit)+counter(32bit)组成,如果counter溢出会强制重新选主,开启新纪元,如果epoch满了呢?

读操作可以在任意一台zk集群节点中进行,包括watch操作也是,但写操作需要集中转发给Leader节点进行串行化执行保证一致性。
Leader 服务会为每一个 Follower 服务器分配一个单独的队列,然后将事务 Proposal 依次放入队列中,并根据 FIFO(先进先出) 的策略进行消息发送。Follower 服务在接收到 Proposal 后,会将其以事务日志的形式写入本地磁盘中,并在写入成功后反馈给 Leader 一个 Ack 响应。
当 Leader 接收到超过半数 Follower 的 Ack 响应后,就会广播一个 Commit 消息给所有的 Follower 以通知其进行事务提交,之后 Leader 自身也会完成对事务的提交。而每一个 Follower 则在接收到 Commit 消息后,完成事务的提交。
这个流程和二阶段提交很像,只是ZAB没有二阶段的回滚操作。

ZAB(Zookeeper Atomic Broadcast)

Fast Leader Election(FLE)

  • myid: 即sid,有cfg配置文件配置,每个节点之间不重复
  • logicalclock: 即electionEpoch,选举逻辑时钟

public class FastLeaderElection implements Election {// ...public Vote lookForLeader() throws InterruptedException {self.start_fle = Time.currentElapsedTime();try {/** The votes from the current leader election are stored in recvset. In other words, a vote v is in recvset* if v.electionEpoch == logicalclock. The current participant uses recvset to deduce on whether a majority* of participants has voted for it.*/// 投票箱, sid : VoteMap<Long, Vote> recvset = new HashMap<>();/** The votes from previous leader elections, as well as the votes from the current leader election are* stored in outofelection. Note that notifications in a LOOKING state are not stored in outofelection.* Only FOLLOWING or LEADING notifications are stored in outofelection. The current participant could use* outofelection to learn which participant is the leader if it arrives late (i.e., higher logicalclock than* the electionEpoch of the received notifications) in a leader election.*/// 存放上一轮投票和这一轮投票 & (FOLLOWING/LEADING)状态的peer的投票// 如果有(FOLLOWING/LEADING)的投票来迟了(即已经选出了leader但是当前节点接收ack的notification迟了),// 可根据outofelection来判断leader是否被quorum ack了,是则跟随该leaderMap<Long, Vote> outofelection = new HashMap<>();int notTimeout = minNotificationInterval;synchronized (this) {// 更新当前electionEpochlogicalclock.incrementAndGet();// 更新投票为自己updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());}// 投当前的leader一票,即投自己一票sendNotifications();SyncedLearnerTracker voteSet = null;/** Loop in which we exchange notifications until we find a leader*/// 循环直到有leader出现while ((self.getPeerState() == ServerState.LOOKING) && (!stop)) {/** Remove next notification from queue, times out after 2 times* the termination time*/// 拉取其他peer的投票Notification n = recvqueue.poll(notTimeout, TimeUnit.MILLISECONDS);/** Sends more notifications if haven't received enough.* Otherwise processes new notification.*/if (n == null) { // 没收到peer的投票信息if (manager.haveDelivered()) { // 上面的notification都发完了sendNotifications(); // 再发一次} else {manager.connectAll(); // 建立连接}/** 指数退避*/notTimeout = Math.min(notTimeout << 1, maxNotificationInterval);/** When a leader failure happens on a master, the backup will be supposed to receive the honour from* Oracle and become a leader, but the honour is likely to be delay. We do a re-check once timeout happens** The leader election algorithm does not provide the ability of electing a leader from a single instance* which is in a configuration of 2 instances.* */if (self.getQuorumVerifier() instanceof QuorumOracleMaj&& self.getQuorumVerifier().revalidateVoteset(voteSet, notTimeout != minNotificationInterval)) {setPeerState(proposedLeader, voteSet);Vote endVote = new Vote(proposedLeader, proposedZxid, logicalclock.get(), proposedEpoch);leaveInstance(endVote);return endVote;}} else if (validVoter(n.sid) && validVoter(n.leader)) { // 收到其他peer的投票/** Only proceed if the vote comes from a replica in the current or next* voting view for a replica in the current or next voting view.*/// 判断发送投票的peer当前状态switch (n.state) {case LOOKING: // 选主中if (getInitLastLoggedZxid() == -1) {break;}if (n.zxid == -1) {break;}if (n.electionEpoch > logicalclock.get()) { // peer的electionEpoch大于当前节点的electionEpochlogicalclock.set(n.electionEpoch); // 直接快进到大的epoch,即peer的electionEpochrecvset.clear(); // 并清空投票箱// 投票pk// peer投票和当前节点进行投票pk: peerEpoch -> zxid -> myid(sid)if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, getInitId(), getInitLastLoggedZxid(), getPeerEpoch())) {//  peer赢了,把当前节点的leader zxid peerEpoch设置为peer的updateProposal(n.leader, n.zxid, n.peerEpoch);} else {// 当前节点赢了,恢复自己的配置updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());}// 将上面更新后的自己的投票信息广播出去sendNotifications();} else if (n.electionEpoch < logicalclock.get()) {// 如果peer的electionEpoch比当前节点的electionEpoch小,则直接忽略break;} else// electionEpoch相等,进行投票pk: peerEpoch -> zxid -> myid(sid)if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) {// pk是peer赢了,跟随peer投票,并广播出去updateProposal(n.leader, n.zxid, n.peerEpoch);sendNotifications();}// 将peer的投票放入投票箱recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));voteSet = getVoteTracker(recvset, new Vote(proposedLeader, proposedZxid, logicalclock.get(), proposedEpoch));if (voteSet.hasAllQuorums()) {// Verify if there is any change in the proposed leaderwhile ((n = recvqueue.poll(finalizeWait, TimeUnit.MILLISECONDS)) != null) {if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch, proposedLeader, proposedZxid, proposedEpoch)) {recvqueue.put(n);break;}}/** This predicate is true once we don't read any new* relevant message from the reception queue*/if (n == null) {setPeerState(proposedLeader, voteSet);Vote endVote = new Vote(proposedLeader, proposedZxid, logicalclock.get(), proposedEpoch);leaveInstance(endVote);return endVote;}}break;case OBSERVING: // peer是观察者,不参与投票直接返回LOG.debug("Notification from observer: {}", n.sid);break;/** In ZOOKEEPER-3922, we separate the behaviors of FOLLOWING and LEADING.* To avoid the duplication of codes, we create a method called followingBehavior which was used to* shared by FOLLOWING and LEADING. This method returns a Vote. When the returned Vote is null, it follows* the original idea to break switch statement; otherwise, a valid returned Vote indicates, a leader* is generated.** The reason why we need to separate these behaviors is to make the algorithm runnable for 2-node* setting. An extra condition for generating leader is needed. Due to the majority rule, only when* there is a majority in the voteset, a leader will be generated. However, in a configuration of 2 nodes,* the number to achieve the majority remains 2, which means a recovered node cannot generate a leader which is* the existed leader. Therefore, we need the Oracle to kick in this situation. In a two-node configuration, the Oracle* only grants the permission to maintain the progress to one node. The oracle either grants the permission to the* remained node and makes it a new leader when there is a faulty machine, which is the case to maintain the progress.* Otherwise, the oracle does not grant the permission to the remained node, which further causes a service down.** In the former case, when a failed server recovers and participate in the leader election, it would not locate a* new leader because there does not exist a majority in the voteset. It fails on the containAllQuorum() infinitely due to* two facts. First one is the fact that it does do not have a majority in the voteset. The other fact is the fact that* the oracle would not give the permission since the oracle already gave the permission to the existed leader, the healthy machine.* Logically, when the oracle replies with negative, it implies the existed leader which is LEADING notification comes from is a valid leader.* To threat this negative replies as a permission to generate the leader is the purpose to separate these two behaviors.*** */case FOLLOWING: // peer正在following leaderVote resultFN = receivedFollowingNotification(recvset, outofelection, voteSet, n);if (resultFN == null) {break;} else {// 成功选主,返回return resultFN;}case LEADING: // peer 是 leader/** In leadingBehavior(), it performs followingBehvior() first. When followingBehavior() returns* a null pointer, ask Oracle whether to follow this leader.* */Vote resultLN = receivedLeadingNotification(recvset, outofelection, voteSet, n);if (resultLN == null) {break;} else {return resultLN;}default:break;}} else {// 推举的leader或投票的peer不合法,直接忽略// ...}}return null;} finally {// ...}}private Vote receivedFollowingNotification(Map<Long, Vote> recvset, Map<Long, Vote> outofelection,SyncedLearnerTracker voteSet, Notification n) {/** Consider all notifications from the same epoch* together.*/if (n.electionEpoch == logicalclock.get()) { // 同一轮投票//            若对方选票中的electionEpoch等于当前的logicalclock,//            说明选举结果已经出来了,将它们放入recvset。recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state));voteSet = getVoteTracker(recvset, new Vote(n.version, n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state));// 判断quorum是否满足选主条件if (voteSet.hasAllQuorums() &&// 判断推举的leader已经被quorum ack了,避免leader挂了导致集群一直在选举中checkLeader(recvset, n.leader, n.electionEpoch)) {// leader是自己,将自己设置为LEADING,否则是FOLLOWING(或OBSERVING)setPeerState(n.leader, voteSet);Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch);// 清空消费投票的queueleaveInstance(endVote);return endVote;}}// 到这里是// peer的electionEpoch和logicalclock不一致// 因为peer是FOLLOWING,所以在它的electionEpoch里已经选主成功了/** 在跟随peer选出的leader前,校验这个leader合法不合法* Before joining an established ensemble, verify that* a majority are following the same leader.** Note that the outofelection map also stores votes from the current leader election.* See ZOOKEEPER-1732 for more information.*/outofelection.put(n.sid, new Vote(n.version, n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state));voteSet = getVoteTracker(outofelection, new Vote(n.version, n.leader, n.zxid, n.electionEpoch, n.peerEpoch, n.state));if (voteSet.hasAllQuorums() && checkLeader(outofelection, n.leader, n.electionEpoch)) {synchronized (this) {logicalclock.set(n.electionEpoch);setPeerState(n.leader, voteSet);}Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch);leaveInstance(endVote);return endVote;}return null;}private Vote receivedLeadingNotification(Map<Long, Vote> recvset, Map<Long, Vote> outofelection, SyncedLearnerTracker voteSet, Notification n) {/** 在两个节点的集群中(leader+follower),如果follower挂了,recovery之后,因为投票无法过半(follower会首先投自己一票),会找不到leader* In a two-node configuration, a recovery nodes cannot locate a leader because of the lack of the majority in the voteset.* Therefore, it is the time for Oracle to take place as a tight breaker.* */Vote result = receivedFollowingNotification(recvset, outofelection, voteSet, n);if (result == null) {/** Ask Oracle to see if it is okay to follow this leader.* We don't need the CheckLeader() because itself cannot be a leader candidate* */// needOracle,当集群无follower & 集群voter==2 时,if (self.getQuorumVerifier().getNeedOracle() // 且cfg配置中key=oraclePath的文件(默认没有,askOracle默认false)中的值 != '1' 时会走到if里// 这里可参考官网 https://zookeeper.apache.org/doc/current/zookeeperOracleQuorums.html&& !self.getQuorumVerifier().askOracle()) {LOG.info("Oracle indicates to follow");setPeerState(n.leader, voteSet);Vote endVote = new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch);leaveInstance(endVote);return endVote;} else {LOG.info("Oracle indicates not to follow");return null;}} else {return result;}}// ...
}

提案处理

在这里插入图片描述

所有的提案均通过leader来提,follower接受的提案会转发到leader。
zk采用责任链模式对请求进行处理,不同的角色(leader/follower/observer)对应不同的责任链:

在这里插入图片描述

以下是leader的各个Processor的作用

  • LeaderRequestProcessor: Responsible for performing local session upgrade. Only request submitted directly to the leader should go through this processor.
  • PrepRequestProcessor: It sets up any transactions associated with requests that change the state of the system
  • ProposalRequestProcessor: 调用Leader#propose将proposal加入发送给follower的queue,由LeaderHandler异步发送给follower和处理follower的ack
  • SyncRequestProcessor: 将request写磁盘
  • AckRequestProcessor: ack leader自己的request
  • CommitProcessor: 提交提案。CommitProcessor本身是一个线程,上游调用先把request加入队列,然后异步消费处理
  • ToBeAppliedRequestProcessor: simply maintains the toBeApplied list
  • FinalRequestProcessor: This Request processor actually applies any transaction associated with a request and services any queries

接收follower的ack并提交走下面的调用:

org.apache.zookeeper.server.quorum.Leader.LearnerCnxAcceptor#run
org.apache.zookeeper.server.quorum.Leader.LearnerCnxAcceptor.LearnerCnxAcceptorHandler#run
org.apache.zookeeper.server.quorum.Leader.LearnerCnxAcceptor.LearnerCnxAcceptorHandler#acceptConnections
org.apache.zookeeper.server.quorum.LearnerHandler#run
org.apache.jute.BinaryInputArchive#readRecord
org.apache.zookeeper.server.quorum.LearnerMaster#processAck 这里如果满足quorum则调用CommitProcessor
org.apache.zookeeper.server.quorum.Leader#tryToCommit
org.apache.zookeeper.server.quorum.Leader#commit (leader 发送commit消息给follower,此时leader还不一定提交了,因为异步处理的) 
org.apache.zookeeper.server.quorum.Leader#inform (leader 发送inform消息给observer,此时leader还不一定提交了,因为异步处理的)

判断是否满足quorum的方法为:SyncedLearnerTracker#hasAllQuorums

public class SyncedLearnerTracker { // Proposal的父类,即每个提案一个Trackerpublic static class QuorumVerifierAcksetPair {private final QuorumVerifier qv; // 每一个zxid就是一个QuorumVerifierprivate final HashSet<Long> ackset; // ack的sid set...}protected ArrayList<QuorumVerifierAcksetPair> qvAcksetPairs = new ArrayList<>();...public boolean hasAllQuorums() {for (QuorumVerifierAcksetPair qvAckset : qvAcksetPairs) {if (!qvAckset.getQuorumVerifier().containsQuorum(qvAckset.getAckset())) {return false;}}return true;}...
}

最终调用QuorumMaj#containsQuorum

public class QuorumMaj implements QuorumVerifier {...protected int half = votingMembers.size() / 2;/*** Verifies if a set is a majority. Assumes that ackSet contains acks only* from votingMembers*/public boolean containsQuorum(Set<Long> ackSet) {return (ackSet.size() > half);}...

参考

  • Consensus Algorithms in Distributed Systems
  • FLP Impossibility Result
  • zookeeperInternals
  • 详解分布式协调服务 ZooKeeper,再也不怕面试问这个了
  • Lecture 8: Zookeeper
  • ZooKeeper: Wait-free coordination for Internet-scale systems
  • diff_acceptepoch_currentepoch
  • Zookeeper(FastLeaderElection选主流程详解)
  • zookeeper-framwork-design-message-processor-leader

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

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

相关文章

ffmpeg视频滤镜:提取缩略图-framestep

滤镜描述 官网地址 > FFmpeg Filters Documentation 这个滤镜会间隔N帧抽取一帧图片&#xff0c;因此这个可以用于设置视频的缩略图。总体上这个滤镜比较简单。 滤镜使用 滤镜参数 framestep AVOptions:step <int> ..FV....... set frame st…

微服务篇-深入了解使用 RestTemplate 远程调用、Nacos 注册中心基本原理与使用、OpenFeign 的基本使用

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 认识微服务 1.1 单体架构 1.2 微服务 1.3 SpringCloud 框架 2.0 服务调用 2.1 RestTemplate 远程调用 3.0 服务注册和发现 3.1 注册中心原理 3.2 Nacos 注册中心 …

TCP/IP学习笔记

TCP\IP从实际应用的五层结构开始&#xff0c;自顶而下的去分析每一层。 TCP/IP五层架构概述 学术上面是TCP/IP四层架构&#xff0c;OSI/ISO是七层架构&#xff0c;实际中使用的是TCP/IP五层架构。 数据链路层 ICMP数据包分析 Wireshark抓包分析ICMP协议_wireshark抓ping包分析…

互联网视频推拉流EasyDSS视频直播点播平台视频转码有哪些技术特点和应用?

视频转码本质上是一个先解码再编码的过程。在转码过程中&#xff0c;原始视频码流首先被解码成原始图像数据&#xff0c;然后再根据目标编码标准、分辨率、帧率、码率等参数重新进行编码。这样&#xff0c;转换前后的码流可能遵循相同的视频编码标准&#xff0c;也可能不遵循。…

深入理解 Java 基本语法之运算符

&#xff08;一&#xff09;研究背景 在 Java 编程中&#xff0c;运算符是处理数据和变量的基本工具&#xff0c;掌握各种运算符的使用方法对于提高编程效率至关重要。 &#xff08;二&#xff09;研究目的 深入理解 Java 基础运算符的概念、分类和作用&#xff0c;通过具体…

Excel把其中一张工作表导出成一个新的文件

excel导出一张工作表 一个Excel表里有多个工作表&#xff0c;怎么才能导出一个工作表&#xff0c;让其生成新的Excel文件呢&#xff1f; 第一步&#xff1a;首先打开Excel表格&#xff0c;然后选择要导出的工作表的名字&#xff0c;比如“Sheet1”&#xff0c;把鼠标放到“She…

ArcGIS pro中的回归分析浅析(加更)关于广义线性回归工具的补充内容

在回归分析浅析中篇的文章中&#xff0c; 有人问了一个问题&#xff1a; 案例里的calls数据貌似离散&#xff0c;更符合泊松模型&#xff0c;为啥不采用泊松而采用高斯呢&#xff1f; 确实&#xff0c;在中篇中写道&#xff1a; 在这个例子中我们为了更好地解释变量&#x…

计算机网络 第4章 网络层

计算机网络 &#xff08;第八版&#xff09;谢希仁 第 4 章 网络层4.2.2 IP地址**无分类编址CIDR**IP地址的特点 4.2.3 IP地址与MAC地址4.2.4 ARP 地址解析协议4.2.5 IP数据报的格式题目2&#xff1a;IP数据报分片与重组题目&#xff1a;计算IP数据报的首部校验和(不正确未改) …

极狐GitLab 17.6 正式发布几十项与 DevSecOps 相关的功能【三】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 学习极狐GitLab 的相关资料&#xff1a; 极狐GitLab 官网极狐…

直接抄作业!Air780E模组LuatOS开发:位运算(bit)示例

在嵌入式开发中&#xff0c;位运算是一种高效且常用的操作技巧。本文将介绍如何使用Air780E模组和LuatOS进行位运算&#xff0c;并通过示例代码帮助读者快速上手。 一、位运算概述 位运算是一种在计算机系统中对二进制数位进行操作的运算。由于计算机内部数据的存储和处理都是…

学习threejs,使用设置lightMap光照贴图创建阴影效果

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshLambertMaterial…

11.23作业

4、将整个 /etc 目录下的文件全部打包并用 gzip 压缩成/back/etcback.tar.gz 5、使当前用户永久生效的命令别名&#xff1a;写一个命令命为hello,实现的功能为每输入一次hello命令&#xff0c;就有hello&#xff0c;everyone写入文件/file.txt中。 6、创建mygroup组群&#xf…

网安瞭望台第5期 :7zip出现严重漏洞、识别网络钓鱼诈骗的方法分享

国内外要闻 7 - Zip存在高危漏洞&#xff0c;请立刻更新 2024 年 11 月 24 日&#xff0c;do son 报道了 7 - Zip 中存在的一个高严重性漏洞 CVE - 2024 - 11477。7 - Zip 是一款广受欢迎的文件压缩软件&#xff0c;而这个漏洞可能会让攻击者在存在漏洞的系统中执行恶意代码。…

ESC字符背后的故事(27 <> 033 | x1B ?)

ANSI不可见字符转义&#xff0c;正确的理解让记忆和书写变得丝滑惬意。 (笔记模板由python脚本于2024年11月26日 15:05:33创建&#xff0c;本篇笔记适合python 基础扎实的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xf…

【MyBatis】全局配置文件—mybatis.xml 创建xml模板

文章目录 模板文件配置元素typeAliasessettings 模板文件 创建模板 按照顺序打开【File】–>【settings】–>【Editor】–>【File and Code Templates】&#xff08;或直接搜索&#xff09; <?xml version"1.0" encoding"UTF-8" ?> <…

python的脚本式编程

一. 简介 前面简单学习了一下 python的交互式编程&#xff0c;文章如下&#xff1a; python的交互式编程-CSDN博客 本文来简单学习一下 python的脚本式编程。 脚本式编程是 Python 编程中最常用的方式之一&#xff0c;特别适合于编写和维护较大的程序或脚本。 二. 脚本式编…

flink学习(8)——窗口函数

增量聚合函数 ——指窗口每进入一条数据就计算一次 例如&#xff1a;要计算数字之和&#xff0c;进去一个12 计算结果为20&#xff0c; 再进入一个7 ——结果为27 reduce aggregate(aggregateFunction) package com.bigdata.day04;public class _04_agg函数 {public static …

uname -m(machine) 命令用于显示当前系统的机器硬件架构(Unix Name)

文章目录 关于 arm64 架构检查是否安装了 Rosetta 2其他相关信息解释&#xff1a;命令功能&#xff1a;示例&#xff1a; dgqdgqdeMac-mini / % uname -m arm64您运行的 uname -m 命令显示您的系统架构是 arm64。这意味着您的 Mac Mini 使用的是 Apple 的 M1 或更新的芯片&…

QUICK调试camera-xml解析

本文主要介绍如何在QUICK QC6490使能相机模组。QC6490的相机基于CameraX的框架&#xff0c;只需通过配置XML文件&#xff0c;设置相机模组的相关参数&#xff0c;就可以点亮相机。本文主要介绍Camera Sensor Module XML和Camera Sensor XML配置的解析&#xff0c;这中间需要cam…

10、PyTorch autograd使用教程

文章目录 1. 相关思考2. 矩阵求导3. 两种方法求jacobian 1. 相关思考 2. 矩阵求导 假设我们有如下向量&#xff1a; y 1 3 x 1 5 [ w T ] 5 3 b 1 3 \begin{equation} y_{1\times3}x_{1\times5}[w^T]_{5\times3}b_{1\times3} \end{equation} y13​x15​[wT]53​b13​​…