beanstalkd binlog 格式解析

最近工做上须要写一个小工具,用于解析 beanstalkd 的 binlog。一如既往,我先在网上搜索相关的资料。令我惊讶的是,beanstalkd 官方文档中连关于 binlog 格式的只言片语都没有。网络上跟 beanstalkd binlog 格式相关的资料也几乎是个空白。因此在阅读了 beanstalkd 相关源码,并编写了对应工具以后,我试着在本文记下 beanstalkd 的 binlog 的一些相关信息。git

binlog 文件格式

beanstalkd 的 binlog 位于 -b 选项指定的文件夹中,名字就叫 binlog.$order。binlog 的序号 $order 从 1 开始,逐一递增。
binlog 文件大小是固定的,能够经过 -s 选项指定,默认为 10M。beanstalkd 在建立 binlog 文件时,会先用 0 填充文件的所有内容。github

beanstalkd 的 binlog 内容很是浅显直白。每一个 binlog 文件最开始是一个 int 类型的版本号,表示 binlog 版本号。
从 2013 年至今,最新的版本号是 7。能够这么认为,现行见到的 binlog 版本号都是 7。以后是每一个操做的 binlog 记录。
值得一提的是,这里的 int 的大小是由编译时编译器决定的,虽然在主流平台上它的值是 32 位的。在解析时,最好用 int32 或等价操做去
处理它,而不是照搬 int 的定义。好比像 golang 里面的 int 就是默认 64 位的。golang

每一个操做的 binlog 记录由四部份组成:网络

  1. len(tubeName),大小为 int
  2. 可选的 tubeName
  3. 表示 job 元数据的 record
  4. 可选的 job body 内容

job record 的格式以下:工具

// 注意我把 padding 标记成 _,原来的结构体定义里面是没有这个符号的
struct Jobrec {
    uint64 id;          // id >= 1
    uint32 pri;
    uint32 _;           // 注意这里有一个内存对齐致使的 padding
    int64  delay;       // 精确到纳秒
    int64  ttr;         // 精确到纳秒
    int32  body_size;
    int32  _;           // 这里是另一个内存对齐致使的 padding
    int64  created_at;  // 建立时间, epoch 纪年,精确到纳秒
    int64  deadline_at; // 下一个会因超时而产生状态变迁的时间
    uint32 reserve_ct;  // reserve 状态切换计数,_ct 结尾的都是状态计数
    uint32 timeout_ct;
    uint32 release_ct;
    uint32 bury_ct;
    uint32 kick_ct;
    byte   state;
    byte[3] _;          // 又一个 padding
};

建立的操做,会进行 write job full。也即会写入 len(tubeName),tubeName,record,body 这四项记录。
其余操做,会进行 write job short。只写入 0,record 这两项记录。这是由于 record 里面已经存有 id 了,
能够经过 id 获取对应 job 的 tubeName 和 body,因此就不须要在 binlog 里重复记录。ui

record 中的 state 取值以下:spa

enum // Jobrec.state
{
    Invalid,
    Ready,
    Reserved,
    Buried,
    Delayed,
    Copy
};

Ready, Reserved, Buried, Delayed 这四种状态对应的是 beanstalkd protocol
里面 job 的四种状态。
Invalid 对应的是删除特定的 job 的操做。
Copy 是 stats*peek* 系列命令处理过程当中产生的临时 job 才有的状态,不会记录到 binlog 中。日志

当咱们解析到 id 为 0 的 job 时,意味着该 binlog 已经所有解析完毕,能够开始解析下一个 binlog 文件了。code

总之解析每一个 binlog 文件的流程是这样的:
binlog解析过程内存

binlog GC 和 compat

beanstalkd 会不停地产生 binlog 记录,若是缺乏清理机制,很快就会把磁盘给塞满。
beanstalkd 在内部维护每个 binlog 文件的 ref 计数。当一个文件里进行 write job full 操做时,会增长 ref;当一个 job
被删除时,会减小对应文件的 ref。当一个文件的 ref 减至 0,就能够放心地把它删掉了。这一操做,相似于 GC 中的引用计数,
在 beanstalkd 内部实现中也是把它称做 GC。

上述机制有一个问题。若是有个 job 一直不可以被删除掉,则对应的 binlog 文件也会一直没法删除掉。受影响的不止单个文件。因为
beanstalkd 须要保证 binlog 文件的有序性,该文件以后的其余 binlog 也没法被删除掉。

所以 beanstalkd 引入了 compat 机制来解决这个问题。若是实际使用量不及日志量的一半,beanstalkd 会开始进行 compat。compat 不会修改现有 job,但会减小 job 对应文件的 ref,并新写入一条记录。其效果等价于,把一个旧的 job 操做记录移动到新的文件中来。这么一来,就能够避免旧文件的回收被阻塞的状况了。

相关文章
相关标签/搜索