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。