phxpaxos源代码整体架构
Paxos协议是分布式系统设计中的一个非常重要的协议,本文转载自微信后台团队公众号团队所发表一系列Paxos的文章,中间针对自己的理解略有修改或注释。在此处做一个备份,一方面为了加深对Paxos协议的理解,另一方面也方便自己的后续查找,防止文章丢失。
1. phxpaxos整体架构
通过对phxecho这个实例的分析,phxpaxos的整体抽象层次如下所示:
一个phxpaxos节点可以有多个Group,Group与Group之间完全隔离,不会进行任何通信。每一个Group可以挂载多个StateMachine。
phxpaxos的整体类图结构如下所示:
图中PNode
代表着一个PhxPaxos节点,其拥有多个Group,并关联着DFNetwork对象。DFNetwork拥有m_oUDPRecv、m_oUDPSend、m_oTcpIOThread三个属性,分别控制着UDP数据包的接收、UDP数据包的发送,以及TCP数据的处理。EventLoop是整个TCP请求事件驱动器,MessageEvent代表着一个具体的TCP socket连接对象。
phxpaxos中,对于TCPsocket的读写是完全分离的,一个socket连接要么只能读,要么只能写。
2. phxpaxos数据的接收与发送流程
本节我们将介绍phxpaxos中数据的接收与发送流程,中间暂时不会涉及到任何与业务相关的操作。
2.1 UDP数据包的发送
UDP数据包的发送是由UDPSend
这个类来完成的。参看如下发送流程:
对于UDP数据的发送,整体流程较为简单,这里不再赘述。
2.2 UDP数据的接收
UDP数据包的接收主要由UDPRecv
和IOLoop
两个类来负责。参看如下接收流程:
两个类的分工很明确,UDPRecv类负责从socket里面获取UDP数据包,IOLoop管理着一个消息队列和定时器队列。UDPRecv获取到的数据包会被投送到IOLoop的消息队列中,以做后续的进一步处理。
2.3 TCP数据包的发送
对于TCP包的发送,主要由TcpIOThread
来负责。但是TcpIOThread其实封装了如下三种对象:
-
TcpAcceptor对象
-
TcpRead对象数组
-
TcpWrite对象数组
phxpaxos这样划分,可以使得每一个对象所完成的功能十分的纯粹。下面我们就简要来看一下针对TCP数据包的发送流程:
此处结构比较复杂,涉及到众多的对象,我们先来梳理一下这些对象之间的关系:
通过上面的类图,我们可以很清楚的发现作者的意图: 一个TcpWrite对象关联着一个TcpClient以及一个EventLoop。其中EventLoop作为TCP读写事件的驱动器,不断的监听对应的socket上是否具有读写事件;TcpClient对象的作用是用于建立MessageEvent,为EventLoop提供源源不断的动力。
通过上面的分析,TCP数据包的发送过程就一目了然了。
2.4 TCP数据包的接收
对于TCP包的接收,因为一般先要接受来自对端的TCP连接,因此还涉及到TcpAccepter对象,连接建立后才能接收到对方发来的数据。如下我们给出接收流程:
在上面MessageEvent::OnRead()后面其实还有一长串流程:
到此为止,整个数据的发送与接收流程就已经介绍完毕。
3. phxpaxos的初始化
这里我们以phxecho为例来探讨一下phxpaxos的初始化过程,以进一步了解paxos的运行机理。
group对象的初始化较为复杂,我们会在后面相关章节进行进一步的分析。
3.1 phxpaxos日志存储
默认情况下,我们会在phxecho程序运行的当前目录下创建logpath_<ip>_<port>
文件夹,用于保存phxpaxos的操作日志。现在我们来大体看一下该文件夹的结构:
# tree logpath_127.0.0.1_11111 logpath_127.0.0.1_11111 └── g0 ├── 000015.log ├── 000016.ldb ├── CURRENT ├── LOCK ├── LOG ├── LOG.old ├── MANIFEST-000013 └── vfile ├── 0.f ├── LOG └── meta 2 directories, 10 files
我们可以看到,对于每一个group,有一个单独的目录来存放其oplog。里面leveldb主要用于存放instanceID
、SystemVariables
以及MasterVariables
;而vfile文件夹会存放我们提交过的proposal
信息,从而有我们整个操作的完整记录。
vfile
文件夹下有如下三类文件:
<x>.f
文件中每条记录的格式如下所示:
其中Length字段保存的是InstanceID与message的总长度,即8+length(message)。上面message消息格式如下:
参看: