Why it matters
Read latency debugging in HBase is impossible without understanding this path. Slow reads can be caused by cold block cache, oversized HFile counts (compaction lag), disabled bloom filters, or slow HDFS. Knowing which stage to blame is what makes ops fast.
Read path knowledge also drives configuration: block cache size, bloom filter tuning, and compaction schedule are all read-path optimizations.
The architecture
Client issues get(row=X) via the Java client library. The client consults its cached meta table to find which RegionServer owns the row's region and sends the get RPC directly.
RegionServer receives the get, finds the target region, and creates a StoreScanner for each column family. Each StoreScanner in turn creates one scanner per storage layer: memstore, and one per HFile.
How it works end to end
The store scanner checks memstore first for the target row. If the row exists in memstore with a live version, that value is included in the merged result.
For each HFile, the scanner first consults the bloom filter (if enabled). If the bloom filter says the row is definitely absent, the HFile is skipped entirely — no HDFS I/O. Otherwise the scanner consults the HFile index to find the block containing the row.
The block is loaded either from block cache (hit, fast) or from HDFS (miss, slower). Once loaded, the scanner iterates within the block to find the target row and any matching cells.
Results from memstore and all HFiles are merged by the store scanner, deduplicated (same row+column+timestamp wins latest write), and returned to the client. The client can iterate the results or apply local processing.