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.
(row key, column family, column qualifier, timestamp) → value. Columns within a family are stored together; different rows can have entirely different columns.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.
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.
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.
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.
| System | Consistency | Topology | Best fit |
|---|---|---|---|
| HBase | strong per row | master + RegionServers on HDFS | existing Hadoop estates, random access next to Spark/MapReduce |
| Cassandra / ScyllaDB | tunable, eventual by default | masterless ring | write-heavy, multi-datacentre |
| Google Cloud Bigtable | strong in a single cluster | managed | Bigtable model without operating HDFS |
| DynamoDB | eventual or strong reads | managed, serverless | key-value and document access on AWS |
| Relational DB | ACID, multi-row | single primary | joins, secondary indexes, moderate scale |