Class FSHLog.RingBufferEventHandler

java.lang.Object
org.apache.hadoop.hbase.regionserver.wal.FSHLog.RingBufferEventHandler
All Implemented Interfaces:
com.lmax.disruptor.EventHandler<RingBufferTruck>, com.lmax.disruptor.LifecycleAware
Enclosing class:
FSHLog

class FSHLog.RingBufferEventHandler extends Object implements com.lmax.disruptor.EventHandler<RingBufferTruck>, com.lmax.disruptor.LifecycleAware
Handler that is run by the disruptor ringbuffer consumer. Consumer is a SINGLE 'writer/appender' thread. Appends edits and starts up sync runs. Tries its best to batch up syncs. There is no discernible benefit batching appends so we just append as they come in because it simplifies the below implementation. See metrics for batching effectiveness (In measurement, at 100 concurrent handlers writing 1k, we are batching > 10 appends and 10 handler sync invocations for every actual dfsclient sync call; at 10 concurrent handlers, YMMV).

Herein, we have an array into which we store the sync futures as they come in. When we have a 'batch', we'll then pass what we have collected to a SyncRunner thread to do the filesystem sync. When it completes, it will then call SyncFuture.done(long, Throwable) on each of SyncFutures in the batch to release blocked Handler threads.

I've tried various effects to try and make latencies low while keeping throughput high. I've tried keeping a single Queue of SyncFutures in this class appending to its tail as the syncs coming and having sync runner threads poll off the head to 'finish' completed SyncFutures. I've tried linkedlist, and various from concurrent utils whether LinkedBlockingQueue or ArrayBlockingQueue, etc. The more points of synchronization, the more 'work' (according to 'perf stats') that has to be done; small increases in stall percentages seem to have a big impact on throughput/latencies. The below model where we have an array into which we stash the syncs and then hand them off to the sync thread seemed like a decent compromise. See HBASE-8755 for more detail.