C++ 自制Redis数据库(十三) 持久化AOF日志模块测试完毕

持久化AOF部分测试完毕

废话不多说,一般写日志,很多人就直接write 了,但是效率很低,这里就不详细解释了。

我AOF模块的设计

我是在为我的数据库写这个日志模块所以我需要考虑如下几个指标:

1.并发量不敢说很巨大。但是多个线程同时需要写日志这种可能性还是有的,一个连接给一个线程池中的线程干活,当业务很多的时候,好几个线程同时需要写日志是很可能的,所以需要来考虑。

2.吞吐量这个指标对于一个日志自系统来说都是很重要的,我们当然需要尽量利用硬盘的读写速度。

设计模式

我也查了很多的多路缓冲写日志的相关信息,也问了学长@王伟豪@苗帅,然后还是不晓得怎么搞,大概理解就是开辟缓冲区,然后加锁,当缓冲区到达一定程度的时候执行写文件操作。这样,策略很多,我也是眼花缭乱,我突然想起来之前看过Glibc 的malloc的设计,于是结合着我的需求,我这个多路缓冲日志就应运而生啦。

思路:

开辟几个缓冲区,每个缓冲区均有自己的锁,然后需要写日志的时候,就获取其中的一个锁,写入缓冲区,如果一个线程发现自己写完日志后,正好这个缓冲区满了,那么它就要负责去抢文件的锁,将整个缓冲区一股脑全写进文件里去。

AOF


就是这样,我希望每次来的日志都写进缓冲区去,然后当一个缓冲区满了就去抢写的锁。我们需要尽量将锁的争抢过程放到缓冲区上,文件写锁尽量少发生抢锁的情况,所以我们的缓冲区可以开得大一些。拖延时间,减少文件磁盘IO操作。

下面是一些代码和测试结果



class AOF_FILE{
    private:
        int fd;
    public:
        std::mutex mutex_write;
        AOF_FILE();
};


class AOF_LOG{
    private:
        
        char    (*log_data)[AOF_LOG_MAXSIZE];
        AOF_FILE  FILE_WRITE;
        int useful;
                        
    public:
        std::mutex mutex_log;
        AOF_LOG();
        ~AOF_LOG();
        bool AOF_LOG_ADD(const char *mesg,int flag);
        bool WRITE();

};


class AOF_LOG_DO{
    private:
        AOF_LOG  aof_buffer[AOF_LOG_AREA];
        int useful;
        int resume;
    public:
        AOF_LOG_DO();
        bool AOF_LOG_add(const char *mesg);
        bool AOF_LOG_enforce_write();
        bool AOF_LOG_READ(char *get);
        int & AOF_LOG_getresume();
};

AOF_FILE::AOF_FILE(){
    
    fd = 0;

}

/********************************************************/



AOF_LOG::AOF_LOG(){             /*init  one pice of buffer*/
    
    log_data = new char[AOF_LOG_ELEM][AOF_LOG_MAXSIZE];
    
    useful   = 0;
      
}

AOF_LOG::~AOF_LOG(){
    
    delete [] log_data;

}

bool AOF_LOG::AOF_LOG_ADD(const char *mesg,int flag){
    
    int length = std::strlen(mesg);
    if(length != flag){
	    return false;
    }
    bzero(log_data[useful],AOF_LOG_MAXSIZE);
    memcpy(log_data[useful],mesg,AOF_LOG_MAXSIZE);
    useful++;
    if(useful == AOF_LOG_ELEM){
        WRITE();
    }
    return true;
}

bool AOF_LOG::WRITE(){
    
    while(1){
        if(FILE_WRITE.mutex_write.try_lock()){
            break;
        }
    }
    FILE *fp;
    //fd = open("LOG_AOF.log",O_RDWR|O_APPEND|O_CREAT,777);
    fp = fopen("LOG_AOF.log","ab+");
    if(!fp){
               
        return false;                                             
    }else{
        for(int i = useful;i > 0;i--){
	     
             //write(fd,log_data[i],AOF_LOG_MAXSIZE);
            fwrite(log_data[i],AOF_LOG_MAXSIZE,1,fp);
        }
        useful = 0;
        fclose(fp);
        FILE_WRITE.mutex_write.unlock();
        return true;
    }


}

/*******************************************************/

AOF_LOG_DO::AOF_LOG_DO(){
    useful = 0;
}




bool AOF_LOG_DO::AOF_LOG_add(const char *mesg){

    int length = std::strlen(mesg);
    if(length > AOF_LOG_MAXSIZE){
        return false;                         
    }
    int get_mutex = 1;
    while(get_mutex){
        for(int id = 0;id < AOF_LOG_AREA; id++){    
            if(aof_buffer[id].mutex_log.try_lock()){
                aof_buffer[id].AOF_LOG_ADD(mesg,length); 
                aof_buffer[id].mutex_log.unlock();
                get_mutex = 0;
                break;
            }
        }
    }

}

bool AOF_LOG_DO::AOF_LOG_enforce_write(){    
    for(int i = 0;i < AOF_LOG_AREA;i++){
        while(1){
            if(aof_buffer[i].mutex_log.try_lock()){
                break;
            }
        }
        aof_buffer[i].WRITE();
        aof_buffer[i].mutex_log.unlock();
        
    }
    return true;
}

bool AOF_LOG_DO::AOF_LOG_READ(char *get){
    FILE *fp;
    resume = 0;
    fp = fopen("LOG_AOF.log","rb");
    if(!fp){
        return false;
    }else{
        while(fread(get,AOF_LOG_MAXSIZE,1,fp)){
            
            resume++;
            //std::cout << get << std::endl;
        }
    }
    fclose(fp);
}

int & AOF_LOG_DO::AOF_LOG_getresume(){
    return resume;
}





测试结果

老实说,我也不知道什么样的效果才能算是称职的日志子系统,大家都看看,提提意见,这肯定不是最优的方法。

开4个线程,每个线程写500000(五十万)条日志,总共两百万条日志。

共花费1.9秒,平均每秒100万条日志,100万条日志 大约等于244MB/s.(基本把硬盘都用上了)

以上。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值