2020년 9월 19일 토요일

Apache HBase [1] - 개요 및 아키텍처


1.Hbase의 등장

하둡은 MapReduce를 이용하여 대용량 데이터를 저장하고 처리하는데는 탁월하다. 그러나 데이터를 순차적방식으로 액세스하여, 간단한 작업을 할 때에도 해당 데이터를 찾을 때 까지 데이터 집합 전체를 검색해야 한다.

이러한 불편함을 개선하기 위해 Random Access Database를 개발하였는데 HBase, Cassandra, couchDB, Dynamo, MongoDB와 같은 데이터베이스이다.


2.HBase란

[ 컬럼지향데이터베이스 ]

HBase는 HDFS(Hadoop Distributed File System)위에 구축된 분산형 컬럼지향 데이터베이스이다. ROW기반의 RDBMS보다 데이터를 통계화 하는데 이점이 있다. 

[ 이미지참조 http://www.dbguide.net/ ]

위의 예와 같이 column1의 평균을 구하려면 RDBMS에서는 Group By로 묶은 후 평균을 구하는 "SELECT AVG(column1) FROM DB1 GROUP BY column1" 와 같이 그룹핑 단계를 거쳐야 하지만 컬럼지향데이터베이스는 그럴 필요가 없어 매우 빠른 속도로 결과값을 얻을 수 있다.

RDBMS는 Online Transaction Process(OLTP)에 적합하여 비즈니스 트랜잭션 처리에 많이 사용한다. 쇼핑몰 구매시스템이 그 예다. 반면 컬럼기반 HBase는 Online Analytical Processing(OLAP)에 적합하여 데이터 분석, 통계 모델링 구축에 많이 사용된다.

[ 랜덤 액세스 ]

기존 HDFS와 가장 큰 차이점은 순차적 데이터액세스만 제공했던 HDFS와는 다르게, HBase는 내부적 Hash테이블을 사용한 실시간 읽기/쓰기 랜덤 액세스를 제공한다. 따라서 보다 빠른 데이터처리를 할 수 있다.


3. HBase 저장 매커니즘

HBase의 테이블 스키마는 키-값 쌍으로 된 컬럼패밀리(column family)로 정의된다. 컬럼패밀리는 수 많은 컬럼을 가질 수 있으며, 각 컬럼은 타임스탬프 값을 가진다.



4. HBase의 특징

  • HBase는 행기준으로 확장이 가능하다. ( 스키마 정보만 있으면 클러스터A에는 1-100행, 클러스터B에는 100-300행을 따로 저장하여 확장기능을 가능케한다. )
  • HBase는 Failure support 기능이 있다.
  • 일관된 읽기과 쓰기를 제공한다.
  • Hadoop및 관련 애플리케이션(Phoenix, Hive 등)과 사용이 용이하다.
  • 클라이언트를 위한 쉬운 JAVA API를 제공한다.
  • 클러스터 간에 데이터 복제 기능을 제공하여 데이터의 정밀성과 정합성을 보장한다.


5. HBase 아키텍처
HBase는 컬럼패밀리에 의해 수직으로 분리된 스토어(MemStore+H file)로 나뉘며, region server에 의해 각 스토어가 HDFS에 저장된다. 지역서버(region server)는 추가되거나 제거할 수 있다.


Hbase 구성요소
  • 클라이언트 라이브러리(Client Library)
  • 마스터서버(Master Server)
  • 지역서버(Region Server)
* HDFS와 Zookeeper와 함께 연동

[ 마스터서버 ]
- Zookeeper를 통해 각 지역서버를 할당하고 작업을 지시
- 서버간 로드밸런싱
- 스키마 및 테이블, 컬럼패밀리 생성/삭제와 같은 메타데이터 작업처리

[ 지역서버 ]
- 클라이언트와 통신하여 데이터관련 작업처리(읽기/쓰기)
- 데이터 및 서버의 Data Size 임계값을 결정
- HDFS 위에서 동작한다.


WAL
(Write Ahead Log) : 새로운 데이터를 저장하기 위해 쓰이는데 중간에 데이터를 잃을 경우 데이터 복구 역할도 한다.
Block Cache : 자주 읽는 데이터를 메모리에 저장
Memstore : Disk에 새로운 데이터를 Write한다. key-value기반의 Cache메모리로 속도가 빠르며 region의 하나의 컬럼패밀리마다 memstore를 갖는다.
Hfile : key-value로 저장된 데이터파일


[ 주키퍼 ]
- 마스터서버가 사용가능한 서버와 통신(서버장애확인,사용가능서버검색)하기 위해 사용 
 

2017년 5월 17일 수요일

[SQL] 0으로 나눌 때 exception


SELECT ISNULL(col1, 0 ) FROM table1
SELECT COALESCE(col1, 0 ) FROM table1
Comparing COALESCE() and ISNULL():
1. The ISNULL function and the COALESCE expression have a similar purpose but can behave differently.

2. Because ISNULL is a function, it is evaluated only once. As described above, the input values for the COALESCE expression can be evaluated multiple times.

3. Data type determination of the resulting expression is different. ISNULL uses the data type of the first parameter, COALESCE follows the CASE expression rules and returns the data type of value with the highest precedence.

4. The NULLability of the result expression is different for ISNULL and COALESCE. The ISNULL return value is always considered NOT NULLable (assuming the return value is a non-nullable one) whereas COALESCE with non-null parameters is considered to be NULL. So the expressions ISNULL(NULL, 1) and COALESCE(NULL, 1) although equivalent have different nullability values. This makes a difference if you are using these expressions in computed columns, creating key constraints or making the return value of a scalar UDF deterministic so that it can be indexed as shown in the following example.

2017년 5월 10일 수요일

[SQL]resultSet 함수

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

String sql = "select * from board where id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();

ResultSetMetaData rsmd = rs.getMetaData();
int columnCnt = rsmd.getColumnCount(); //컬럼의 수
 
if(rs.next()){
  for(int i=1 ; i<=columnCnt ; i++){
                                    // 컬럼명                                   //데이터
System.out.println(rsmd.getColumnName(i)+","+rs.getString(rsmd.getColumnName(i)));  
  }
}
 
 

2017년 4월 26일 수요일

[Java]날짜 변환 기본

[날짜 계산을 위한 변환]
String edate = "2016-12-01";

int year = Integer.valueOf(edate.substring(0, 4));
int month = Integer.valueOf(edate.substring(5, 7));
int day = Integer.valueOf(edate.substring(8, 10));

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.set(year, month-1, day-1);
String date = sdf.format(c.getTime());


[단순 변환]
String edate = "2016-12-01";

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date ndate = sdf.parse(edate);
Calendar c = Calendar.getInstance();
c.setTime(ndate);
String date = sdf.format(c.getTime());

2017년 4월 20일 목요일

[SQL]데이터 불러올 때 한글 깨짐



EX)
SELECT CONCAT(CAST(COUNT(B.ENAME) AS CHAR),'개') AS '$amount_count'
FROM KSP200_DATA A," + "KSP200S_DATA B

Count는 int형 '개'는 Char형으로 숫자+문자열일 시 한글이 깨짐.
그래서  COUNT(B.ENAME를 char형으로 캐스트하여 불러와야 함.

2017년 4월 13일 목요일

[SQL] 커넥션풀 옵션

※ 커넥션 풀의 속성

  • maxActive  : 커넥션 풀이 제공할 최대 커넥션 갯수
  • whenExhaustedAction 커넥션 풀에서 가져올 수 있는 커넥션이 없을 때 어떻게 동작할지를 지정.
    0일 경우 에러 발생.
    1일 경우 maxWait 속성에서 지정한 시간만큼 커넥션을 구할때까지 기다림.
    2일 경우 일시적으로 커넥션을 생성해서 사용
  • maxWait whenExhaustedAction 속성의 값이 1일 때 사용되는 대기 시간.
    단위는 1/1000초, 0보다 작을 경우 무한히 대기
  • maxIdle  사용되지 않고 풀에 저장될 수 있는 최대 커넥션 갯수.
    음수일 경우 제한이 없음
  • minIdle 사용되지 않고 풀에 저장될 수 있는 최소 커넥션 갯수.
  • testOnBorrow : true일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사
  • testOnReturn : true일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션이 유효한지의 여부를 검사 
  • timeBetweenEvctionRunsMillis사용되지 않는 커넥션을 추출하는 쓰레드의 실행 주기 지정.
    양수가 아닐 경우 실행되지 않는다.
    시간 단위는 1/1000초.
  • testWhileIdle true일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거.



커넥션 풀 API 참조 : http://commons.apache.org/proper/commons-dbcp/apidocs/index.html


[ Java 예제 ]

package com.dataSource.dbcp;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;

public class DataSource {

     private static DataSource     datasource;
     private BasicDataSource ds;

     private DataSource() throws IOException, SQLException, PropertyVetoException {

         ds = new BasicDataSource();
         ds.setDriverClassName("com.mysql.jdbc.Driver");
         ds.setUsername("root");
         ds.setPassword("root");
         ds.setUrl("jdbc:mysql://localhost/test");
       
      // the settings below are optional -- dbcp can work with defaults
         ds.setMinIdle(5);
         ds.setMaxIdle(20);
         ds.setMaxOpenPreparedStatements(180);
     }

     public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {

         if (datasource == null) {
             datasource = new DataSource();
             return datasource;
         } else {
             return datasource;
         }

     }

     public Connection getConnection() throws SQLException {
         return this.ds.getConnection();
     }

 }

2017년 4월 4일 화요일

[JAVA]Thread Option

yield : 현재 실행중인 스레드 객체를 일시적으로 중단
sleep : 현재 실행중인 스레드를 지정된 밀리초 + 지정된 나노초 동안 수면 상태(일시적 실행 중단)로 변경
stop :스레드가 실행을 중단하도록 강제 실행
interrupt : 스레드를 인터럽트
interrupted : 현재 스레드를 인터럽트했는지 여부를 테스트
destroy : 종결 처리하지 않고, 스레드를 버림
isAlive : 스레드가 활동중인지 여부를 테스트 (해당 스레드가 활동중인 경우 true, 그렇지 않으면 false)
suspend : 스레드를 일시 중단
resume : 중단된 스레드를 재개
setPriority : 스레드의 우선순위를 변경
getPriority : 스레드의 우선순위를 리턴
getName : 스레드의 이름을 리턴
activeCount : 스레드 그룹에 있는 활성 스레드의 현재 수를 리턴
enumerate : 스레드 그룹 및 하위 그룹에 있는 모든 활성 스레드를 지정된 배열로 복사
countStackFrames : 스레드에 있는 스택 프레임의 수를 계산
join : 스레드가 종료되는 것을 적어도 millis 밀리초 동안 기다림립. 시간 종료 값이 0이면 무한히 기다림
toString : 스레드 이름, 우선순위 및 스레드 그룹을 포함하여, 스레드의 문자열 표시를 리턴

package test;

import java.text.SimpleDateFormat;
import java.util.Date;

class News extends Thread{
String news;
public News(String n){
this.news = n;
}
public void run(){
for(int i=0; i<3000000;i++){
System.out.println("Message "+news+" "+i);
}
}
}
class tt{
public static String time() {
Date dt = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd, hh:mm:ss:SSS a");
return sdf.format(dt).toString();
}
}
class Synchronized_Sample {

public static void main(String[] args) {
News n1 = new News("Eng");
News n2 = new News("Kor");
News n3 = new News("Mat");

try{
String st = tt.time();

n1.start();n1.join();
n2.start();n2.join();
n3.start();
n3.join();
String en = tt.time();

System.out.println("start:"+st+" // "+"end:"+en);
}catch(InterruptedException e){
e.printStackTrace();
}

}
}쓰레드 예시.


쓰레드풀 가이드라인 http://palpit.tistory.com/732