GreenPlum中高可用实现与恢复简介
2015-11-04
在上一篇文章中介绍了除了master外,primary和mirror的进程以及其主要的作用。本文主要从业务流程上将各个进程的处理功能串联一下。
GreenPlum中的文件
在PostgreSQL数据库中主要存在两类文件:数据文件和非数据文件。这两个概念在GreenPlum中用BufferPoolFile和FlatFile来说明。相对于PostgreSQL,在GreenPlum增加了另外一种文件类别--append only,什么意思呢?查了一下相关的概念:
This allows for more compact storage on disk because each row does not need to store the MVCC(Unlike traditional database systems which use locks for concurrency control, Greenplum Database (as does PostgreSQL) maintains data consistency by using a multiversion model (multiversion concurrency control or MVCC). This means that while querying a database, each transaction sees a snapshot of data which protects the transaction from viewing inconsistent data that could be caused by (other) concurrent updates on the same data rows. This provides transaction isolation for each database session.MVCC, by eschewing explicit locking methodologies of traditional database systems, minimizes lock contention in order to allow for reasonable performance in multiuser environments. The main advantage to using the MVCC model of concurrency control rather than locking is that in MVCC locks acquired for querying (reading) data do not conflict with locks acquired for writing data, and so reading never blocks writing and writing never blocks reading.) transaction visibility info. This saves 20 bytes per row. AO tables can also be compressed.
根据前面介绍的primary和mirror多进程差异,需要思考的一个问题是,数据如何在其之间同步的?在GreenPlum中定义了一类文件同步操作接口,在primary上主要为FileRepPrimary_mirror,在mirror上主要为FileRepMirror_。
前面提到在GreenPlum中总共有三类文件类型,拿primary为例,其在FileRepPrimary_mirror*之上封装了三类操作,分别为:
cdb/cdbmirroredappendonly.c: MirroredAppendOnly_Open();MirroredAppendOnly_Create();...
cdb/cdbmirroredbufferpool.c: MirroredBufferPool_Open();MirroredBufferPool_Create();...
cdb/cdbmirroredflatfile.c: MirroredFlatFile_Open();MirroredFlatFile_Create();...
实际上在cdb目录下还存在另外一种mirror操作:cdbmirroredfilesysobj.c中定义的接口,实际上这些操作并没有直接参与primary-mirror同步,此处不详细展开。
GreenPlum中的高可用
那么介绍了这些接口的概念后,业务数据如何在primary和mirror间同步的呢?举一个很简单的列子:针对一个simple table,执行语句INSERT INTO table VALUES (...)往表中插入记录。语句经过词法->语法->语义->计划->优化->执行,可能简单语句会跳过很多处理,最终会调用heap_insert将记录插入到heap page中,并且针对这个插入操作封装一条xlog record插入到wal page中。数据最终被转化为格式化的信息存到了两类文件中,数据文件以及日志文件。在GreenPlum中这两种存储的信息会从primary同步到mirror。
回忆一下,在PostgreSQL中的高可用是这样的:主机(primary)上执行insert同样会产生数据和日志信息并写入存储介质,存在一个进程walsender进程,周期性检测日志文件是否被更新,看清楚是日志文件 日志文件 日志文件,如果发现日志文件发生更新,则从日志文件中读取新插入的那些日志记录,通过网络发送到备机(mirror),备机alreceiver进程收到日志记录后写入到相应的日志文件中,由恢复进程startup读取文件中新写入的日志记录进行恢复,从而完成主备的一个同步过程。由于涉及到跨网络的进程传输,因此在walsender-walreceiver之间增加了心跳信息。
GreenPlum与PostgreSQL不同之处在于,日志和数据都会同步到备机,而不单单是日志,并且同步的方式不同,信息的同步直接是从内存同步而没有经过写盘读取磁盘上的数据这样的过程,效率相对要高一些。
日志同步
产生日志时,backend进程会调用XLogWrite函数将日志信息写入磁盘,并且根据条件决定是否需要flush。在GreenPlum中,日志的打开读写都与主备同步点滴相关。写记录来举例一下,在PostgreSQL中使用write函数将日志写入磁盘就完了,在GreenPlum中要复杂的多,具体而言,因为日志文件是flat file,因此此处使用MirroredFlatFile_Write函数替换了write函数。
MirroredFlatFile_Write函数中,首先调用前面介绍的更底层的操作接口FileRepPrimary_MirrorWrite将数据发送给备机,然后使用FileSeek&FileWrite接口将数据才真正的写入本地日志文件。
展开来看FileRepPrimary_MirrorWrite函数中,首先通过FileRep_ReserveShmem()从共享内存申请空间,然后针对要同步的数据,构造FileRepMessageHeader,将消息头以及需要同步的数据放入申请的共享空间。使用FileRep_IpcSignal通知消费者去共享内存中取数据。这个就是所谓前面提到的通过信号量及共享内存进行程序内多进程的同步。
这里的消费者就是primary sender进程,进程的工作方式以及作用参见前文中的介绍,sender进程将数据再封装发送到备机端, 备机的mirror receiver进程将受到的数据进行初步解析确定属于哪种类型的数据,将数据同样放入本地的接受共享空间,针对不同的数据类型使用ipc信号通知不同的消费者,这里就是为什么备机上会有三个消费者(mirror consumer、mirror consumer writer以及mirror consumer append only)的原因了。
当前场景下日志数据属于flat file,此处通知的是mirror comsumer进程,mirror comsumer进程从共享内存中取到最新的日志数据,发现类型为FileRepOperationWrite,将日志写入对应的日志文件。本次日志信息同步结束。
数据同步
数据同步 不同于日志同步,日志同步在日志记录产生时就会同步,而数据并非如此,INSERT修改或者产生页面后,页面被缓存在bufferpool中,当发生checkpoint时,会调用flushbuffer将所有脏页面刷盘,最终调用存储底层smgrwrite的实现mdwrite将数据页面写入磁盘。
在GreenPlum中数据的同步就发生在这个阶段,mdwrite真正的实现被封装为MirroredBufferPool_Write,就是我们上面提到的其中一类接口中的一种。MirroredBufferPool_Write底层调用FileRepPrimary_MirrorWrite将页面数据同步到备机,整体流程与日志类似,此处不再详述。
实际上在GreenPlum中的主备同步,存在同步和异步的区别,即有些操作主机不需要等待数据同步到备机,比如前面提到的两类。同样存在其他操作需要强同步的,在GreenPlum中的实现方式一般为:主机先将操作信息放入发送共享队列,同时插入到共享哈希表中,然后进行本地操作,最后等待检查哈希表中备机反馈的信息完成后,操作才算完成。
GreenPlum中的恢复
在GreenPlum中只有产生实际数据的实例才需要恢复,和PostgreSQL不同的是,因为数据是直接被同步到备机的,所以备机不需要恢复,在主机发生故障,备机failover时其效率肯定是很不错的。 对于primary和master而言,数据库的恢复与PostgreSQL基本类似,不同之处是在reaper中如果是startup进程退出,则根据条件会拉起另外几个恢复进程进行额外的处理。
morning sweety.
Category: 润物细无声 Tagged: GreenPlum