4.2.10 主备机制
openGauss提供主备机制来保障数据的高可靠和数据库服务的高可用。如图4-37所示,在主、备实例之间通过日志复制来进行数据库数据和状态的一致性同步。日志同步是指将主机对数据的修改日志同步到备机,备机通过日志回放将日志重新还原为数据修改。
图4-37 主备机日志同步示意图
参与日志同步的主要有“wal sender”(主机端)和“wal receiver”(备机端)两个线程。一个主机上可以由多个“wal sender”线程同时存在,用于给不同的备机进行日志复制;一个备机上同一时刻只会有一个“wal receiver”线程,从唯一一个指定的主机上拷贝日志。
“wal sender”线程的所有关键信息均保存在knl_t_walsender_context结构体中,其定义代码如下:
typedef struct knl_t_walsender_context {
char* load_cu_buffer;
int load_cu_buffer_size;
struct WalSndCtlData* WalSndCtl;
struct WalSnd* MyWalSnd;
int logical_xlog_advanced_timeout;
DemoteMode Demotion;
bool wake_wal_senders;
bool wal_send_completed;
int sendFile;
XLogSegNo sendSegNo;
uint32 sendOff;
struct WSXLogJustSendRegion* wsXLogJustSendRegion;
XLogRecPtr sentPtr;
XLogRecPtr catchup_threshold;
struct StringInfoData* reply_message;
struct StringInfoData* tmpbuf;
char* output_xlog_message;
Size output_xlog_msg_prefix_len;
char* output_data_message;
uint32 output_data_msg_cur_len;
XLogRecPtr output_data_msg_start_xlog;
XLogRecPtr output_data_msg_end_xlog;
struct XLogReaderState* ws_xlog_reader;
TimestampTz last_reply_timestamp;
TimestampTz last_logical_xlog_advanced_timestamp;
bool waiting_for_ping_response;
volatile sig_atomic_t got_SIGHUP;
volatile sig_atomic_t walsender_shutdown_requested;
volatile sig_atomic_t walsender_ready_to_stop;
volatile sig_atomic_t response_switchover_requested;
ServerMode server_run_mode;
char gucconf_file[MAXPGPATH];
char gucconf_lock_file[MAXPGPATH];
FILE* ws_dummy_data_read_file_fd;
uint32 ws_dummy_data_read_file_num;
struct cbmarray* CheckCUArray;
struct LogicalDecodingContext* logical_decoding_ctx;
XLogRecPtr logical_startptr;
int remotePort;
bool walSndCaughtUp;
} knl_t_walsender_context;
其中:
(1) WalSndCtl指向保存全局所有“wal sender”线程控制状态的共享结构体,是一致性复制协议的关键所在。
(2) MyWalSnd指向上述全局共享结构体中当前“wal sender”线程的槽位。
(3) Demotion为当前主机降备模式,分为未降备(NoDemote)、优雅降备(SmartDemote)和快速降备(FastDemote)。
(4) sendFile、sendSegNo、sendOff用于保存当前复制的日志文件的文件操作状态。
(5) reply_message用于保存备机回复的消息。
(6) output_xlog_message为待发送的日志内容主体。
(7) server_run_mode为wal sender线程启动时的HA(high availability,HA)高可靠性)状态,即主机(primary)、备机(standby)或未决(pending)。
(8) walSndCaughtUp指示备机是否已经追赶上主机。
(9) remotePort为wal receiver线程的端口,用于身份验证。
(10) load_cu_buffer 、load_cu_buffer_size 、output_data_message、output_data_msg_cur_len、output_data_msg_start_xlog、output_data_msg_end_xlog、ws_xlog_reader、CheckCUArray为后续支持混合类型(日志+增量页面)复制的预留接口。
wal receiver线程的所有关键信息均保存在knl_t_walreceiver_context结构体中,其定义代码如下:
typedef struct knl_t_walreceiver_context {
volatile sig_atomic_t got_SIGHUP;
volatile sig_atomic_t got_SIGTERM;
volatile sig_atomic_t start_switchover;
char gucconf_file[MAXPGPATH];
char temp_guc_conf_file[MAXPGPATH];
char gucconf_lock_file[MAXPGPATH];
char** reserve_item;
time_t standby_config_modify_time;
time_t Primary_config_modify_time;
TimestampTz last_sendfilereply_timestamp;
int check_file_timeout;
struct WalRcvCtlBlock* walRcvCtlBlock;
struct StandbyReplyMessage* reply_message;
struct StandbyHSFeedbackMessage* feedback_message;
struct StandbySwitchRequestMessage* request_message;
struct ConfigModifyTimeMessage* reply_modify_message;
volatile bool WalRcvImmediateInterruptOK;
bool AmWalReceiverForFailover;
bool AmWalReceiverForStandby;
int control_file_writed;
} knl_t_walreceiver_context;
其中:
(1) walRcvCtlBlock指向“wal receiver”线程主控数据,保存当前日志复制进度,备机日志写盘、写入磁盘进度,以及接收日志缓冲区。
(2) reply_message保存用于回复主机的消息。
(3) feedback_message用于保存热备的相关信息,供主机空闲空间清理时参考。
(4) request_message用于保存主机降备请求的相关信息。
(5) reply_modify_message用于保存请求配置文件复制的相关信息。
(6) AmWalReceiverForFailover表示当前“wal receiver”线程处于failover场景下,连接从备进行日志追赶。
(7) AmWalReceiverForStandby表示当前“wal receiver”线程为连接备机进行日志复制的级联备机。
主备日志同步,主要包括以下6个场景。