HBase源码系列(七)WAL与日志恢复

WAL

Write Ahead Log (WAL)其实就是以前的HLog。在2.0之前,HBase中的WAL接口被命名为HLog。 在0.94中,HLog是WAL实施的名称。 您可能会在为这些旧版本定制的文档中找到对HLog的引用。

MultiWAL

MultiWAL允许RegionServer通过在底层HDFS实例中使用多个管道来并行写入多个WAL流,从而提高写入期间的总吞吐量。
使用原始WAL实现的RegionServers和使用MultiWAL实现的RegionServers可以分别处理任意一组WAL的恢复,因此通过滚动重启可以实现零停机配置更新。
为RegionServer配置MultiWAL,设置hbase.wal.provider 为 multiwal。

<property>
  <name>hbase.wal.provider</name>
  <value>multiwal</value>
</property>

修改后需要重启RegionServer才能生效。
关闭MultiWAL,就不要设置这个属性,然后重启RegionServer。

WAL Compression

WAL可以使用LRU Dictionary进行压缩,进而提升WAL复制到不同datanode节点的效率。通过设置 hbase.regionserver.wal.enablecompression 为 true,可以启用这个压缩机制(默认情况下,这个属性为false)。

Disabling the WAL

在特殊的情况下,为了提高性能,可能会关闭WAL。
HBase client 关闭WAL有下面的方式,但是在table上已经不提供关闭WAL的方式。

Mutation.writeToWAL(false)
或者
Mutation.setDurability(Durability.SKIP_WAL)

推荐在bulk load的时候,关闭WAL。其他情况下,都不建议关闭WAL,因为这会让你的数据处于危险之中。

Put过程中记录WAL

在服务端进行写入数据之前,会实例化WALEdit类,在日志中来记录需要写入的数据

// 4. Let the processor scan the rows, generate mutations and add waledits
   doProcessRowWithTimeout(processor, now, this, mutations, walEdit, timeout);

然后会将要写入的数据写入到memstore,后续会将memstore flush到HStore中做持久化。
写入memstore以后,追加日志到WAL

walKey = new HLogKey(this.getRegionInfo().getEncodedNameAsBytes(),
        this.htableDescriptor.getTableName(), WALKey.NO_SEQUENCE_ID, now,
        processor.getClusterIds(), nonceGroup, nonce);
// 追加walEdit日志到wal,实际调用的是子类FSHLog的append()方法
txid = this.wal
        .append(this.htableDescriptor, this.getRegionInfo(), walKey, walEdit, getSequenceId(),
                true, memstoreCells);

============================
// 这里使用了Disruptor 并发框架
FSWALEntry entry = null;
    long sequence = this.disruptor.getRingBuffer().next();
    try {
      RingBufferTruck truck = this.disruptor.getRingBuffer().get(sequence);

      entry = new FSWALEntry(sequence, key, edits, sequenceId, inMemstore, htd, hri, memstoreCells);
      truck.loadPayload(entry, scope.detach());
    } finally {
      this.disruptor.getRingBuffer().publish(sequence);
    }

日志追加到WAL后,又同步了事务txid。这里的代码有点看不懂了。

// 11. Sync edit log
if (txid != 0) {
    syncOrDefer(txid, getEffectiveDurability(processor.useDurability()));
}
walSyncSuccessful = true;

对上面数据写入过程中记录WAL的操作做个总结:
1、首先实例化WALEdit,来记录需要写入的日志;
2、数据写入memstore后,使用Disruptor并发框架追加waledit日志到WAL,并记录事务txid;
3、同步事务txid。

日志恢复

猜你喜欢

转载自blog.csdn.net/oitebody/article/details/78555877