在金融,电商,等高可用环境下,不允许有任何数据丢失的情况,redo log 是一个不错的低成本高可用方案,其作用有点类似mysql binlog, 下面在生产环境中事件和优化的多线程安全,自己恢复的 c++ redo log 类,在实际生产过程遇到相应问题,很多地方进行优化设计,尽量保持高性能和高可靠性。
/******************************************************
function: redo log is use for service restart, sys crash
and Exception to recover the data.
author: liuyi
date:2016.08.26
version:1.0
******************************************************/
#ifndef REDO_LOG_H
#define REDO_LOG_H
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <string.h>
#include <fstream>
#include <pthread.h>
#include <vector>
#include <map>
#include <set>
using namespace std;
struct redo_file_pair_info
{
int file_max_lines;
int file_input_lines;
int file_output_lines;
FILE *output_log_ptr;
};
struct reload_data
{
string file_prefix;
string uid;
string log_str;
};
class redo_log
{
public:
redo_log()
{
m_log_version = 0;
m_uuid = 0;
m_input_log_lines = 0;
m_max_log_lines = 100000;
m_rm_finish_log_time = 5;
m_mutex = new pthread_mutex_t;
pthread_mutex_init(m_mutex, NULL);
sleep(1);//insure every start the log file name is not same
m_start_time = time(NULL);
char tmp[64] = {0};
sprintf(tmp, "%lu_%lld", m_start_time, m_log_version);
m_current_input_prefix = string(tmp);
}
~redo_log()
{
if(m_mutex != NULL)
{
pthread_mutex_destroy(m_mutex);
delete m_mutex;
m_mutex = NULL;
}
}
bool init(const string& redo_log_path, int max_log_lines, int rm_finish_log_time = 5)
{
m_path = redo_log_path;
m_max_log_lines = max_log_lines;
m_rm_finish_log_time = rm_finish_log_time;
char file_name[1024] = {0};
snprintf(file_name, 1023, "%s/%s.input", m_path.c_str(), m_current_input_prefix.c_str());
m_input_log = fopen(file_name, "w");
memset(file_name, '\0', 1024);
snprintf(file_name, 1023, "%s/%s.output", m_path.c_str(), m_current_input_prefix.c_str());
m_output_log = fopen(file_name, "w");
redo_file_pair_info new_file;
new_file.file_max_lines = m_max_log_lines;
new_file.file_input_lines = 0;
new_file.file_output_lines = 0;
new_file.output_log_ptr = m_output_log;
m_file_pair_info_map.insert(pair<string, redo_file_pair_info>(m_current_input_prefix, new_file));
++m_log_versi