Apache HBase

Apache HBase is an open-source clone of Google’s Bigtable, built on top of HDFS as the storage layer. Started in 2008 as part of the Hadoop ecosystem, HBase provides random, strongly-consistent read/write access to massive structured datasets — petabyte-scale tables with billions of rows and millions of columns. HBase remains widely deployed at large enterprises that already run Hadoop, but greenfield projects today usually choose Cassandra, ScyllaDB, or a managed wide-column service instead.

Key Features:

HBase vs. Cassandra:

Use Cases:

Notes:

HBase’s master-region-server topology has more operational complexity than Cassandra’s peer-to-peer ring. For new deployments today the question usually becomes “HBase or Cassandra/Scylla?” — HBase wins when strong consistency is required and Hadoop infrastructure is already in place; otherwise Cassandra or a managed Bigtable / DynamoDB equivalent is typically simpler.

Architecture

HBase Architecture ClientJava API, Shell ZooKeeperlocate hbase:meta HMasterassign regions, DDL RegionServerserves regions WALdurability log MemStoresorted, in memory HFilesflushed, on HDFS Clients find the RegionServer for a row via hbase:meta (located through ZooKeeper) and then talk to it directly; the HMaster is not on the read/write path. Writes go to the WAL and MemStore, then flush to immutable HFiles.

A table is split into regions, each a contiguous range of row keys. Each region is served by exactly one RegionServer at a time, which is how HBase provides strong consistency for single-row operations without a consensus protocol on every write. A write is appended to the RegionServer's write-ahead log on HDFS, then applied to an in-memory MemStore per column family. When a MemStore fills, it is flushed to a new immutable HFile. Background compactions merge HFiles to keep the number of files a read must consult small, and remove deleted or expired cells. Reads merge the MemStore with the relevant HFiles, using a block cache and Bloom filters to skip files that cannot contain the row. If a RegionServer fails, the HMaster reassigns its regions and replays the WAL.

Data Model and Row-Key Design

Logical Data Model: One Row Row keyuser#42 Family: infoname, email Family: statslogins, last_seen Cell versionsby timestamp A cell is addressed by (row key, family:qualifier, timestamp). Families are fixed in the schema; qualifiers are free-form per row. Rows are stored sorted by row key, so key design determines both locality and hotspotting.

HBase is a sorted map, so the only efficient access paths are a get by full row key and a scan over a row-key range. There are no secondary indexes or joins built in. Good row keys therefore encode the query: for time series, sensor_id#reversed_timestamp keeps one sensor's readings together with the newest first. Monotonically increasing keys, such as plain timestamps, send every write to the last region, creating a hotspot; prefixing with a hash or a salt bucket spreads load at the cost of needing several scans for range queries. Keep the number of column families small (one to three), because each family has its own MemStore and files and they flush together.

Example: HBase Shell and Python

hbase shell
create 'users', {NAME => 'info', VERSIONS => 3}, {NAME => 'stats'}
put 'users', 'user#42', 'info:name', 'Ada'
put 'users', 'user#42', 'info:email', 'ada@example.com'
put 'users', 'user#42', 'stats:logins', '17'
get 'users', 'user#42'
scan 'users', {STARTROW => 'user#', STOPROW => 'user$', LIMIT => 10}
incr 'users', 'user#42', 'stats:login_count', 1
# pip install happybase   (talks to the HBase Thrift server)
import happybase

conn = happybase.Connection("hbase-thrift.internal", port=9090)
users = conn.table("users")
users.put(b"user#43", {b"info:name": b"Grace", b"stats:logins": b"3"})
print(users.row(b"user#43"))
for key, data in users.scan(row_prefix=b"user#", limit=10):
    print(key, data.get(b"info:name"))

The shell is a JRuby console, convenient for administration. Applications usually use the native Java client; the Python example goes through the Thrift gateway, which must be running on the cluster.

When to Use HBase

SystemConsistencyTopologyBest fit
HBasestrong per rowmaster + RegionServers on HDFSexisting Hadoop estates, random access next to Spark/MapReduce
Cassandra / ScyllaDBtunable, eventual by defaultmasterless ringwrite-heavy, multi-datacentre
Google Cloud Bigtablestrong in a single clustermanagedBigtable model without operating HDFS
DynamoDBeventual or strong readsmanaged, serverlesskey-value and document access on AWS
Relational DBACID, multi-rowsingle primaryjoins, secondary indexes, moderate scale

Pitfalls