keep源码
A. Zookeeper之两阶段提交源码分析
zookeeper集群为了保证数据一致性,使用了两阶段提交。
在zookeeper集群的角色有:leader、follower、observer。
在这几个角色中处理读写请求是不同的:
读请求:从当前节点直接读取数据
写请求:在leader直接进行两阶段提交、在非leader则是把请求转交给leader处理
所以,分析两阶段提交就是分析集群模式下的请求处理。在单机模式在请求处理是经过RequestProcessor请求处理链处理。
单个zookeeprt请求处理主要有以下几步:
1、对当前请求生成日志txn
2、持久化日志txn
3、根据日志txn更新Database
两阶段提交(2PC)步骤:
其中标绿色的PrepRequestProcessor、SyncRequestProcessor、CommitProcessor都继承了ZooKeeperCriticalThread是一个线程。
org.apache.zookeeper.server.quorum.LeaderZooKeeperServer#setupRequestProcessors
org.apache.zookeeper.server.quorum.ProposalRequestProcessor#ProposalRequestProcessor
org.apache.zookeeper.server.quorum.LeaderRequestProcessor#processRequest
①、检查是不是local session本地session,创建临时节点会升级session
org.apache.zookeeper.server.quorum.QuorumZooKeeperServer#checkUpgradeSession
②、交给下一个请求处理器处理
作用与单机模式相同,给请求Request的Hdr和Txn赋值,然后交给下一个请求处理器处理
如果是写请求(request.getHdr() != null),则会把当前请求封装为协议并发送给follower。发送之后交给SyncRequestProcessor持久化处理
org.apache.zookeeper.server.quorum.Leader#propose
org.apache.zookeeper.server.quorum.Leader#sendPacket
发送到所有其他Followe节点forwardingFollowers
把请求放入到queuedRequests阻塞队列
①、对请求进行持久化与单机相同
org.apache.zookeeper.server.SyncRequestProcessor#run
向lead发送自己的ack(2PC发送ACK)
org.apache.zookeeper.server.quorum.Leader#processAck
org.apache.zookeeper.server.quorum.Leader#tryToCommit
org.apache.zookeeper.server.quorum.CommitProcessor#commit
提交当前请求,放入到committedRequests,最终会更新database
CommitProcessor类参数:
queuedRequests:表示接收到的请求,没有进行两阶段的提交
queuedWriteRequests:表示接收到的写请求,没有进行两阶段的提交
committedRequests:表示可以提交的请求,在两阶段验证过半之后进行会在本地进行committe操作,便添加到这个队列
commitIsWaiting:表示存在可以提交的请求(committedRequests是否有值,有true)
pendingRequests:是一个map集合,表示每个客户端sessionId的请求
Leader类参数:
outstandingProposals:表示记录提议的请求的队列,符合过半机制之后会移除
toBeApplied:表示记录待生效的请求,在FinalRequestProcessor移除
①、processRequest
org.apache.zookeeper.server.quorum.CommitProcessor#processRequest
首先判断是否需要两阶段提交。如果需要则会添加到queuedWriteRequests队列
org.apache.zookeeper.server.quorum.CommitProcessor#needCommit
如果是更改操作则返回true
d、然后,再看一下这个while的退出条件。
①、从queuedRequests取出的是空
②、如果queuedRequests数据不为空,那么requestsToProcess是大于0的。这时只有maxReadBatchSize < 0或readsProcessed <= maxReadBatchSize才能退出。
maxReadBatchSize < 0表示默认是-1,如果配置了这个参数当连续读了readsProcessed时,也会退出。
③、pendingRequests和committedRequests不为空
e、commitIsWaiting有待提交的
org.apache.zookeeper.server.quorum.Leader.ToBeAppliedRequestProcessor#processRequest
删除toBeApplied
其中标绿色的FollowerRequestProcessor、CommitProcessor、SyncRequestProcessor都继承了ZooKeeperCriticalThread是一个线程。
org.apache.zookeeper.server.quorum.FollowerZooKeeperServer#setupRequestProcessors
开了两条链:
FollowerRequestProcessor(firstProcessor)---->CommitProcessor----->FinalRequestProcessor
SyncRequestProcessor---->SendAckRequestProcessor
org.apache.zookeeper.server.quorum.FollowerRequestProcessor#processRequest
请求添加到queuedRequests队列
FollowerRequestProcessor是一个线程,会从queuedRequests获取请求
org.apache.zookeeper.server.quorum.FollowerRequestProcessor#run
createSession和closeSession也会转发给lead节点处理
org.apache.zookeeper.server.quorum.SendAckRequestProcessor#processRequest
在用SendAckRequestProcessor处理之前会先调用SyncRequestProcessor进行持久化处理,由于与单机或lead处理相同就不单独列出来了。
向领导者发送确认ack包
org.apache.zookeeper.server.quorum.Learner#writePacket
在经过FollowerRequestProcessor处理后,lead端会得到一个Request的请求
org.apache.zookeeper.server.quorum.LearnerHandler#run
org.apache.zookeeper.server.quorum.Leader#submitLearnerRequest
在连接Follower节点的客户端发送更改命令请求会转发到leader节点的prepRequestProcessor进行处理
1、run
org.apache.zookeeper.server.quorum.QuorumPeer#run
2、followLeader
org.apache.zookeeper.server.quorum.Follower#followLeader
不断读取从lead端的数据包
org.apache.zookeeper.server.quorum.FollowerZooKeeperServer#logRequest
其中标绿色的ObserverRequestProcessor、CommitProcessor、SyncRequestProcessor都继承了ZooKeeperCriticalThread是一个线程。
org.apache.zookeeper.server.quorum.ObserverZooKeeperServer#setupRequestProcessors
也是开了两条链:
ObserverRequestProcessor(firstProcessor)---->CommitProcessor----->FinalRequestProcessor
SyncRequestProcessor---->null
observer节点不参与两阶段提交,所以同步SyncRequestProcessor之后没有ACK确认提交。这样既提高了读效率,又对写效率没有影响。请求处理链与leader、follower的功能相同不再累述。
zookeeper集群的两阶段提交,是在写操作的情况下发生的。2PC的整体实现逻辑是在RequestProcessor请求处理链处理的。只有在接受到的ACK超过一半才会进行提交,提交的实现逻辑是在CommitProcessor中实现的,CommitProcessor处理器中里面涉及多种集合、队列等参数(需要首先了解这些参数意义,然后再读CommitProcessor源码)。
B. keeptalk安装怎么安装
下载keeptalk源码。
从keeptalk官网下载keeptalk源码安装包,解压keeptalk文件,然后运行安装程拆猛序,闷孝从终端旅罩桥运行(node keeptalk.js)命令,启动keeptalk。
KeepTalk是一款开放源代码的计算机软件,主要用于实现P2P客户端/服务器文本聊天。
C. Vue keep-alive源码
上面的 extend(Vue.options.components, builtInComponents);我们知道
D. vue列表缓存keep-alive
列表查询出约课记录之后,跳转到详情后再返回页面内容刷新,之前搜索的结果就没有了,为了解决这一问题,使用了keep-alive组件来实现页面缓存。
keep-alive
keep-alive.js源码:
只执行一次的钩子:当vnode.componentInstance和keepAlive为州中true时,不再进入$mount过程,也就不会执行mounted以及之前的钩子函数(beforeCreated、created、mounted)
可重复执行的activated:在patch阶段,最后会执行invokeInsertHook函数,这个函数调用组件实例的insert钩子,insert钩子中调用了activateChildComponent函数,递归执行子组件中的activated钩子函数
pageList → pageDetail → pageList,pageList保存原有状态;pageList → 其他 → pageList,猜迹虚pageList初始化状态
pageList → pageDetail → pageList,pageList保存原有状态;pageList → 其他 → pageList,pageList初始化状态
问题:方法二中,pageList → pageDetail → 其他 → pageList,pageList采用了缓存的数据, 解决:其他页面中的beforeRouteLeave增加 this.$store.dispatch('setCacheList', '穗燃')
E. Vue—KeepAlive源码探究,适时清理页面缓存
使用过 Vue 的小伙伴们肯定都知道,Vue 的内部组件 keep-alive 是用来缓存我们不活动的组件的。
但是在某些情况下,我们需要缓存,某些情况下希望及时释放掉缓存,那我们应该怎么做呢?
有个场景是,希望模仿App的方式,每次push到当前碧敬页面的时候,触发 mounted 进行组件初始化,而从其他页面返回到当前页面时,希望可以保留当前组件的状态。
举个例子:
移动端的分页列表页面,加载了几页,并且有滑动记录,但是希望进详情页后,返回列表页时,可以保持分页的状态以及滑动的轨迹。
需求如上,这就需要 keep-alive 帮助我们缓存组件了。
但是用过 keep-alive 组件的小伙伴肯定明白,如果 include 当前列表页面,虽然可以做到返回列表页保持状态,但是从其他页面前往列表页时,依然会加载缓存的状态,我们不得不采用 activated 钩子方法来处理,但这样总归是不优雅的。
看过一些文字有人说让include的数组变成动态的是否能达到类似的效果,这种方式也非常好,可以很容易的达到我们想要的效果。
阅读过源码之后发现, keep-alive 内部实现是将组件缓存在一个 caches 数仿胡组中的,如果我们可以操作这个数组,是否可以达到灵活控制缓存组件的效果呢?
方法一比较繁琐,但是悔大慎用起来还是很直接的,比较灵活,可以应付浏览器刷新的场景
方法二比较简单,适合在移动app中使用,自己维护页面栈,不会有浏览器刷新等操作,否则include的内容可能会由于刷新而出现栈异常