ZooKeeper技术细节_zookeeper and 服务器 and 客户端 and 数据节点

服务器 0
Leader和Follower服务器启动期交互过程

  • PrepRequestProcessor是Leader服务器的请求预处理器,在ZK中,将创建删除节点/更新数据/创建会话等会改变服务器状态的请求称为事务请求,对于事务请求,预处理器会进行一系列预处理,如创建请求事务头、事务体、会话检查、ACL检查和版本检查
  • ProposalRequestProcessor Leader的事务投票处理器,也是Leader服务器事务处理流程的发起者。
  • 对于非事务请求:直接将请求流转到CommitProcessor,不作其他处理
  • 对于事务请求:除了交给CommitProcessor,还会根据对应请求类型创建对应的Proposal,并发送给所有Follower服务器发起一次集群内的事务投票。ProposalRequestProcessor还会将事务请求交给SyncRequestProcessor进行事务日志的记录
  • SyncRequestProcessor 事务日志处理器,将事务请求记录到事务日志文件中,触发ZooKeeper进行数据快照
  • AckRequestProcessor 是Leader特有的处理器,负责在SyncRequestProcessor处理器完成事务日志记录后向Proposal的投票收集器发送ACK反馈,通知投票收集器当前服务器已完成对该Proposal的事务日志记录
  • CommitProcessor 事务提交处理器
  • ToBeCommitProcessor 该处理类中有一个toBeApplied队列(ConcurrentLinkedQueue toBeApplied)存储被CommitProcessor处理过的可被提交的Proposal,等待FinalRequestProcessor处理完提交的请求后从队列中移除
  • FinalRequestProcessor 进行客户端请求返回前的收尾工作:创建客户端请求的响应、将事务应用到内存数据库

LearnerHandler:Leader服务器会与每一个Follower/Observer服务器建立一个TCP长链接,同时为每个Follower/Observer服务器创建LearnerHandler。LearnerHandler是ZK集群中的Learner服务器的管理器,负责Follower/Observer服务器和Leader服务器之间的网络通信:数据同步、请求转发、Proposal提议的投票。

Follower

Follower的职责:处理客户端非事务请求,转发事务请求给Leader服务器;参与事务请求Proposal的投票;参与Leader选举投票;

Follower不需要负责事务请求的投票处理(所以不需要ProposalRequestProcessor),所以其请求处理链简单一些

  • FollowerRequestProcessor 识别出当前请求是否是事务请求,如果是事务请求,Follower就会将请求转发给Leader服务器,Leader服务器收到请求后提交给请求处理器链,按正常事务请求进行处理
  • SendAckRequestProcessor Follower服务器上另一个和Leader服务器有差异的请求处理器,与Leader服务器上的AckRequestProcessor类似,SendAckRequestProcessor同样承担了事务日志记录反馈的角色,在完成事务日志记录后,会向Leader服务器发送ACK消息表明自身完成了事务日志的记录工作。两者的一个区别是:AckRequestProcessor在Leader服务器上,因此ACK反馈是一个本地操作,而SendAckRequestProcessor在Follower上,需要通过ACK消息的形式向Leader服务器进行反馈。
Observer

观察ZooKeeper集群的最新状态并将这些状态变更同步过来,Observer服务器在工作原理上与Follower基本一致,对于非事务请求可以进行独立的处理,对于事务请求同样需要转发到Leader服。与Follower的一大区别是:Observer不参与任何形式的投票,包括Leader选举和事务请求Proposal的投票。

集群内消息通信

ZK集群各服务器间消息类型分为4类:数据同步型、服务器初始化型、请求处理型、会话管理型

数据同步消息

Learner与Leader进行数据同步使用的消息,分为4种(消息类型定义在Leader.java中,使用常量数字标记):

  • DIFF, 13 Leader发送给Learner,通知Learner进行DIFF方式的数据同步
  • TRUNC, 14 Leader --> Learner 触发Learner服务器进行内存数据库的回滚操作
  • SNAP, 15 Leader --> Learner 通知Learner,Leader即将与其进行全量数据同步
  • UPTODATE, 12 Leader --> Learner 通知Learner完成了数据同步,可以对外提供服务
服务器初始化型消息

整个集群或某些机器初始化时,Leader与Learner之间相互通信所使用的消息类型:

  • OBSERVERINFO,16: Observer在启动时发送消息给Leader,用于向Leader注册Observer身份,消息中包含当前Observer服务器的SID和已经处理的最新ZXID
  • FOLLOWERINFO,11:Follower启动时发送包含SID和已处理的最新ZXID的注册消息到Leader
  • LEADERINFO,17:上述两种情形下,Leader服务器会返回包含最新EPOCH值的LeaderInfo返回给Observer或Follower
  • ACKEPOCH,18:Learner在收到LEADERINFO消息时会将自己的最新ZXID和EPOCH以ACKEPOCH消息的形式发送给Leader
  • NEWLEADER,10:足够多的Follower连接上Leader服务器,或是Leader服务器完成数据同步后,Leader向Learner发送的阶段性标识信息,包含当前最新ZXID
请求处理型

请求处理过程中Leader和Learner之间互相通信所使用的消息:

  • REQUEST,1:Learner收到事务请求时需要将请求转发给Leader,该请求使用REQUEST消息的形式进行转发
  • PROPOSAL,2:在处理事务请求时,Leader服务器会将事务请求以PROPOSAL消息的形式创建投票发送给集群中的所有的Follower进行事务日志的记录
  • ACK,3:Follower完成事务日志的记录后会以ACK消息的形式反馈给Leader
  • COMMIT,4:Leader通知集群中的所有Follower,可以进行事务请求的提交了,Leader在收到过半Follower发来的ACK消息后,进入事务请求的最终提交流程——生成COMMIT消息,告知所有Follower进行事务请求的提交,这是一个2PC的过程
  • INFORM,8:Leader发起事务投票并通知提交事务,只需要PROPOSAL和COMMIT消息给Follower就可以了,而Observer不参与事务投票,无法接收COMMIT消息,但需要知道事务提交的内容,所以ZK设计了INFORM消息发给Observer,消息中会携带事务请求的内容
  • SYNC,7:Leader通知Learner服务器已完成Sync操作
会话管理型

ZK服务器在进行会话管理过程中,与Learner服务器之间通信所使用的消息:

  • PING,5:ZK客户端随机选择一个服务器进行连接,所以Leader服务器无法直接收到所有客户端的心跳检测,所以需要委托Learner维护所有客户端的心跳检测。Leader定时向Learner发送PING消息就是要求Learner将一段时间内保持心跳检测的客户端列表同样以PING消息的形式返回给Leader,这样Leader就能获取到全部客户端的活跃状态并进行会话激活了。
  • REVALIDATE,6:客户端发生重连后(可能切换了服务器)新连接的服务器需要向Leader发送REVALIDATE消息以确定客户端会话是否已经超时。

客户端请求的处理

会话创建请求

ZK服务端对于会话创建的处理,可以分为请求接收、会话创建、预处理、事务处理、事务应用和会话响应。

zookeeper源码分析(3)— 一次会话的创建过程 - 简书— 一次会话的创建过程 - 简书")

预处理

  1. IO层接收来自客户端的请求
  2. 判断是否是客户端会话创建类请求,setData请求到来时已完成了会话创建
  3. PrepRequestProcessor处理器进行处理
  4. 创建请求事务头
  5. 检查会话是否超时,超时向客户端抛出SessionExpiredException
  6. 反序列化请求,创建ChangeRecord记录。ZK对于客户端请求,反序列化生成特定SetDataRequest请求,请求中包含数据节点path、更新数据内容data、期望的数据节点版本version。
  7. ACL权限检查,没有权限会抛出NoAuthException
  8. 数据版本检查(乐观锁)
  9. 创建事务请求体SetDataTxn
  10. 保存事务操作到outstandingChanges队列中

事务处理:无论对于会话创建还是SetData请求,事务处理流程都是一致的:由ProposalRequestProcessor处理器发起,通过Sync、Proposal、Commit 3个子流程相互协作完成

事务应用

  1. FinalRequestProcessor处理
  2. ZK将请求事务头和事务体交给内存数据库 ZKDatabase进行事务应用,返回ProcessTxnResult,包含了数据节点内容更新后的stat
  3. 将事务请求放入 commitProposal 队列

请求响应

  1. 统计处理
  2. 创建响应体SetDataResponse,包含当前数据节点的最新状态stat
  3. 创建响应头,方便客户端对响应进行解析,包括当前响应对应的事务ZXID和请求处理是否成功的标识err
  4. 序列化响应
  5. IO层发送响应给客户端

事务请求转发

所有非Leader服务器如果收到了来自客户端的事务请求,必须将其转发给Leader服务器处理。Follower或Observer服务器中,第一个请求处理器分别是FollowerRequestProcessor和ObserverRequestProcessor,都会检查当前请求是否是事务请求,对于事务请求会议REQUEST消息的形式转发给Leader,Leader解析出原始请求后提交到自己的请求处理链中。

GetData请求

预处理:

IO层接收来自客户端的请求;判断是否是客户端会话创建请求;PrepRequestProcessor处理;会话检查;

由于GetData请求是非事务请求,因此不需要事务预处理逻辑:创建请求事务头、ChangeRecord、事务体、数据节点版本的检查;

非事务处理:

反序列化GetDataReqeuest(得到path和watcher注册情况);获取数据节点(ZK从内存数据库中获取节点及ACL信息);ACL检查;获取数据内容和stat,注册watcher;

请求响应:

创建响应体GetDataResponse,获取数据成功后的响应,包含当前数据节点内容和状态stat;创建响应头;统计处理;序列化响应;IO层发送响应给客户端;

ZK底层数据与存储

内存数据库存储了ZK树结构的数据,包括节点路径、节点数据和ACL信息,ZK会定时将这些数据存储到磁盘上

DataTree类

org.apache.zookeeper.server.DataTree维护了树形结构数据,内部没有任何网络或客户端连接逻辑,所以可以单独进行调试。

DataNode是数据存储的最小单元,内含数据节点内容 byte[] data、ACL列表对应的map key Long acl、节点状态对象StatPersisted stat、子节点列表Set children、父节点parent的引用?

DataTree维护了两个数据结构:path与DataNode组成的ConcurrentHashMap<String, DataNode> nodes、DataNode树;

另外为方便及时访问和清理临时节点,额外维护字段 Map<Long, HashSet> ephemerals = new ConcurrentHashMap<Long, HashSet>()

ZKDatabase

ZooKeeper的内存数据库,管理ZK的所有会话、DataTree存储和事务日志。ZKDatabase会定时向磁盘dump快照数据,ZK服务器启动时会通过磁盘上的事务日志和快照文件进行恢复

事务日志

zoo.cfg配置文件中的dataDir目录默认用于存储事务日志文件,dataLogDir可以配置为事务日志单独分配一个文件存储目录。

如果配置了 dataLogDir = /home/admin/zkData/zk_log,ZK运行时会在该目录下创建 version-2 子目录,该目录的命名跟随ZK的事务日志版本号。这样运行一段时间后在 /home/admin/zkData/zk_log/version-2 出现了日志文件

-rw-rw-r-- 1 admin admin 67108880 02-23 16:10   log.2c01631713
-rw-rw-r-- 1 admin admin 67108880 02-23 17:07   log.2c0164334d
-rw-rw-r-- 1 admin admin 67108880 02-23 18:19   log.2d01654af8
-rw-rw-r-- 1 admin admin 67108880 02-23 19:28   log.2d0166a224

  • 这些日志文件大小固定都是64MB
  • 文件后缀名是十六进制数字,即ZXID - 64位数字,前32位表示ecpoch,这些日志文件只有两个epoch:2c、2d;后32位是操作序列号。每个日志文件达到设定的大小后,创建新日志文件并以当时的ZXID为文件名,这样方便根据日志文件后缀名寻找ZXID的存储位置
  • 事务日志文件内容的解析命令 java LogFormatter log.2d0166a224

事务日志文件头信息,输出事务日志的DBID和日志版本号

ZooKeeper Transactional Log File with dbid 0 txnlog format version 2

客户端会话创建的事务操作日志,分别记录了 事务操作时间、客户端会话ID、CXID客户端操作序列号、ZXID、操作类型和会话超时时间

…11:07:41 session 0x1446994y6273434 cxid 0x0 zxid 0x300000002 createSession 30000

节点创建的事务操作日志,记录了操作类型、节点路径、节点数据内容、节点ACL信息、是否是临时节点(F表示永久节点,T表示临时节点)、节点版本号

…11:08:40 session 0x1446995520000 cxid 0x2 zxid 0x3000003 create '/test_log,#7631,v{s{31,s{'world,'anyone}}},F,2

  • 事务日志文件不会记录读操作
FileTxnLog类

在其public synchronized boolean append(TxnHeader hdr, Record txn, TxnDigest digest)方法中进行了日志的写入,会传递事务头TxnHeader和事务体Record,日志写入步骤:

  • 判断FileTxnLog是否已关联上一个可写的事务日志文件,如果没有关联上,就会用与事务操作关联的ZXID作为后缀创建一个事务日志文件,同时构建事务日志文件头信息(包含魔数magic、事务日志格式版本version、dbid)并写入日志文件。改日志文件的文件流会放入 Queue streamsToFlush = new ArrayDeque<>() 中
  • 对日志文件进行磁盘空间预分配(日志文件不断追加写入会触发底层磁盘空白块的Seek,为提高IO效率,所以预分配磁盘空间),通常一个日志文件预分配64MB,已分配空间不足4KB时会再次分配,预分配的文件使用0填充,预分配的文件大小使用 zookeeper.preAllocSize 进行设置
  • 事务序列化,包括事务头TxnHeader和事务体Record的序列化,事务体又分为会话创建事务CreateSessionTxn、节点创建事务CreateTxn、节点删除事务DeleteTxn、节点数据更新事务SetDataTxn
  • 为保证事务日志文件的完整性和准确性,ZK在将事务日志写入文件前,会根据序列化步骤产生的字节数组计算checksum,ZK默认使用Adler32算法计算checksum
  • 将序列化后的事务头、事务体和checksum写入文件流,由于ZK使用的是BufferedOutputStream,写入的数据并没有立刻到达磁盘
  • 事务日志刷入磁盘:将缓冲数据输入磁盘,从streamToFlush 中获取文件流,调FileChannel.force(bool metadata) 进行磁盘文件的强制写入,该方法基于底层的fsync接口,通过 zookeeper.forceSync 来设置
TRUNC日志截断

在运行过程中如果出现非Leader服务器的ZXID(peerLastZxid)大于Leader服务器的,此时Leader服务器会发出TRUNC给这台服务器,清除掉所有包含或大于peerLastZxid的事务日志,保持与Leader服务器的同步

Sanpshot数据快照

记录ZK服务器上某一时刻全量内存数据内容,写入到指定磁盘文件中,同样位于指定的dataDir目录下。与事务日志文件不同的是,快照文件没有采用预分配的方式,所以快照文件的大小就可以反映当前ZK服务器内存中的全量数据大小。

快照数据的解析可使用命令 java SnapshotFormatter snapshot.30000000007

快照文件记录的是数据节点的元信息,不包含节点的数据内容

FileSnap类

ZK定期将内存数据库全量Dump到本地文件,这个文件就是Snapshot,通过snapCount配置在事务日志记录多少次后进行快照写入。数据快照的流程是

  1. 理论上在snapCount后进行数据快照,但考虑到数据快照对ZK服务器性能的影响,需要避免所有机器在同一时刻进行进行snapshot。ZK采用了过半随机策略,满足下述条件就进行数据快照:logCount > (snapshot / 2 + randRoll) ,logCount表示当前已经记录的事务日志数量,randRoll为 1 ~ snapCount/2 之间的随机数,所以上述条件相当于:如果配置snapCount=1000,则ZK会在500~1000次事务日志后进行一次快照
  2. 切换事务日志文件:当前事务日志文件已经写入了snapCount条事务日志,需要创建一个新的事务日志文件
  3. 创建数据快照异步线程,不影响ZooKeeper主流程
  4. 从ZkDatabase获取全量数据DataTree和会话信息
  5. 根据当前已提交的最大ZXID确定快照文件名称
  6. 先序列化文件头信息(包含魔数、版本号和dbid信息)对会话信息和DataTree分别进行序列化,生成checksum写入快照文件

服务器初始化流程

初始化流程 Zookeeper–数据初始化过程-蒲公英云 主要包括从快照文件中加载数据和从事务日志文件中进行数据订正两个过程

  1. 初始化FileTxnSnapLog:FileTxnSnapLog是ZooKeeper事务日志和快照数据访问层,用于衔接上层业务与底层数据存储,底层数据又分为snapshot和txn两部分,所以FileTxnSnapLog内部又分为FileTxnLog和FileSnap的初始化
  2. 初始化ZKDatabase:DataTree是ZooKeeper内存数据的核心模型,在每个ZooKeeper服务器内部是单例。ZkDatabase初始化时也会初始化DataTree:创建一些ZK的默认节点,如/ /zookeeper /zookeeper/quota。初始化阶段还会创建一个会话超时时间记录器 sessionsWithTimeouts
  3. 创建PlayBackListener监听器,接收事务使用过程中的回调。在ZK数据恢复后期事务订正过程中会回调这个监听器进行数据校正
  4. 完成内存数据库的初始化后从磁盘的快照文件中恢复数据
  5. 获取至多100个最近的快照文件
  6. 反序列化这些二进制文件生成DataTree对象和sessionWithTimeouts集合,同时进行文件的checkSum校验。当最新的快照文件不可用时才会进行逐个文件解析,直到这100个文件全部解析完,否则服务启动失败
  7. 获取最新的ZXID,从加载解析成功的快照文件的文件名中可以得到一个最新的ZXID
  8. 完成快照文件加载后,此时ZK服务器内存中已经有一份近似全量的数据,就可以通过事务日志更新增量数据了
  9. 从事务日志中获取比快照文件最大ZXID zxid_for_snap 大的事务操作
  10. 将这些事务操作逐个应用到之前基于快照数据文件恢复出来的DataTree 和 sessionsWithTimeouts 中。当一个事务被应用到内存数据库中后,ZK会回调PlayBackListener监听器,将这一事务操作记录转换成Proposal,保存到ZKDatabase.committedLog中,以便Follower进行快速同步
  11. 所有事务被完整应用后,此时就能获取到上次服务器正常运行时提交的最大事务ID
  12. 校验当前Leader周期 epoch 纪元号:上一步骤得到的ZXID中解析到epochOfZxid,同时与磁盘上的currentEpoch、acceptedEpoch文件中的epoch值进行校验
Leader应用完事务日志后的数据同步

PlayBackListener是一个事务应用监听器,Leader在事务应用后会回调该Listener的 onTxnLoaded 方法

public interface PlayBackListener {
void onTxnLoaded(TxnHeader hdr, Record rec, TxnDigest digest);
}

PlayBackListener会将这些事务通过 ZKDatabase#addCommittedProposal方法转存到 ZKDatabase.committedLog 中,便于集群间同步。

事务同步的过程就是Leader向Learner同步事务的过程,Learner向Leader注册的最后阶段会发送一个ACKEPOCH数据包,Leader会从该数据包中解析出该Learner的 currentEpoch 和 lastZxid。

数据同步初始化

数据同步代码位于LearnerHandler和Learner两个类中。Leader依据内存数据库ZKDatabase中的committedLog进行初始化,生成3个ZXID值:

  • peerLastZxid:Learner服务器最后处理的ZXID
  • minCommittedLog:Leader服务器提案缓存队列committedLog中的最小ZXID
  • maxCommittedLog:Leader服务器提案缓存队列committedLog中的最大ZXID

ZK集群数据同步分为4类:

  • DIFF 差异化同步(触发条件 minCommittedLog <= peerLastZxid <= maxCommittedLog)Leader向Learner发送DIFF指令通知Leader进入差异化同步状态,针对每个 ZXID > peerLastZxid 的提案,Leader会发出 PROPOSAL内容 和 COMMIT指令 两个数据包。与通常的Leader和Follower之间的事务请求的提交过程一致。 Leader在发送完差异数据后,会将Learner加入到 forwardingFollowers 或 observingLearners 队列中,随后向Learner发出NEWLEADER指令,通知其差异化同步完毕。 此后Learner反馈一个ACK消息给Leader,Leader接收到过半Learner的ACK消息后,会向所有已完成数据同步的Learner发送UPTODATE指令,通知Learner已经完成了数据同步。此时集群中过半机器完成了数据同步,具备了对外提供服务的能力。 Learner在接收到这个来自Leader的UPTODATE指令后,会终止数据同步流程,向Leader再次反馈一个ACK消息。

@startuml
autonumber
Leader <- Learner : FOLLOWERINFO/OBSERVERINFO
Leader -> Learner : LEADERINFO
Leader <- Learner : ACKEPOCH
note right
1-3 注册
end note
Leader -> Learner : DIFF
Leader -> Learner : PROPOSAL
Leader -> Learner : COMMIT
note right
4-9 差异化同步
end note
Leader -> Learner : PROPOSAL
Leader -> Learner : COMMIT
Leader -> Learner : NEWLEADER
Leader <- Learner : ACK
Leader -> Learner : UPTODATE 等待过半
Leader <- Learner : ACK
note right
10-12 同步确认
end note

  • TRUNC+DIFF 先回滚再差异化同步。适用场景:A B C三台机器,某一时刻B是Leader,当前的Leader_Epoch=5,被过半数机器提交的ZXID包括 0x500000001、0x500000002,B服务器在处理完0x500000003事务时将该事务写入本地事务日志。但在B向其他Follower发送Proposal进行投票时,B服务器宕机,Proposal没有被同步出去。在新一轮选举后新Leader A服务器将Leader_Epoch变更为6,之后AC两台服务器对外提供服务,又提交了0x600000001、0x600000002两个事务,此时服务器B恢复加入集群。此时peerLastZxid、minCommittedLog、maxCommittedLog的值分别是 0x500000003、0x500000001、0x600000002,满足 minCommittedLog <= peerLastZxid <= maxCommittedLog。 当Leader服务器发现某个Learner包含了一条自己没有的事务记录,就需要让该Learner进行事务回滚,回滚到Leader上存在的且是最接近peerLastZxid的ZXID(上述例子中就是 0x500000002),然后再进行差异化同步
  • TRUNC 仅回滚同步
  • SNAP 全量同步。适用场景: peerLastZxid < minCommittedLog 或 Leader服务器上没有committedLog,peerLastZxid != lastProcessedZxid Leader服务器上数据恢复后得到的最大ZXID。这两种场景下,Leader都无法使用committedLog与Learner进行数据同步,因此只能进行全量同步

ZooKeeper技术内幕总结

ZooKeeper以树作为其内存数据模型,树上的每一个节点是最小的数据单元,即ZNode。ZNode有一个递增的版本号,以此可以实现分布式数据的原子性更新。

ZooKeeper序列化层使用从Hadoop中遗留下来的Jute组件,该组件不是性能最好的序列化框架,但在ZooKeeper中够用。

ZooKeeper的客户端和服务端之间会建立起TCP长链接进行网络通信,基于该TCP连接衍生出的会话概念,是客户端和服务端之间所有请求与响应交互的基础。在会话的生命周期中,会出现连接断开、重连或是会话失效等一系列问题。Leader服务器会负责管理每个会话的生命周期,包括会话的创建、心跳检测和销毁等。

服务器启动阶段会进行磁盘数据的恢复,恢复完成后会进行Leader选举,一旦选举产生Leader后,就立即开始进行集群间的数据同步——在整个过程中,ZooKeeper都处于不可用状态,直到数据同步完毕(集群中绝大部分机器数据和Leader一致),ZooKeeper才可以对外提供服务。在运行期间,如果Leader服务器所在机器宕机或是和集群中绝大部分机器断开连接,就会触发新一轮Leader选举。

一个正常运行的ZooKeeper集群,其机器角色通常由Leader、Follower和Observer组成。ZooKeeper对于客户端请求的处理严格按照ZAB协议规范进行。每个服务器在启动初始化阶段都会组装一个请求处理链,Leader服务器能够处理所有类型的客户端请求,而Follower或是Observer服务器只能处理非事务请求。对于每个事务请求,Leader都会为其分配一个全局唯一且递增的ZXID,以此保证事务处理的顺序性。在事务请求的处理过程中,Leader和Follower都会进行事务日志的记录。ZooKeeper通过JDK的File接口简单实现了自己的数据库存储系统,底层数据存储包括事务日志和快照数据两部分,这些都是ZooKeeper实现数据一致性非常关键的部分。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)
img

己的数据库存储系统,底层数据存储包括事务日志和快照数据两部分,这些都是ZooKeeper实现数据一致性非常关键的部分。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数大数据工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-i4LIavI6-1712540612539)]
[外链图片转存中…(img-xHMAzEYL-1712540612539)]
[外链图片转存中…(img-ta488tTa-1712540612539)]
[外链图片转存中…(img-ZzXcDPZU-1712540612540)]
[外链图片转存中…(img-nQL3xr5e-1712540612540)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上大数据开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加VX:vip204888 (备注大数据获取)
[外链图片转存中…(img-F74U9A9u-1712540612540)]

也许您对下面的内容还感兴趣: