6.1 HBase를 발명한 사람과 이유
이 강의에서는 최근 큰 인기를 얻은 Hbase와 같은 훌륭한 도구에 대해 이야기할 것입니다. 예를 들어 Facebook은 이를 메시징 시스템의 기반으로 사용하는데 이것은 이미 많은 것을 말해줍니다.
강의에서는 Big Table의 개념과 무료 구현, 작업의 특징 및 고전적인 관계형 데이터베이스(예: MySQL 및 Oracle) 및 키-값 스토리지(예: Redis, Aerospike 및 memcached)와의 차이점에 대해 이야기합니다. 평소와 같이 문제의 역사부터 시작하겠습니다. 다른 많은 BigData 프로젝트와 마찬가지로 Hbase는 Google에서 개발한 개념에서 탄생했습니다. Hbase의 기본 원칙은 Bigtable: A Distributed Storage System for Structured Data 기사에 설명되어 있습니다 .
이전 강의에서 논의한 것처럼 일반 파일은 MapReduce 패러다임을 사용하여 배치 데이터 처리에 매우 적합합니다. 반면에 파일에 저장된 정보는 업데이트하기가 다소 불편합니다. 파일에 대한 임의 액세스 가능성도 박탈됩니다. 임의 액세스로 빠르고 편리한 작업을 위해 Aerospike, Redis, Couchbase, Memcached와 같은 키-값 저장소와 같은 nosql 시스템 클래스가 있습니다. 그러나 일괄 처리는 일반적으로 이러한 시스템에서 매우 불편합니다. Hbase는 배치 처리의 편리함과 업데이트 및 임의 액세스의 편리함을 결합하려는 시도입니다.
![](https://cdn.codegym.cc/images/article/54d64a29-4642-4c59-8211-2b143dfcd48a/512.jpeg)
6.2 데이터 모델
HBase는 분산형 열 지향 다중 버전 키-값 데이터베이스입니다.
- 데이터는 Hbase에서 RowKey라는 기본 키로 인덱싱된 테이블로 구성됩니다.
- 각 RowKey 키에 대해 특성(또는 열) 집합을 무제한으로 저장할 수 있습니다.
- 열은 열 패밀리라고 하는 열 그룹으로 구성됩니다. 원칙적으로 동일한 사용량과 저장 패턴을 가진 열은 하나의 Column Family로 결합됩니다.
- 각 속성에 대해 여러 다른 버전을 저장할 수 있습니다. 버전마다 타임스탬프가 다릅니다.
레코드는 물리적으로 RowKey 정렬 순서로 저장됩니다. 이 경우 서로 다른 Column Family에 해당하는 데이터가 별도로 저장되어 필요에 따라 원하는 컬럼 패밀리의 데이터만 읽을 수 있습니다.
특정 속성이 삭제되면 물리적으로 즉시 삭제되지 않고 특수한 삭제 표시 플래그로만 표시됩니다. 데이터의 물리적 삭제는 Major Compaction 작업이 수행될 때 나중에 발생합니다.
동일한 열 그룹에 속하고 동일한 키에 해당하는 속성은 물리적으로 정렬된 목록으로 저장됩니다. 모든 속성은 각 키에 대해 없거나 존재할 수 있으며 속성이 없는 경우 빈 값을 저장하는 오버헤드가 발생하지 않습니다.
목록 및 열 그룹 이름은 고정되어 있으며 레이아웃이 명확합니다. 열 그룹 수준에서 TTL(Time to Live) 및 최대 저장 버전 수와 같은 매개 변수가 설정됩니다. 특정 버전의 타임스탬프와 현재 시간의 차이가 TTL보다 크면 항목이 삭제 대상으로 표시됩니다. 특정 속성의 버전 수가 최대 버전 수를 초과하면 레코드도 삭제 표시됩니다.
![](https://cdn.codegym.cc/images/article/38a31201-f909-4a45-9792-a5d72225f060/512.jpeg)
Hbase 데이터 모델은 키-값 일치로 기억할 수 있습니다.
<table, RowKey, Column Family, Column, timestamp> -> Value
6.3 지원되는 작업
hbase에서 지원되는 작업 목록은 매우 간단합니다. 4가지 주요 작업이 지원됩니다.
- Put : hbase에 새 항목을 추가합니다. 이 항목의 타임스탬프는 수동으로 설정할 수 있습니다. 그렇지 않으면 자동으로 현재 시간으로 설정됩니다.
- Get : 특정 RowKey에 대한 데이터를 가져옵니다. 데이터를 가져올 열군과 읽으려는 버전 수를 지정할 수 있습니다.
- 스캔 : 레코드를 하나씩 읽습니다. 읽기 시작하는 레코드, 읽을 레코드, 읽을 레코드 수, 읽기가 수행될 Column Family 및 각 레코드의 최대 버전 수를 지정할 수 있습니다.
- 삭제 : 삭제할 특정 버전을 표시합니다. 물리적인 삭제는 없으며 다음 Major Compaction까지 연기됩니다(아래 참조).
6.4 아키텍처
HBase는 수십 또는 수백 대의 물리적 서버에서 실행할 수 있는 분산 데이터베이스로, 일부 서버가 실패하더라도 중단 없는 운영을 보장합니다. 따라서 HBase의 아키텍처는 기존 관계형 데이터베이스에 비해 상당히 복잡합니다.
![](https://cdn.codegym.cc/images/article/5bae086c-b213-47db-be33-a23d854a1543/1024.jpeg)
HBase는 작업에 두 가지 주요 프로세스를 사용합니다.
1. 지역 서버 - 하나 이상의 지역에 서비스를 제공합니다. 영역은 특정 범위의 연속 RowKey에 해당하는 레코드 범위입니다. 각 지역에는 다음이 포함됩니다.
- 영구 저장소 는 HBase의 주요 데이터 저장소입니다. 데이터는 특수 HFile 형식으로 HDFS에 물리적으로 저장됩니다. HFile의 데이터는 RowKey 정렬 순서로 저장됩니다. 한 쌍(영역, 컬럼 패밀리)은 적어도 하나의 HFIle에 해당합니다.
- MemStore - 쓰기 버퍼. 데이터가 정렬된 순서로 HFile d에 저장되기 때문에 레코드당 HFile을 업데이트하는 데 비용이 많이 듭니다. 대신 데이터를 쓸 때 데이터가 특정 MemStore 메모리 영역에 들어가 일정 시간 동안 축적됩니다. MemStore가 일부 임계 값으로 채워지면 데이터가 새 HFile에 기록됩니다.
- BlockCache - 읽기용 캐시. 자주 읽는 데이터의 시간을 크게 절약할 수 있습니다.
- WAL(Write Ahead Log) . 데이터가 memstore에 기록되기 때문에 크래시로 인해 데이터가 손실될 위험이 있습니다. 이를 방지하기 위해 실제 조작을 구현하기 전의 모든 작업은 특수 로그 파일에 저장됩니다. 이를 통해 오류 발생 후 데이터를 복구할 수 있습니다.
2. 마스터 서버 - HBase 클러스터의 주 서버입니다. 마스터는 지역 서버 간의 지역 분포를 관리하고, 지역 등록을 유지하고, 정규 작업 시작을 관리하고, 기타 유용한 작업을 수행합니다.
서비스 간의 작업을 조정하기 위해 HBase는 구성을 관리하고 서비스를 동기화하도록 설계된 특수 서비스인 Apache ZooKeeper를 사용합니다.
영역의 데이터 양이 증가하여 일정 크기에 도달하면 Hbase는 영역을 2로 분할하는 분할 작업을 시작합니다. 영역의 지속적인 분할을 피하기 위해 영역의 경계를 미리 설정하고 최대값을 늘릴 수 있습니다. 크기.
하나의 지역에 대한 데이터는 여러 HFiles에 저장될 수 있으므로 Hbase는 작업 속도를 높이기 위해 주기적으로 병합합니다. 이 작업을 Hbase에서 압축이라고 합니다. 압축에는 두 가지 유형이 있습니다.
- 작은 다짐 . 자동으로 시작되고 백그라운드에서 실행됩니다. 다른 Hbase 작업에 비해 우선 순위가 낮습니다.
- 주요 다짐 . 수동으로 또는 특정 트리거(예: 타이머) 발생 시 시작됩니다. 우선 순위가 높으며 클러스터 속도를 크게 저하시킬 수 있습니다. Major Compaction은 클러스터의 부하가 적을 때 가장 잘 수행됩니다. Major Compaction은 또한 이전에 삭제 표시로 표시된 데이터를 물리적으로 삭제합니다.
6.5 HBase로 작업하는 방법
HBase 셸
Hbase를 시작하는 가장 쉬운 방법은 hbase 셸 유틸리티를 사용하는 것입니다. 모든 hbase 클러스터 노드에 hbase를 설치한 후 즉시 사용할 수 있습니다.![](https://cdn.codegym.cc/images/article/d13e20e1-fed9-444a-929c-15ab43d8209b/800.jpeg)
Hbase 셸은 모든 기본 Hbase 작업을 기본적으로 지원하는 jruby 콘솔입니다. 다음은 두 개의 열 패밀리가 있는 사용자 테이블을 생성하고 일부 조작을 수행한 후 hbase 셸의 마지막에 테이블을 삭제하는 예입니다.
create 'users', {NAME => 'user_profile', VERSIONS => 5}, {NAME => 'user_posts', VERSIONS => 1231231231}
put 'users', 'id1', 'user_profile:name', 'alexander'
put 'users', 'id1', 'user_profile:second_name', 'alexander'
get 'users', 'id1'
put 'users', 'id1', 'user_profile:second_name', 'kuznetsov'
get 'users', 'id1'
get 'users', 'id1', {COLUMN => 'user_profile:second_name', VERSIONS => 5}
put 'users', 'id2', 'user_profile:name', 'vasiliy'
put 'users', 'id2', 'user_profile:second_name', 'ivanov'
scan 'users', {COLUMN => 'user_profile:second_name', VERSIONS => 5}
delete 'users', 'id1', 'user_profile:second_name'
get 'users', 'id1'
disable 'users'
drop 'users'
네이티브 API
대부분의 다른 hadoop 관련 프로젝트와 마찬가지로 hbase는 Java로 구현되므로 Java에서 기본 API를 사용할 수 있습니다. 네이티브 API는 공식 웹사이트에 꽤 잘 문서화되어 있습니다. 다음은 거기에서 가져온 Hbase API를 사용하는 예입니다.
import java.io.IOException;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
public class MyLittleHBaseClient {
public static void main(String[] args) throws IOException {
Configuration config = HBaseConfiguration.create();
Connection connection = ConnectionFactory.createConnection(config);
try {
Table table = connection.getTable(TableName.valueOf("myLittleHBaseTable"));
try {
Put p = new Put(Bytes.toBytes("myLittleRow"));
p.add(Bytes.toBytes("myLittleFamily"), Bytes.toBytes("someQualifier"),
Bytes.toBytes("Some Value"));
table.put(p);
Get g = new Get(Bytes.toBytes("myLittleRow"));
Result r = table.get(g);
byte [] value = r.getValue(Bytes.toBytes("myLittleFamily"),
Bytes.toBytes("someQualifier"));
String valueStr = Bytes.toString(value);
System.out.println("GET: " + valueStr);
Scan s = new Scan();
s.addColumn(Bytes.toBytes("myLittleFamily"), Bytes.toBytes("someQualifier"));
ResultScanner scanner = table.getScanner(s);
try {
for (Result rr = scanner.next(); rr != null; rr = scanner.next()) {
System.out.println("Found row: " + rr);
}
} finally {
scanner.close();
}
} finally {
if (table != null) table.close();
}
} finally {
connection.close();
}
}
}
Thrift, REST 및 기타 프로그래밍 언어 지원
다른 프로그래밍 언어에서 작업하기 위해 Hbase는 Thrift API 및 Rest API를 제공합니다. 이를 기반으로 클라이언트는 Python, PHP, Java Script 등 모든 주요 프로그래밍 언어용으로 구축됩니다.
6.6 HBase 작업의 일부 기능
-
Hbase는 즉시 MapReduce와 통합되며 특별한 TableInputFormat 및 TableOutputFormat을 사용하여 입력 및 출력으로 사용할 수 있습니다.
-
올바른 RowKey를 선택하는 것이 매우 중요합니다. RowKey는 여러 지역에 걸쳐 균일한 분포를 제공해야 합니다. 그렇지 않으면 다른 지역보다 훨씬 더 자주 사용되는 지역인 소위 "핫 지역"의 위험이 있어 시스템 리소스를 비효율적으로 사용할 수 있습니다.
-
데이터가 개별적으로 업로드되지 않고 대량 배치로 즉시 업로드되는 경우 Hbase는 단일 Puts를 사용하는 것보다 훨씬 빠르게 데이터를 업로드할 수 있는 특별한 BulkLoad 메커니즘을 지원합니다. BulkLoad는 기본적으로 2단계 작업입니다.
- 특별한 MapReduce 작업을 사용하여 put 참여 없이 HFile 형성
- 이 파일을 Hbase에 직접 삽입
-
Hbase는 Ganglia 모니터링 서버에 메트릭 출력을 지원합니다. 이는 Hbase 문제를 해결하기 위해 Hbase를 관리할 때 매우 유용할 수 있습니다.
행 키
RowKey는 전 세계적으로 고유하도록 특별히 생성된 문자열인 GUIUID인 사용자 ID입니다. GUIUID는 균등하게 분산되므로 서버 전체에 데이터가 잘 분산됩니다.
컬럼 패밀리
우리 스토리지는 두 가지 컬럼 패밀리를 사용합니다.
- 데이터. 이 열 그룹은 사용자가 특정 URL을 방문했다는 사실과 같이 더 이상 광고 목적과 관련이 없는 데이터를 저장합니다. 이 Column Family의 TTL은 2개월로 설정되어 있으며 버전 수 제한은 2000개입니다.
- longdata.longdata. 이 열 그룹은 성별, 생년월일 및 기타 "영원한" 사용자 특성과 같이 시간이 지나도 관련성을 잃지 않는 데이터를 저장합니다.
스피커
각 유형의 사용자 사실은 별도의 열에 저장됩니다. 예를 들어 Data:_v 열은 사용자가 방문한 URL을 저장하고 LongData:gender 열은 사용자의 성별을 저장합니다.
이 팩트의 타임스탬프는 타임스탬프로 저장됩니다. 예를 들어 Data:_v 열에서 타임스탬프는 사용자가 특정 URL을 방문한 시간입니다.
이 사용자 데이터 저장 구조는 우리의 사용 패턴과 매우 잘 맞으며 사용자 데이터를 빠르게 업데이트하고 사용자에 대한 모든 필요한 정보를 빠르게 얻을 수 있으며 MapReduce를 사용하여 모든 사용자에 대한 데이터를 한 번에 빠르게 처리할 수 있습니다.
6.7 대안
HBase는 관리 및 사용이 매우 복잡하므로 HBase를 사용하기 전에 대안을 살펴보는 것이 좋습니다.
-
관계형 데이터베이스 . 특히 데이터가 하나의 시스템에 맞는 경우 매우 좋은 대안입니다. 또한 기본이 아닌 다른 인덱스의 트랜잭션이 중요한 경우 관계형 데이터베이스를 먼저 생각해야 합니다.
-
키-값 저장 . Redis 및 Aerospike와 같은 저장소는 대기 시간이 필요하고 일괄 처리가 덜 중요할 때 더 적합합니다.
-
MapReduce를 사용한 파일 및 해당 처리 . 데이터가 추가되기만 하고 업데이트/변경이 거의 없다면 HBase를 사용하지 않고 단순히 데이터를 파일에 저장하는 것이 좋습니다. 파일 작업을 단순화하기 위해 Hive, Pig 및 Impala와 같은 도구를 사용할 수 있습니다.
HBase 사용은 다음과 같은 경우에 정당화됩니다.
- 많은 데이터가 있으며 하나의 컴퓨터/서버에 맞지 않습니다.
- 데이터가 자주 업데이트 및 삭제됨
- 데이터에는 다른 모든 것을 바인딩하는 데 편리한 명시적인 "키"가 있습니다.
- 일괄 처리 필요
- 특정 키로 데이터에 임의 액세스 필요
GO TO FULL VERSION