binlog相关的文件包含两部分: manifest和write2file,其中manifest记录了日志元信息,包括当前日志文件编号、当前日志文件偏移量,write2file+num记录了pika接收到的所有redis写命令、参数。文件格式manifest文件格式:日志偏移量(8字节)|con_offset(8字节,未使用)|元素个数(4字节,未使用)|日志文件编号(4字节)。Binlog文件格式:Binlog文件固定大小为100MB,每个Binlog文件由多个Block组成,每个Block大小固定为64KB,每一个写redis命令称为一个Record。一个Record可以分布在多个Block中,但只会分布在一个Binlog文件里,所以Binlog文件有可能大于100MB。#推荐大家可以看看《Linux就该这么学》中学习更多互联网知识。Record格式:Header|Cmd Header: Record Length(3字节)|时间戳(4字节)|记录类型(1字节)。Cmd: redis命令的一部分或者全部,取决于当前Block剩余空间是否可以存放该Record。
基本操作构造Binlog//file_size可以在配置文件指定,默认为100MBBinlog::Binlog(const std::string& binlog_path, const int file_size)1.1创建binlog文件目录。1.2检查log目录下manifest文件是否存在,不存在则新建。1.3根据manifest文件初始化Version类。1.4根据manifest中的filenum找到对应的日志文件,根据pro_offset定位到文件append的位置,初始化日志指针、记录日志内容长度、Block块数量。更新当前日志生产状态//pro_num: 日志文件编号//pro_offset: 日志文件偏移量//用在需要全量同步时更新slave实例对应的binlog信息Status Binlog::SetProducerStatus(uint32_t pro_num, uint64_t pro_offset)2.1 删除write2file0。2.2 删除write2file+pro_num。2.3 构造新的write2file+pro_num文件,填充pro_offset个空格,初始化version->pro_num为pro_num,version->pro_offset为pro_offset,并刷新到manifest文件中。2.4 初始化当前filesize、block_offset。更新当前日志生产状态//filenum: 当前日志编号//pro_offset: 当前日志偏移量Status Binlog::GetProducerStatus(uint32_t* filenum, uint64_t* pro_offset)3.1 读取version中的pro_num、pro_offset并返回。生产日志//Put->Produce->EmitPhysicalRecordStatus Binlog::Put(const std::string &item)4.1检查当前日志文件是否满足切割条件,如果满足则进行切割。4.1.1 pro_num自增加1,初始化新的日志文件,version->pro_num=pro_num,version->pro_offset = 0,binlog->filesize = 0,binlog->block_offset = 0。4.1.2 如果当前block剩余大小