【openGauss技术文档openGauss极致RTO日志处理流程简介

2024年 5月 21日 86.1k 0

极致RTO简单介绍

极致RTO是openGauss在并行回放的基础上,实现的一个加速回放功能。其主要原理是将record粒度的日志拆分成block粒度的日志进行回放,通过增加流水线和redoworker线程的数量,并且利用相关hash算法,保证同一张表的日志由同一流水线回放,以此提高回放速度和回放并发度。

极致RTO相关参数

recovery_parse_workers > 1 或 recovery_redo_workers > 1,即为开启极致TO.

recovery_parse_workers

参数说明: 是极致RTO特性中ParseRedoRecord线程的数量。

该参数属于POSTMASTER类型参数,请参考表1中对应设置方法进行设置。

取值范围:整型,1~16

仅在开启极致RTO情况下可以设置recovery_parse_workers为>1。需要配合recovery_redo_workers使用。若同时开启recovery_parse_workers和recovery_max_workers,以开启极致RTO的recovery_parse_workers为准,并行回放特性失效。因极致RTO不支持主备从模式,仅在参数replication_type设置成1时可以设置recovery_parse_workers为>1。另外,极致RTO也不支持列存,在已经使用列存表或者即将使用列存表的系统中,请关闭极致RTO。极致RTO不再自带流控,流控统一由recovery_time_target参数来控制。

默认值: 1

recovery_redo_workers

参数说明: 是极致RTO特性中每个ParseRedoRecord线程对应的PageRedoWorker数量。

该参数属于POSTMASTER类型参数,请参考表1中对应设置方法进行设置。

取值范围:整型,1~8

需要配合recovery_parse_workers使用。在配合recovery_parse_workers使用时,只有recovery_parse_workers大于1,recovery_redo_workers参数才生效。

默认值: 1

极致RTO回放线程类型

REDO_BATCH 负责record粒度的日志拆分成block粒度,并分发给redo manager线程

REDO_PAGE_MNG, 负责向redo worker线程分发xlog

REDO_PAGE_WORKER, 负责回放

REDO_TRXN_MNG, 负责向trxn worker分发xlog

REDO_TRXN_WORKER, 负责回放事务日志

REDO_READ_WORKER, 流复制场景,用于从磁盘读xlog

REDO_READ_PAGE_WORKER, 负责从磁盘读取xlog或从xlog缓冲区读取xlog,并校验完整性

REDO_READ_MNG, 负责控制读xlog线程

REDO_SEG_WORKER, 按需回放新增线程,

REDO_HTAB_MNG, 按需回放新增线程,

REDO_CTRL_WORKER, 按需回放新增线程,

Startup线程:负责将日志分发给对应的流水线

极致RTO流水线示意图

极致RTO后台有多个流水线,由recovery_parse_workers 参数控制,通过特定的hash算法,可以保证同一个表的日志一定会路由到特定的流水线回放,以保证日志回放时有序

【openGauss技术文档】openGauss极致RTO日志处理流程简介-1

各线程功能简述

REDO_READ_WORKER

主函数:XLogReadWorkerMain

流复制场景,用于从磁盘读xlog,该线程会把xlog从磁盘读取到g_recordbuffer->xlogsegarray[readindex],read buffer中。

代码流程

XLogReadWorkerMain->XLogReadWorkRun->XLogReadFromWriteBuffer

【openGauss技术文档】openGauss极致RTO日志处理流程简介-2

REDO_READ_PAGE_WORKER

XLogReadPageWorkerMain,循环读取xlog,将读到的xlog record,解析为XLogReaderState,并置入g_dispatcher->readLine.readPageThd->queue传递给startup线程

  • 流复制场景(传统主备),
    • failover阶段,IsRecoveryDone == false,从磁盘读xlog。
    • 备机normal状态,IsRecoveryDone == true,用于从g_recordbuffer->xlogsegarray[readindex]缓冲区读取日志,传递给Startup线程。
  • 资源池化场景,XLogReadPageWorkerMain同时负责读取xlog和解析xlog传递给startup线程。

代码流程

xlog读取主流程

XLogReadPageWorkerMain->XLogParallelReadNextRecord->ParallelReadRecord->ParallelReadPageInternal->ParallelXLogPageRead

读xlog的场景分类

  1. 流复制场景(传统主备):ParallelXLogReadWorkBufRead->XLogPageReadForExtRto
  2. 资源池化,从DSS读xlog文件:SSXLogPageRead
  3. 非池化,通过文件系统读xlog文件:ParallelXLogPageReadFile

XLogReadPageWorkerMain循环流程

读xlog:XLogParallelReadNextRecord

生成下一个readerState: NewReaderState

更新读取最新xlog的起止点:

g_redoWorker->lastReplayedReadRecPtr = xlogreader->ReadRecPtr;
g_redoWorker->lastReplayedEndRecPtr = xlogreader->EndRecPtr;

更新g_GlobalLsnForwarder:SendLsnFowarder

把读到的xlog(XLogReaderState)存入队列:PutRecordToReadQueue

【openGauss技术文档】openGauss极致RTO日志处理流程简介-3

StartupXLOG

代码流程

循环执行以下流程直到XLogReaderState == NULL

  • 从队列中读取下一条xlog:ReadNextXLogRecord->ReadNextRecordFromQueue->SPSCBlockingQueueTake(g_dispatcher->readLine.readPageThd->queue)
    • 读取获取到record后解析xlog,从XLogReaderState解析到XLogRecord,DecodeXLogRecord
    • 如果读到g_redoEndMark.record,则退出循环
    • 如果读取到g_GlobalLsnForwarder.record或g_cleanupMark.record,调用StartupSendFowarder,向所有batchRedo线程和txnmanager线程分发该日志
  • 将xlog解析成RedoItem ,并分发给下一级流水线线程
    • DispatchRedoRecord->ExtremeDispatchRedoRecordToFile->g_dispatchTable[rmid].rm_dispatch(record, expectedTLIs, recordXTime);
    • 根据XLogReaderState 偏移获取RedoItem : RedoItem *item = GetRedoItemPtr(record);
    • 根据xlog的类型(rmid),选择对应的分发方法:g_dispatchTable[rmid].rm_dispatch(record, expectedTLIs, recordXTime);
      • 普通日志通常分发给batchRedo线程(g_dispatcher->pageLines[i].batchThd)。其中,同一个表的日志一般发给某个特定流水线,会通过rnode计算流水线Id:GetSlotId
      • 事务日志分发给txnmanager线程。(g_dispatcher->trxnLine.managerThd),对应函数:DispatchXactRecord
      • ddl相关日志create、truncate,

分发策略:

极致RTO通过函数向下级流水线分发ExtremeDispatchRedoRecordToFile

具体分发方法会根据xlog类型rmid选择对应的分发算法g_dispatchTable[rmid].rm_dispatch(record, expectedTLIs, recordXTime);

在选择流水线时,为了尽量避免回放时的页面交换问题,极致RTO根据relfilenode计算hash值,该hash值用于选择哪一条流水线向下分发日志。对应函数:GetWorkerIds。

【openGauss技术文档】openGauss极致RTO日志处理流程简介-4

BatchRedoMain

循环把record级别的xlog(RedoItem)解析成Block级别的xlog(XLogRecParseState),并传递给PageRedoManager线程进行回放。

  • 从流水线中循环读取区出xlog:BatchRedoMain->SPSCBlockingQueueGetAll(g_redoWorker->queue, &eleArry, &eleNum)
  • 把record级别的xlog(RedoItem)解析成Block级别的xlog(XLogRecParseState): BatchRedoDistributeItems->BatchRedoParseItemAndDispatch->XLogParseToBlockForExtermeRTO->g_xlogParseBlockTable[rmid].xlog_parseblock(record, blocknum)
  • 把 Block级别的xlog分发给下一级流水线:AddPageRedoItem(myRedoLine->managerThd, recordblockstate);

【openGauss技术文档】openGauss极致RTO日志处理流程简介-5

RedoPageManagerMain

把XLogRecParseState根据rnode等信息,分发给RedoPageWorker线程,

  • RedoPageManagerMain->PageManagerRedoDistributeItems->PageManagerRedoParseState->根据日志类型选择解析方式
  • AddPageRedoItem(myRedoLine->redoThd[work_id], record_block_state);

【openGauss技术文档】openGauss极致RTO日志处理流程简介-6

RedoPageWorkerMain

回放上一层流水线下发的日志。不同xlog类型执行函数不同

RedoPageWorkerMain->XLogBlockRedoForExtremeRTO->g_xlogExtRtoRedoTable[block_valid].xlog_redoextrto(blockhead, blockrecbody, bufferinfo);

一些关键变量

特殊xlog标记

RedoItem g_redoEndMark = { false, false, NULL, 0, NULL, 0 };

RedoItem g_terminateMark = { false, false, NULL, 0, NULL, 0 };

RedoItem g_GlobalLsnForwarder;

RedoItem g_cleanupMark;

RedoItem g_closefdMark;

RedoItem g_cleanInvalidPageMark;

不同类型XLOG的处理函数

极致RTOxlog分发函数

src\gausskernel\storage\access\transam\extreme_rto\dispatcher.cpp

static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1]

极致RTO batchRedo线程解析函数

src\gausskernel\storage\access\redo\redo_xlogutils.cpp

static const XLogParseBlock g_xlogParseBlockTable[RM_MAX_ID + 1] = {

极致RTO 回放函数

src\gausskernel\storage\access\redo\redo_xlogutils.cpp

static const XLogBlockRedoExtreRto g_xlogExtRtoRedoTable[BLOCK_DATA_CSNLOG_TYPE + 1] = {
{ XLogBlockDataCommonRedo, BLOCK_DATA_MAIN_DATA_TYPE }, { XLogBlockVmCommonRedo, BLOCK_DATA_VM_TYPE },
{ XLogBlockUndoCommonRedo, BLOCK_DATA_UNDO_TYPE },
{ XLogBlockFsmCommonRedo, BLOCK_DATA_FSM_TYPE }, { XLogBlockDdlCommonRedo, BLOCK_DATA_DDL_TYPE },
{ XLogBlockBcmCommonRedo, BLOCK_DATA_BCM_TYPE }, { XLogBlockNewCuCommonRedo, BLOCK_DATA_NEWCU_TYPE },
{ XLogBlockClogCommonRedo, BLOCK_DATA_CLOG_TYPE }, { XLogBlockCsnLogCommonRedo, BLOCK_DATA_CSNLOG_TYPE },
};

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论