[AWS RDS] Modify RDS SQL Server Standard Edition to Enterprise Edition

-          AWS RDS SQL Server 스탠다드 에디션에서 엔터프라이즈 에디션으로 변경

 

l  Version : Amazon RDS for SQL Server

 

Microsoft SQL Server 다양한 버전으로 제공되며 버전은 고유한 기능, 성능 가격 옵션을 제공한다. 설치하는 버전도 특정 요구사항에 따라 다르다. 일부 고객은 높은 메모리와 고가용성 기능을 활용하기 위해 SQL Server Amazon RDS Standard Edition에서 Amazon RDS Enterprise Edition으로 변경을 원할 있다. 이번 글은 RDS SQL Server 스탠다드 에디션에서 RDS SQL Server 엔터프라이즈 에디션으로 업그레이드 하는 방법에 대해서 살펴 본다.

 

업그레이드를 위해서 작업자는 아래의 권한을 가지고 있어야 한다.

l  Amazon RDS for SQL Server

l  AWS Management Console 접근 권한

l  SQL Server Management Studio

 

업그레이드 프로세스는 아래와 같은 단계가 포함된다.

l  기존 RDS SQL Server Standard Edition 인스턴스의 스냅샷 생성

l  스냅샷을 RDS SQL Server Enterprise Edition으로 복원

l  RDS SQL Server Enterprise 인스턴스 확인

 

먼저 콘솔을 통해 SQL Server RDS 버전을 수정하는 방법을 안내한다. 기존 RDS for SQL Server 인스턴스의 스냅샷을 만든 다음 다른 버전의 SQL Server 복원한다. SQL Server Management Studio에서 RDS 버전을 확인할 있다.

1.        Amazon RDS 콘솔에서 데이터베이스를 선택

2.        데이터베이스를 선택하고 작업 메뉴에서 스냅샷 생성을 선택

3.        스냅샷 이름을 입력, 스냅샷을 생성

4.        스냅샷 페이지에서 스냅샷이 성공적으로 생성되었는지 확인하고 상태가 사용 가능한지 확인

5.        스냅샷을 선택하고 작업 메뉴에서 스냅샷 복원을 선택

6.        DB 사양에서 SQL Server 버전(SQL Server Enterprise Edition) 선택

7.        DB 인스턴스 식별자에 인스턴스 이름을 입력

8.        인스턴스 클래스를 선택

9.        DB 인스턴스 복원 선택

10.    데이터베이스 복원 진행

11.    데이터베이스가 복원된 SQL Server 버전 확인

 

AWS CLI 통해서도 SQL Server RDS 인스턴스를 업그레이드 있다.  아래 스크립트를 실행하여 DB 스냅샷을 생성한다.

aws rds create-db-snapshot ^
db-instance-identifier mydbinstance ^
db-snapshot-identifier mydbsnapshot

 

아래 스크립트를 실행하여 스냅샷에서 데이터베이스를 복원한다.

aws rds restore-db-instance-from-db-snapshot ^
db-instance-identifier mynewdbinstance ^
db-snapshot-identifier mydbsnapshot^
engine sqlserver-ee

 

업그레이드가 완료되면 향후 비용이 발생하지 않도록 기존 RDS Standard Edition 삭제 하도록 한다.

 

[참고자료]

l  https://dataintegration.info/modify-an-amazon-rds-for-sql-server-instance-from-standard-edition-to-enterprise-edition

 

 

2022-03-21 / Sungwook Kang / http://sungwookkang.com

 

 

AWS RDS, SQL Server, AWS SQL Server, Modify SQL Server Edition, 에디션 변경

'AWS' 카테고리의 다른 글

[AWS RDS] RDS Proxy  (0) 2022.03.23
[AWS RDS] Modify RDS instance type  (0) 2022.03.23
[AWS Aurora] Aurora I/O Planning  (0) 2022.03.20
[AWS Aurora] Aurora Storage Engine  (0) 2022.03.19
[AWS RDS MySQL] RDS MySQL와 Aurora MySQL 차이점  (0) 2022.03.18

[AWS Aurora] Aurora I/O Planning

 

l  Version : Aurora

 

Amazon Aurora 상용 데이터베이스의 성능 가용성과 오픈 소스 데이터 베이스의 단순성 비용 효율성을 결합한다. Aurora 클러스터는 공유 분산 Aurora 스토리지 볼륨에 연결된 하나 이상의 인스턴스로 구성된다. 새로운 스토리지 엔진은 관계형 데이터베이스에서 일반적으로 사용되는 기존 블록 스토리지 장치를 자동 크기 조정, 자동 복구, 로그 기반 동적 스토리지 볼륨으로 대체한다. 새로운 스토리지 엔진은 클라우드용으로 설계되었으므로 데이터베이스가 전통적으로 스토리지 시스템과 상호작용하는 방식에서 가지 근본적인 변경이 이루어 졌다. 글은 기존 데이터베이스와 비교하여 Aurora에서 I/O 작동하는 방식, Aurora I/O 비용을 모니터링하는 방법 Aurora I/O 최적화하는 방법을 설명한다.

 

[데이터베이스 I/O 개요]

높은 수준에서 관계형 데이터베이스는 전통적으로 블록 스토리지와 상호작용한다. 블록 스토리지에서 데이터는 페이지라는 블록에 저장된다. 페이지 크기는 데이터베이스 엔진마다 다르며 동일한 데이터베이스 엔진 내에서도 엔진의 구성 매개변수에 따라 다르다. Aurora Amazon Aurora MySQL 대해 16KB 페이지 크기와 Amazon Aurora PostgreSQL 대해 8KB 페이지 크기를 지원한다. 페이지 크기는 데이터베이스 엔진이 수행하는 가장 작은 I/O 작업이다.

 

[읽기 작업]

MySQL 또는 PostgreSQL 같은 관계형 데이터베이스가 디스크에서 페이지를 읽을 해당 페이지는 버퍼풀이라는 세그먼트의 메모리에 저장된다. 해당 페이지는 버퍼풀로 읽혀지는 다른 페이지의 메모리 압력으로 인해 제거되거나 엔진이 다시 시작될 때까지 무기한 남아 있을 있다. 응용 프로그램이 SELECT 쿼리를 실행할 엔진은 버퍼풀에 이미 있는 페이지를 사용하여 쿼리를 수행하려고 시도한다. 쿼리를 완료하는데 필요한 페이지 버퍼 풀에 존재하지 않는 페이지는 쿼리가 완료되기 전에 먼저 디스크에서 버퍼풀로 읽어와야 한다.

 

Aurora 사용하면 읽기가 기본 MySQL 또는 PostgreSQL 동일한 방식으로 처리된다. , 버퍼풀을 채우는데 필요한 만큼 스토리지 볼륨에서 페이지별로 데이터를 읽고 버퍼풀 내부의 해당 페이지에 대해 SELECT 쿼리를 실행한다. 이와 같이 읽기I/O 작업은 스토리지 볼륨에서 페이지 또는 익스텐트를 읽을 누적된다. 쿼리를 실행하는데 필요한 모든 페이지가 이미 버퍼풀에 존재하는 쿼리인 경우 스토리지 볼륨에서 읽을 이유가 없기 때문에 해당 쿼리에 대한 I/O 0이다. 스토리지 볼륨에서 페이지를 검색 해야하는 쿼리의 경우 읽은 각페이지는 하나의 읽기 I/O 계산된다.

 

여러 요인에 따라 페이지가 얼마나 가득 있는지 따라서 동일한 수를 유지하는데 필요한 페이지수를 결정할 있다. 이러한 요인 중하나는 인덱스의 지정된 채우기 비율이다, 채우기 비율 100 인덱스가 생성될 페이지가 100% 용량에 최대한 가깝게 채워 져야함을 나타낸다. 결과 동일한 수의 행을 저장하는데 사용되는 페이지수가 줄어들어 읽기 I/O 효율성이 최대화 된다. 예를 들어 테이블의 크기가 100바이트이고 채우기 비율이 100 기본 키가 생성된 경우 대략 160개의행이 16KB 페이지에 기록된다. 그러나 채우기 비율이 50이고 페이지가 50% 용량으로 채워지면 결과는 각각 80행이 있는 페이지가 된다. , 채우기 비율이 50 동일한 집합을 읽으면 읽기 I/O 작업이 많이 발생한다. 채우기 비율은 기본 또는 인덱스를 생성하거나 다시 작성할 적용된다.

 

후속 DML 작업이 페이지를 채우는 정도는 다른 여러 요인에 따라 다르다. 예를 들어, 테이블의 기본 키를 순차적인 자동 증가 정수로 지정하면 행이 페이지에 깔끔하게 쌓이기 때문에 페이지가 용량까지 채워지고 페이지 수가 최소화된다. 반대로 GUID 또는 여러 열로 구성된 자연 키와 같이 기본 키가 무작위인 경우 행이 끝에 추가되지 않고 인덱스 중간에 삽입 있기 때문에 페이지가 분할되는 경향이 있다. 이런 식으로 인덱스가 단편화(조각화)되고 같은 수의 행을 저장하는 필요한 페이지 수가 크게 늘어난다. 조각난 페이지는 버퍼풀에서 많은 공간을 낭비하고 읽기 I/O 증기 시킨다.

 

[쓰기 작업]

관계형 데이터베이스가 INSERT, UPDATE, DELETE 같은 쓰기 작업을 수행 가지 일이 발생한다. 먼저 수정할 페이지를 버퍼풀에 넣고 해당 페이지에 대한 변경 기록을 트랜잭션 로그에 기록한다. 로그의 이름은 플랫폼마다 다르지만 MySQL에서는 redo로그, PostgreSQL에서는 WAL 로그라고 한다. 플랫폼에 따라 디스크에 기록되는 MySQL 바이너리 로그(binlog) 같은 다른 로그도 있지만 글에서는 redo 로그에 초점을 맞춘다.

 

redo 로그가 기록된 페이지는 버퍼풀에서 수정되고 체크포인트로 알려진 프로세스가 다른 모든 더티 페이지와 함께 해당 페이지를 디스크에 때까지 버퍼풀에 더티 페이지로 남아 있다. 체크포인트 프로세스는 쓰기 집약적이며 상당한 디스크  I/O 유발할 있다.

 

Aurora 사용하면 페이지를 버퍼풀에 배치하고, redo 로그에 쓰고, 버퍼풀에서 페이지를 수정하는 동일한 작업이 유지되며, redo 로그 레코드는 페이지에 대한 변경 사항을 나타낸다. 가장 차이점은 Aurora 체크포인트를 발행하지 않는다는 것이다. 대신 Aurora스토리지 볼륨에 기록되는 데이터는 전체 페이지에 비해 크기가 매우 작은 redo로그 뿐이다. , 일반적으로 더티 8KB 또는 16KB 페이지를 디스크에 기록하여 생성되는 모든 디스크 I/O 제거된다. 대신 페이지는 스토리지 노드에서 주기적으로 구체화되며 경우에 따라 요청시에도 구체화된다. 이러한 I/O 작업에는 요금이 부과되지 않는다. 이러한 변경의 순효과는 모든 쓰기가 3개의 가용 영역에 분산된 6개의 스토리지 노드로 전송된다는 사실에도 불구하고 쓰기 I/O 작업이 전반적으로 감소한다는 것이다. (1개의 쓰기로 계산됨)

 

실제 로그 레코드의 크기는 다양하지만 Aurora 클러스터에 대한 쓰기는 가능한 경우 4KB 단위로 전송된다. 기록기에 크기가 4KB 미만인 여러 로그 레코드가 동시에 있으면 단일 쓰기 작업으로 일괄 처리 된다. 예를 들어 50바이트 로그 레코드와 3000바이트 로그 레코드를 단일 쓰기 작업으로 결합할 있다. 4KB보다 로그 레코드는 4KB 단위로 분할된다.

 

Aurora 클러스터에 읽기 전용 인스턴스가 포함된 경우 스토리지 볼륨으로 전송된 동일한 쓰기가 해당 읽기 전용 인스턴스에도 전송된다. 이렇게 하면 판독기의 버퍼풀이 최신 상태로 유지된다. 리더가 로그 레코드를 수신하고 이미 읽기 전용 인스턴스의 버퍼 풀에 있는 페이지에 해당하면 로그 레코드에 설명된 변경 사항이 리더의 버퍼풀에 있는 페이지에 적용된 다음 로그 레코드 자체가 삭제 된다. 버퍼풀에 페이지가 없으면 로그 레코드는 단순히 폐기된다. 경우 모두 스토리지 볼륨에 대한 I/O활동이 발생하지 않는다.

 

[I/O 작업]

이제 Aurora에서 I/O 기본 사항을 다루었으므로 Aurora MySQL 사용하는 보다 구체적인 예를 살펴본다. 아래 스크립트를 실행할 column_name1 테이블의 기본키이며 현재 버퍼풀은 아무것도 채워져 있지 않은 상태를 가정한다.

UPDATE <tablename> SET <column_name2> = ‘XXX’ WHERE <column_name1> = YYY;

 

작업 순서는 아래와 같다.

1.        클러스터형 인덱스를 탐색하여 수정할 행이 포함된 페이지에 도달 (암시적 읽기 I/O)

2.        트랜잭션 시작 업데이트를 위한 undo 로그 공간 할당 (데이터베이스 엔진 I/O)

3.        수정 중인 행이 포함된 페이지 업데이트 (사용자 SQL 쿼리 I/O)

4.        트랜잭션 시스템에 undo 로그 기록 (데이터베이스 엔진 I/O)

5.        트랜잭션 커밋 (데이터베이스 엔진 I/O)

 

예에서는 암시적 I/O 작업이 여러 있지만 쓰기 작업의 일부 또는 전체를 단일 쓰기 I/O 일괄 처리할 있다. 또한 쓰기 작업임에도 불구하고 읽기 I/O 여전히 필요했다. 마지막으로 주의할 점은 데이터베이스 엔진의 일반적인 트랜잭션 프로세스의 일부인 I/O 작업이 있다는 것이다. 쿼리를 전혀 포함하지 않는 다른 I/O 작업들도 있다. 예를 들어 인덱스 생성이다. 시나리오 에서는 인덱스를 만드는데 필요한 데이터를 읽기 위한 암시적 읽기 I/O 스토리지 볼륨에 인덱스를 쓰기 위한 명시적 I/O 쓰기가 있다.

 

[I/O 모니터링]

Aurora 클러스터로 최적의 I/O 비용을 보장하려면 모니터링부터 시작하는 것이 가장 좋다. Amazon CloudWatch 지표에서 [Billed] Volume Read IPOS (Count) 사용하면 모든 Aurora 인스턴스에 소비하는 초당 읽기 I/O수를 모니터링 있다. [Billed] Volume Write IPOS (Count) 지표는 모든 Aurora 인스턴스에서 소비한 쓰기 IPOS수를 모니터링 있다. 모니터링이 설정되고 평균 읽기 쓰기 I/O 요청 수에 대한 기준이 결정되면 CloudWatch 경고 알림을 설정하여 I/O 사용량이 급증하는 경우 알림을 받을 있다.

 

[MySQL 관련 고려 사항]

Aurora 클러스터의 쓰기 노드와 읽기 노드 간의 복제에는 추가 I/O 필요하지 않다. 그러나 일부 사용 사례에서는 binlog 활성화 하여 Aurora외부의 대상으로 복제 해야 수도 있다. Aurora MySQL에서 binlog 활성화하면 트랜잭션에 대해 쓰기 I/O 요청이 하나 이상 증가하고 내부 binlog 구조를 유지하기 위해 추가 쓰기 I/O 필요할 있다. 사용자가 binlog 읽을 추가 읽기  I/O 발생한다.

 

느린 쿼리 로그를 활성화 하여 장기 실행 쿼리를 캡처하는 것은 최적화 해야 하는 쿼리를 찾는데 유용한 방법일 있다. 또는 성능 스키마 개체를 사용하여 많은 행을 처리하거나 성능 조정이 필요한 SQL 쿼리 목록을 가져올 있다.

 

[PostgreSQL 관련 고려 사항]

PostgreSQL에서 테이블의 행은 튜플로 유지된다. 행이 삭제될 해당 행을 나타내는 튜플은 물리적으로 제거되지 않는다. 단순히 삭제된것으로 표시된다. 또한 업데이트 작업으로 인해 이전 튜플을 삭제된 것으로 표시하고 동일한 행을 나타내기 위해 튜플을 삽입한다. 시간이 지남에 따라 삭제된 튜플의 수가 증가하여 데이터베이스 엔진이 이러한 삭제된 튜플을 통과할 불필요한 I/O 그에 따른 성능 저하가 발생할 있다. Vacuum(진공 청소기) 프로세스는 데드 튜플을 제거한다. PostgreSQL vacuum 프로세스에서 생성되는 여러 유형의 데이터베이스 엔진 읽기 쓰기 I/O 작업이 있다.

 

pgBadger 사용하여 로그를 분석하여 느리게 실행되는 쿼리를 표시할 있으며 pg_stat_statements 비싼 SQL문을 캡처하기 위한 강력한 저수준 도구가 있다. 또한 Aurora PostgreSQL 쿼리 계획 관리를 지원한다. 기능은 계획 안정성과 계획 적응성을 모두 제공한다.

 

주기적으로 테이블 인덱스 확장을 검토하고 적절하게 vacuum 프로세스를 실행하는 것이 가장 좋다. 선호되는 접근 방식은 auto vacuum 활성화하는 것이다. 이는 vacuum 프로세스를 자동화 하고 나은 성능과 낮은 I/O 소비를 제공하는데 도움이 된다.

 

기본적으로 모든 업데이트는 색인된 속성이 수정되지 않은 경우에도 새로 생성된 페이지에 연결하기 위해 새로운 색인 항목을 추가 해야한다. HOT(Heap Only Tuple) 경우 업데이트 튜플 체인을 유지하면서 가능한 경우 이전 튜플과 동일한 페이지에 튜플이 생성된다. 페이지가 생성되지 않았기 때문에 인덱스는 계속해서 동일한 페이지를 가리킬 있으며 수정할 필요가 없다.

 

다음 쿼리는 HOT 업데이트 수를 반환한다. 테이블에 대한 HOT 업데이트 수가 많으면 채우기 비율을 수정하여 향후 일반 또는 HOT 업데이트에 사용하지 않는 데이터 페이지의 추가 디스크 공간을 남길 있다.

select schemaname, relname, n_tup_upd, n_tup_hot_upd from pg_stat_all_tables order by n_tup_upd;

 

 

[Aurora 전용 기능]

Cloning - 복제 기능을 사용하면 Aurora 클러스터의 복사본을 빠르게 생성할 있다. 생성 데이터가 복사되지 않기 때문에 프로세스가 빠르고 I/O 집약적이지 않다. 대신 Aurora 클론은 클론이 생성될 당시 존재했던 페이지가 변경될 페이지를 생성하는 쓰기시점의 복사 메커니즘을 사용한다. 이러한 I/O 작업은 다른 Aurora 클러스터의 I/O 작업과 정확히 동일한 방식으로 작동하고 비용이 청구된다. 변경을 일으킨 클러스터는 I/O 작업이 청구되는 클러스터이다.

Global databases -  Amazon Aurora 글로벌 데이터베이스는 리전간 지연 시간이 짧은 글로벌 읽기 재해복구를 제공한다. Aurora 글로벌 데이터베이스를 사용하면 기본 클러스터에 단일 지역 클러스터와 동일한 방식으로 I/O 비용이 발생한다. 그러나 전역 복제본을 유지 관리하려면 모든 쓰기 I/O 보조 지역으로 전성되고 보조 클러스터에 기록되어야 한다. 하나의 기본 클러스터와 하나의 복제본 클러스터가 있는 시나리오에서 쓰기 I/O 기본 클러스터의 쓰기 I/O 3배이다. (기본 + 전송 + 보조). 읽기 I/O 경우 기본 보조 클러스터의 독립적인 읽기를 기반으로 요금이 청구 된다.

Parallel queries (Aurora MySQL) – Aurora MySQL 병렬 쿼리는 필터링 집계 작업의 대부분을 스토리지 엔진으로 푸시하여 특정 분석 쿼리에 대한 성능 향상을 제공한다. 그러나 병렬 쿼리로 처리된 페이지는 버퍼풀에 저장되지 않는다. 따라서 읽기 I/O 요청이 증가할 있다.

Cluster cache management (Aurora PostgreSQL) – Aurora PostgreSQL 클러스터 캐시 관리 기능은 클러스터에서 기본 장애 조치 노드로 지정된 리더 노드가 작성자와 유사한 버퍼풀을 유지하도록 한다. 이를 통해 장애조치(failover) 기록기의 성능이 향상된다. 리더(Reader) 버퍼풀에서 유사한 페이지 세트를 유지하려면 스토리지 볼륨에서 주기적으로 읽어야 한다. 활동으로 인해 해당 인스턴스에 대한 읽기 I/O활동이 증가한다.

 

[일반적인 모범 사례]

다음은 Aurora에서 I/O 계획할 모범 사례이다.

인덱스 검토

l  모든 인덱스가 쓰기 I/O 볼륨에 추가되므로 사용하지 않는 인덱스를 제거

l  테이블 스캔 또는 기타 높은 I/O 활동을 처리하기 위해 인덱스를 작성

l  기본키의 경우 값에 자동 증가 정수를 사용

l  테이블과 인덱스를 생성할 적절한 채우기 비율을 고려

l  가능하면 커버링 인덱스를 사용

l  특정 쿼리에 대해 분석된 페이지를 최소화 하려면 가능한 경우 파티션을 사용

 

실적이 저조한 쿼리 식별

l  Amazon RDS 성능 개선 도우미와 같은 도구를 사용하여 성능이 낮은 쿼리를 식별

l  I/O 대기가 높은 쿼리의 실행 계획을 검사

l  높은 I/O 대기 쿼리를 다시 작성하거나 이러한 쿼리를 지원하는 적절한 인덱스를 다시 생성

 

하드웨어 고려

l  99.98% 이상의 목표로 버퍼캐시 적중률을 모니터링한다. 측정 단위는 디스크에서 페이지를 읽는 것이 아니라 버퍼풀에서 페이지를 찾는 빈도를 반영한다.

l  버퍼 캐시 적중률이 낮으면 메모리가 많은 인스턴스 유형을 사용하는 것이 좋다.

l  많은 메모리를 제공하는 인스턴스 크기로 확장하면 보고 워크로드에 대한 전체 읽기 I/O 줄어들어 전체 I/O 비용이 감소할 있다.

 

내장된 Aurora 기능 사용

l  높은  I/O 초래할 있는 논리적 내보내기를 사용하는 대신 Aurora 특정시점 복구 기능을 활용한다.

l  전체 데이터베이스를 스캔해야 하는 논리적 내보내기 도구를 사용하는 것과 비교하여 클론을 생성하려면 I/O 필요하지 않다.

 

[목적에 맞게 구축된 데이터베이스]

올바른 작업에 올바른 도구를 사용하는 것이 중요하다. Aurora 처리량이 많은 대규모 병렬 OLTP 시스템으로 설계 되었다. Aurora 초당 수십만개의 쿼리로 수천개의 연결을 처리하는데 탁월하다. 이러한 쿼리는 일반적으로 단일 또는 작은행 집합에서 작동한다. Aurora에는 분석 쿼리와 관련하여 향상된 기능을 제공하는 Aurora MySQL 병렬 쿼리와 같은 특정 기능이 있지만 대규모 테이블 스캔 대규모 집계를 중심으로 설계된 워크로드는 상당한 수의 읽기 IOPS 생성한다. 시나리오에서는 Amazon Redshift, Amazon Athena, S3 Select 또는 Amazon EMR 같은 다른 도구가 이러한 워크로드에 적합할 있다. 마찬가지로 쓰기가 많고 읽기가 거의 없는 로그 중심의 워크로드의 경우 Amazon Kinesis Data Firehose 같은 도구를 Amazon Simple Storage Service(Amazon S3) 함께 사용하는 것이 가장 적합할 있다.

 

 

[참고자료]

l  https://dataintegration.info/planning-i-o-in-amazon-aurora

 

 

 

2022-03-20 / Sungwook Kang / http://sungwookkang.com

 

 

AWS RDS, MySQL, Aurora, RDS Aurora, Aurora MySQL, Aurora Storage, Aurora PostgreSQL, Aurora I/O Plan, 오로라 읽기 쓰기 계획, 오로라 스토리지 계획, 오로라 활용

[AWS Aurora] Aurora Storage Engine

 

l  Version : Aurora

 

Amazon Aurora 스토리지 엔진은 지역의 여러 AWS 가용 영역(AZ) 걸쳐 있는 분산 SAN 이다. AZ 물리적 데이터센터로 구성된 논리적 데이터센터 이다. AZ 해당 지역의 다른 AZ 빠른 통신을 허용하는 짧은 지연 시간 링크를 제외하고 다른 AZ 격리되어 있다. Amazon Aurora 중심에 있는 분산형 저지연 스토리지 엔진은 AZ 의존한다.

 

Amazon Aurora 현재 보호 그룹이라고 하는 10GB 논리 블록에 스토리지 볼륨을 구축한다. 보호 그룹의 데이터는 6개의 스토리지 노드에 복제된다. 그런 다음 이러한 스토리지 노드는 Amazon Aurora 클러스터가 있는 리전의 3 AZ 할당된다.

클러스터가 생성될 때에는 매우 적은 양의 스토리지를 사용한다. 데이터 볼륨이 증가하고 현재 할당된 스토리지를 초과하면 Aurora 수요를 충족하도록 볼륨을 원활하게 확장하고 필요에 따라 보호 그룹을 추가한다. Amazon Aurora 현재 64TB 도달할 때까지 이러한 방식으로 계속 확장된다.

 

Amazon Aurora에서 데이터를 쓰기가 발생하면 6개의 스토리지 노드에 병렬로 전송된다. 이러한 스토리지 노드는 3개의 가용 영역에 분산되어 있어 내구성과 가용성이 크게 향상된다. 스토리지 노드에서는 레코드는 먼저 메모리 대기열에 들어간다. 대기열의 로그 레코드는 중복 제거된다. 예를 들어, 마스터 노드가 스토리지 노드에 성공적으로 쓰기 작업을 했으나 마스터와 스토리지 노드 간의 연결이 끊긴 경우 마스터 노드는 로그 기록을 재전송하지만 중복된 로그 기록은 폐기한다. 유지해야하는 기록은 로그의 디스크에 저장된다.

 

레코드가 지속되면 로그 레코드는 업데이트 대기열이라는 메모리 구조에 기록된다. 업데이트 대기열에서 로그 레코드는 먼저 병합된 다음 데이터 페이지를 만드는데 사용된다. 하나 이상의 LSN(Log Sequence Number) 누락된 것으로 확인되면 스토리지 노드는 프로토콜을 사용하여 볼륨의 다른 노드에서 누락된 LSN 검색한다. 데이터페이지가 업데이트되면 로그 레코드가 백업되고 가비지 수집용으로 표시된다. 그런 다음 페이지는 Amazon S3 비동기식으로 백업 된다. 쓰기가 로그에 기록되어 지속 가능하게 되면 스토리지 노드는 데이터 수신을 확인한다. 6개의 스토리지 노드 4 이상이 수신을 확인하면 쓰기가 성공한 것으로 간주되고 클라이언트 애플리케이션에게 성공을 반환한다.

 

Amazon Aurora 다른 엔진보다 훨씬 빠르게 있는 이유 하나는 로그 레코드를 스토리지 노드에만 보내고 이러한 쓰기가 병렬로 수행되기 때문이다 실제로 Amazon Aurora 데이터가 6개의 다른 노드에 기록되고 있음에도 불구하고 평균적으로 MySQL 비교하여 유사한 워크로드에 대해 1/8 IOPS 필요한다. 프로세스의 모든 단계는 비동기 방식이다. 쓰기는 그룹 커밋을 사용하여 병렬로 수행되어 대기 시간을 줄이고 처리량을 향상 시킨다. 쓰기 지연 시간이 짧고 I/O 풋프린트가 감소한 Aurora 쓰기 집약적인 애플리케이션에 이상적이다.

 

아래 다이어그램은 3개의 AZ 저장된 데이터를 보여준다 복제된 데이터는 99.999999999% 내구성을 제공하도록 설계된 S3 지속적으로 백업 된다.

 

설계를 통해 Amazon Aurora 클라이언트 애플리케이션에 대한 가용성 영향 없이 전체 AZ 또는 2개의 스토리지 노드 손실을 견딜 있다.

 

 

복구 중에 Aurora 데이터 손실 없이 보호 그룹에 있는 AZ 다른 스토리지 노드의 손실을 유지하도록 설계 되었다. 이는 보호 그룹에 있는 4개의 스토리지 노드에 지속된 경우에만 Aurora에서 쓰기가 지속되기 때문이다. 쓰기를 수신한 3개의 스토리지 노드가 다운 되더라도 Aurora 여전히 4번째 스토리지 노드에서 쓰기를 복구 있다. 복구 읽기 쿼럼을 달성하기 위해 Aurora 3개의 스토리지 노드가 동일한 LSN 따라 잡는지 확인한다. 그러나 쓰기를 위해서 볼륨을 열기 위해 Aurora 향후 쓰기를 위한 쓰기 쿼럼을 달성할 있도록 4개의 스토리지 노드가 복구될 때까지 기다려야 한다.

 

읽기의 경우 Aurora 읽기를 수행할 갖아 가까운 스토리지 노드를 찾으려고 한다. 읽기 요청은 타임스탬프, LSN 연결된다. 스토리지 노드는 LSN 도달한 경우 (해당 LSN까지의 모든 업데이트를 수신한 경우) 읽기를 수행할 있다. 하나이상의 스토리지 노드가 다운되거나 다른 스토리지 노드와 통신할 없는 경우 해당 노드는 가십 프로토콜을 사용하여 온라인 상태가 자신을 재동기화 한다. 스토리지 노드가 손실되고 자리를 대신할 노드가 자동으로 생성되는 경우에도 가십 프로토콜을 통해 동기화 된다.

 

Amazon Aurora 사용하면 컴퓨팅과 스토리지가 분리된다. 이를 통해 Aurora 복제본은 복제본 자체의 데이터를 유지하지 않고도 스토리지 계층에 대한 컴퓨팅 인터페이스 역할을 있다. 이렇게 하면 데이터를 동기화할 필요 없이 인스턴스가 온라인 상태가 되는 즉시 Aurora 복제본이 트래픽 제공을 시작할 있다. 마찬가지로 Aurora 복제본의 손실은 기본 데이터에 영향을 미치지 않는다 Aurora 복제본이 마스터 노드가 되면 데이터 손실이 없다. 최대 15개의 Aurora 복제본을 지원하고 로드 밸런싱하기 때문에 Aurora 고가용성, 읽기 집약적 워크로드에 적합하다.

 

Aurora 성능에 영향없이 특정 시점에 대한 클러스터의 데이터 스냅샷을 생성할 있다. 또한 백업에서 복원할 10GB보호 그룹은 병렬로 복원한다. 또한 보호 그룹이 복원된 에는 로그를 다시 적용할 필요가 없다. , 보호 그룹이 복원되는 즉시 Amazon Aurora 최고 성능으로 작동할 있다.

Aurora AES-256 암호화를 사용하여 모든 저장 데이터를 암호화 있다. 사용자는 AWS Key Management Service (AWS KMS) 사용하여 키를 관리 수도 있다. 또한 TLS 연결을 통해 전송 중인 데이터를 보호할 있다.  

 

[참고자료]

l  https://aws.amazon.com/ko/blogs/database/introducing-the-aurora-storage-engine/

l  https://www.percona.com/blog/2016/05/26/aws-aurora-benchmarking-part-2/

l  https://blog.acolyer.org/2019/03/25/amazon-aurora-design-considerations-for-high-throughput-cloud-native-relational-databases/

l  https://www.slideshare.net/AmazonWebServices/amazon-aurora-storage-demystified-how-it-all-works-dat363-aws-reinvent-2018

 

 

 

2022-03-19 / Sungwook Kang / http://sungwookkang.com

 

 

AWS RDS, MySQL, AWS Aurora, RDS Aurora, MySQL Aurora, Aurora Storage, Storage Node

[AWS RDS MySQL] RDS MySQL Aurora MySQL 차이점

 

l  Version : 

 

AWS에서 관리형 관계형 데이터베이스를 보면 RDS MySQL Aurora MySQL 있다. 서비스의 차이점은 무엇일까? 결론부터 말하면 기존의 MySQL 소스를 기반으로 AWS 에서 커스터마이징 하여 만든 것이 Aurora이며   서비스는 스토리지 메커니즘이 다르다.

 

AWS RDS MySQL

RDS 플랫폼은 기존 데이터베이스 아키텍처를 중심으로 완전히 관리되는 추상화 계층을 제공한다. RDS 내에서 데이터베이스 플랫폼은 EC2에서 수동으로 수행하는 것처럼 구축된다. EC2인스턴스는 적절한 Amazon Machine Image (AMI)에서 프로비저닝 되고, EBS(Elastic Block Store)스토리지는 프로비저닝된 인스턴스에 연결된다. 그리고 적절한 서브넷 그룹과 보안그룹이 인스턴스에 연결되는 구조이다. RDS 몇번의 버튼 클릭만으로 데이터베이스 플랫폼을 안전하고 성능있는 방식으로 프로비저닝 있다. 프로비저닝되면 RDS 백업/복원 패치가 모두 자동으로 처리되어 플랫폼 유지관리가 자동으로 이루어진다. 아래는 RDS MySQL 특징 가지를 정리한 것이다.

l  트랜잭션 로그 데이터베이스 데이터 파일은 로컬 EBS 스토리지 볼륨 사용

l  데이터베이스의 모든 커밋된 트랜잭션 I/O WAL(Write-Ahead Log)이라고 하는 전후 이미지가 있는 로그 레코드를 생성한 지속가능한 스토리지로 저장

l  체크포인트 작업은 수정된 페이지를 디스크로 플러시하여 수행

l  EC2 인스턴스에 생성되기 때문에 I/O 대역폭 IOPS 인해 성능이 제한됨

l  튜닝에는 I/O 대역폭을 늘리거나 I/O 수를 줄여야

 

 

AWS Aurora MySQL

Aurora 플랫폼은 AWS만의 관계형 데이터베이스로써 기존의 소스를 커스터마이징하여 AWS 최적화 시킨 것이 특징이다. 기존 RDS 모든 관리 기능 뿐만 아니라 데이터베이스에 최적화된 스토리지 하위 시스템을 제공하여 RDS 플랫폼을 확장한다. RDS에서 사용하는 EBS 스토리지 대신 NVMe SSD 드라이브 위에 구축되어 훨씬 빠른 성능 이점을 제공한다. 아래는 Aurora 특징 가지를 정리한 것이다.

l  애플리케이션에 따라 자동으로 확장

l  6개의 데이터 복사본을 만들어 여러 위치에 배포하고 Amazon S3 지속적으로 백업

l  99.99% 이상의 가용성 제공

l  스토리지 장애로부터 투명하게 복구

l  일반 적으로 30 미만의 인스턴스 장애조치 허용

l  이전 시점으로 빠르게 복구할 있는 기능 제공

 

Aurora 빠른 로컬 성능 재해 복구를 위해 여러 지역에 데이터를 복제하고 컴퓨팅 스토리지 작업을 분리하여 I/O병목현상을 줄인다. 로컬 스토리지에 대한 체크포인트 작업으로 데이터베이스 인스턴스에 부담을 주신 대신 Aurora 지속적인 체크포인트를 위해 분산 스토리지 플릿을 사용한다. 분산 스토리지 플릿은 Aurora 처리량 측면에서 표준 MySQL 능가하는데 도움이 되며 가용성과 내구성도 향상된다.

 

아래 그림을 보면 MySQL 경우 로컬 EBS 데이터를 저장하고 저장된 EBS 미러링한 다음 Replication 통해 Replica instance 보내 복제 DB 로컬 EBS 다시 저장한다. Aurora 경우 4/6 쿼럼을 사용하여 스토리지에 저장하고 스토리지 레벨에서 복제가 발생한다.

 

 

 

 

Aurora 다른 특징은 교차 리전 복제(Cross Region Replication, CRR)이다. 리전당 3개의 가용 영역, 6개의 복제본이 제공된다. Write 작업은 Primary 인스턴스에서 수행되고 로그 레코드가 Replica 인스턴스로 전달된다.

 

 

 

[참고자료]

l  https://d1.awsstatic.com/events/reinvent/2019/REPEAT_Amazon_Aurora_storage_demystified_How_it_all_works_DAT309-R.pdf

l  https://aws.amazon.com/ko/blogs/database/amazon-aurora-as-an-alternative-to-oracle-rac/

 

2022-03-18 / Sungwook Kang / http://sungwookkang.com

 

AWS RDS, MySQL, AWS Aurora, RDS Aurora, MySQL Aurora

[AWS RDS MySQL] InnoDB cache warming

-          버퍼풀 정보를 저장하고 시작시 로드하여 워밍업 단계 생략하기

 

l  Version : AWS RDS MySQL 5.6 later

 

InnoDB cache warming(캐시워밍) DB 인스턴스가 종료될 버퍼 풀의 현재 상태를 저장한 다음 DB 인스턴스가 시작될 저장된 버퍼 정보를 다시 로드하여 MySQL DB 인스턴스에 대한 성능 향상을 제공할 있다. 뜻은 정상적인 데이터베이스 사용에서 버퍼풀의 워밍업 필요를 무시하고 대신 알려진 공통 쿼리에 대한 페이지로 버퍼풀을 미리 로드한다. 버퍼풀 정보를 저장하는 파일은 페이지 자체가 아니라 버퍼풀에 있는 페이지에 대한 메타데이터만 저장한다. 따라서 결과적으로 파일에 많은 저장공간이 필요하지 않다. 파일크기는 캐시 크기의 0.2% 정도이다. 예를들어 64GB캐시의 경우 캐시 워밍업 파일은 128MB이다. 캐시워밍에 대한 자세한 내용은 MySQL 공식 문서인 아래 링크에서 확인할 있다.

l  Saving and Restoring the Buffer Pool State : https://dev.mysql.com/doc/refman/8.0/en/innodb-preload-buffer-pool.html

 

AWS RDS에서는 MySQL 5.6 버전 이상에 대해서 InnoDB 캐시 워밍업을 지원한다. InnoDB 캐시 워밍업을 활성화 하려면 DB 인스턴스의 파라미터 그룹에서 innodb_buffer_pool_dump_at_shutdown,  innodb_buffer_pool_load_at_startup 파라미터를 1 설정해야 한다. 해당 파라미터 값을 변경하면 해당 파라미터 그룹을 사용하는 모든 MySQL DB 인스턴스에 영향이 있기 때문의 사용시 주의하도록 한다. 특정 MySQL 대해서만 InnoDB 캐시 워밍업을 활성화 하려면 해당 인스턴스에 대한 파라미터 그룹을 생성 하도록 한다.

 

InnoDB 캐시 워밍은 주로 표준 스토리지를 사용하는 DB 인스턴스에 대한 성능 이점을 제공한다. PIOPS 스토리지를 사용하는 경우 일반적으로 상당한 성능 이점이 나타나지 않는다. InnoDB 캐시 워밍을 활성화 하였더라도 장애 조치중과 같이 MySQL DB 인스턴스가 정상적으로 종료되지 않으면 버퍼풀 상태가 디스크에 저장되지 않는다. 경우 MySQL DB 인스턴스가 다시 시작될 사용 가능한 모든 버퍼 파일을 로드 한다. 이런 경우에도 데이터베이스에는 아무런 이상이 없지만 복원된 버퍼풀은 가장 최근의 상태를 반영하지 않을 수도 있다. 시작 InnoDB 캐시를 워밍업 하는데 사용할 있는 버퍼풀의 최신 상태를 사용하려면 주기적으로 버퍼풀을 덤프하는 것이 좋다.

버퍼풀의 현재 상태를 디스크에 저장하려면 아래 프로시저를 호출 한다.

CALL mysql.rds_innodb_buffer_pool_dump_now();

 

디스크에 저장된 버퍼풀의 상태를 로드하려면 아래 프로시저를 호출 한다.

CALL mysql.rds_innodb_buffer_pool_load_now();

 

진행중인 로드 작업을 취소하려면 아래 프로시저를 호출 한다.

CALL mysql.rds_innodb_buffer_pool_load_abort();

 

버퍼풀을 주기적으로 자동으로 덤프하는 이벤트를 생성하여 사용할 경우 수동으로 매번 호출할 필요가 없다. 아래 스크립트는 매시간 버퍼풀을 덤프하는 periodic_buffer_pool_dump라는 이벤트를 생성한다.

CREATE EVENT periodic_buffer_pool_dump
ON SCHEDULE EVERY 1 HOUR
DO CALL mysql.rds_innodb_buffer_pool_dump_now();

 

 

[참고자료]

l  https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt

l  https://dev.mysql.com/doc/refman/8.0/en/innodb-preload-buffer-pool.html

l  https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/mysql_rds_innodb_buffer_pool_dump_now.html

l  https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/mysql_rds_innodb_buffer_pool_load_now.html

l  https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/mysql_rds_innodb_buffer_pool_load_abort.html

 

 

 

2022-03-17 / Sungwook Kang / http://sungwookkang.com

 

 

AWS RDS, MySQL, InnoDB Cache warming, 캐시워밍업, 버퍼풀, buffer pool

Hive 데이터 입력시 노드당 처리 파티션 개수 초과 오류

 

·       Version : Hive

 

파티셔닝된Hive 테이블에 데이터 입력시 아래와 같은 오류가 발생하였다. 오류 메시지를 살펴보면 노드당 최대 동적 파티션 개수보다 많은 수의 동적 파티션이 생성되어 발생한 오류이다.

Error: java.lang.RuntimeException: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row {“col_1”:25513237,“col_2”:8104666,“col_3”:3808,“col_4”:6705,“col_4”:“2016-01-21 08:31:33",“col_6”:42,“col_7”:“471.00”,“col_8”:null} at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:157) at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:54) at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:465) at org.apache.hadoop.mapred.MapTask.run(MapTask.java:349) at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:174) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAs(Subject.java:422) at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1875) at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:168) Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: Hive Runtime Error while processing row {“col_1”:25513237,“col_2”:8104666,“col_3”:3808,“col_4”:6705,“col_5”:“2016-01-21 08:31:33",“col_6”:42,“col_7”:“471.00”,“col_8”:null} at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:494) at org.apache.hadoop.hive.ql.exec.mr.ExecMapper.map(ExecMapper.java:148) ... 8 more Caused by: org.apache.hadoop.hive.ql.metadata.HiveFatalException: [Error 20004]: Fatal error occurred when node tried to create too many dynamic partitions. The maximum number of dynamic partitions is controlled by hive.exec.max.dynamic.partitions and hive.exec.max.dynamic.partitions.pernode. Maximum was set to 100 partitions per node, number of dynamic partitions on this node: 101 at org.apache.hadoop.hive.ql.exec.FileSinkOperator.getDynOutPaths(FileSinkOperator.java:951) at org.apache.hadoop.hive.ql.exec.FileSinkOperator.process(FileSinkOperator.java:722) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:882) at org.apache.hadoop.hive.ql.exec.SelectOperator.process(SelectOperator.java:95) at org.apache.hadoop.hive.ql.exec.Operator.forward(Operator.java:882) at org.apache.hadoop.hive.ql.exec.TableScanOperator.process(TableScanOperator.java:130) at org.apache.hadoop.hive.ql.exec.MapOperator$MapOpCtx.forward(MapOperator.java:146) at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:484) ... 9 more

 

Hive 노드당 최대 동적 파티션 기본값은 100으로 설정되어 있다. 문제를 해결하기 위해서는 아래와 같은 명령을 사용하여 노드당 최대 동적 파티션 갯수 설정을 변경할 있다.

set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.dynamic.partitions.pernode=100000;

 

노드당 파일 갯수 초과할 경우에도 비슷한 오류가 발생한다. 아래 같은 오류 구문이 발생 때에는 파일 갯수의 설정을 오류가 발생한 최대 값보다 크게 설정할 있도록 한다.

[Fatal Error] total number of created files now is 100028, which exceeds 100000. Killing the job.

 

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=100000;
set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.created.files=900000;

 

 

위와 같이 설정값을 변경하기에 앞서 Hive에서 이렇게 많은 파티션 또는 파일을 생성하는지 생각해보아야 한다. 대부분의 경우 사용자 설정값 범위 내에서 파티션이 이루어진다는 가정하에 사용하는데,  이렇게 한계를 벗어난 다는 것은 파티션 키를 잘못 배치했거나 파티션 처리에 적절하지 않는 데이터셋을 사용했을 가능성이 크다. 그럼에도 불구하고 파티션을 늘려야한다고 생각되면 옵션을 사용하여 적절할 임계치를 조절할 있도록 한다.

 

2021-09-13 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, 파티션 테이블, 동적 파티션 개수 초과,

Kubernetes 장점

 

·       Version :

 

 쿠버네티스(Kubernetes) 환경에서는 컨테이너에 애플리케이션에 필요한 모든 항목이 포함되어 있기 때문에 시스템 관리자가 애플리케이션을 실행하기 위해 아무것도 설치할 필요가 없다.

·       애플리케이션 배포 단순화 : 쿠버네티스는 모든 워커 노드를 단일 플랫폼으로 제공하므로 애플리케이션 개발자는 자체적으로 배포할 있으며 클러스터를 구성하는 서버에 대해서 필요가 없다. 특히 특정 컨테이너가  SSD에서만 실행되거나 또는 HDD에서만 실행되어야 하는  경우처럼 특정 리소스가 필요한 경우 쿠버네티스 노드에서 필요한 리소스가 있는 노드를 선택해서 배포할 있다.

·       효율적인 하드웨어 활용 : 쿠버네티스환경에서 애플리케이션을 배포,실행하면 애플리케이션 리소스 요구사항에 따라 사용 가능한 가장 적합한 노드가 선택되어 할당된다. 또한 특정 노드에 애플리케이션을 종속시키지 않는다면 클러스터를 자유럽게 이동할 있어 리소스 가용 상태에 따라 자동으로 이동하거나 매치하여 사용할 있다.

·       자동 복구 모니터링 : 특정 클러스터에 종속되지 않으면 자유롭게 클러스터를 이동할 있기 때문에 이러한 장점으로 인해 모니터링 중에 특정 노드에 장애가 발생하면 자동으로 다른 노드에 애플리케이션이 재배치 되어 실행되기 때문에 야간이나 장애 발생시 즉시 대응할 필요가 없다.

·     오토스케일링 : 쿠버네티스는 애플리케이션에서 사용하는 리소스를 모니터링 하고 애플리케이션에서 실행되는 인스턴스 수를 조정하도록 지시할 있다.

·       개발 환경 단순화 : 애플리케이션이 개발 운영 환경이 동일하기 때문에 개발자는 본인 컴퓨터에서 개발하고 버그를 수정하고, 테스트한 완성된 애플리케이션 환경 그대로 운영 환경에서 실행할수 있다.

 

 

2021-07-30 / Sungwook Kang / https://sungwookkang.com

 

 

Kubernetes, 쿠버네티스

Kubernetes 마스터 노드, 워커 노드

 

·       Version :

 

 쿠버네티스(Kubernetes) 클러스터에서 마스터 노드는 전체 쿠버네티스 시스템을 관리하고 통제하는 쿠버네티스 컨트롤 플레인을 관장한다. 워커 노드는 실제 배포하고자 하는 애플리케이션 실행을 담당한다.

마스터 노드(컨트롤 플레인)에서는 클러스터를 관리하고 클러스터의 기능을 실행한다. 단일 마스터 노드에서 실행하거나 여러 노드로 분할 복제되어 고가용성을 보장할 있는 여러 구성요소로 구성 있다.

·       API Server : 사용자와 컨트롤 플레인과 통신하는 쿠버네티스 API

·       Scheduler : 애플리케이션을 예약하는 스케줄러로, 배포 가능한 구성 요서에 워커 노드 할당을 담당

·       Control Manager : 구성 요소 복제, 워커 노드 추적, 노드 장애 처리 클러스터 기능을 실행

·       etcd : 클러스터 구성을 저장하는 분산 데이터 스토리지  

 

워커 노드는 컨테이너화된 애플리케이션을 실행하는 시스템으로 서비스 실행, 모니터링을 제공한다.

·       Kubelet : API 서버와 통신하고 노드에서 컨테이너를 관리

·       Kube-proxy : 애플리케이션 구성 요소 간에 네트워크 트래픽을 분산하는 쿠버네티스 서비스 프록시

 

 

2021-07-28 / Sungwook Kang / https://sungwookkang.com

 

 

Kubernetes, 쿠버네티스, 마스터 노드, 워커 노드, 컨트롤 플레인, Control Plane

'SW Engineering > DevOps, SRE' 카테고리의 다른 글

[Prometheus] Prometheus 구조 및 개념  (0) 2023.06.28
Kubernetes 장점  (0) 2021.07.31
SRE (Site Reliability Engineering) 역할  (0) 2020.05.14
SRE (Site Reliability Engineering)  (0) 2020.05.11
Docker Network  (0) 2019.03.27

MySQL Master DB 백업하여 Replication Slave DB 구성하기

 

·       Version : MySQL 5.7.5 Later

 

MySQL DB 처음 구축할때 마스터DB 슬레이브DB 구성하는것이 아니라면 반드시 마스터 DB 데이터를 백업하여 슬레이브DB 구성 하여야 한다. 이때 특정 시점까지 (Point in Time) 마스터 DB 백업하면, 백업파일에는 백업이 완료된 시점의 바이너리 로그파일과 포지션 정보가 기록된다. 슬레이브DB에서는 마스터DB 백업 파일 이후로 발생된 데이터 변경사항을 전달받아 레플리케이션 한다.

 

InnoDB 스토리지 엔진은 트랜잭션을 지원하므로 특정 시점까지 백업한 백업 시점의 마지막 바이너리 로그 파일과 로그 포지션 정보로 마스터 DB 슬레이브 DB 연결하는 식으로 레플리케이션을 구성할 있다.

 

MySQL에서 데이터를 백업할 시점 백업(Point in Time) 수행하는 방법에는 가지가 있다. 첫번째 방법은 mysqldump 명령을 사용할때 –single=transaction옵션을 사용하는 방법이고, 두번째 방법은 xtrabackup 사용하는 것이다. 이번 포스트에서는 mysqldump 다루도록 한다.

mysqldump 사용한 시점 백업은 아래와 같다.

mysqldump --all-databases --master-data –single-transaction > all_databases.sql

 

백업이 완료 되었으면 아래 명령을 사용하여 Slave DB에서 백업 파일을 복원한다.

mysql -uroot -p ‘xxxx’ < all_databases.sql

 

슬레이브DB 백업파일 복원이 완료 되었으면 백업파일에서 마스터DB 로그 파일과 포지션 정보를 확인하여 레플리케이션 정보를 등록한다.

head -30 all_databases.sql

 

 

정보를 바탕으로 연결할 마스터DB 정보를 입력하고 연결을 시작한다.

--연결설정
mysql>CHANGE MASTER TO
MASTER_HOST=’1.2.3.4’,
MASTER_USER=’replication_user’,
MASTER_PASSWORD=’replication_password’,
MASTER_PORT=3306,
MASTER_LOG_FILE=’mysql-bin.000108’,
MASTER_LOG_POS=384679355;


--연결시작
mysql> start lave

 

슬레이브DB 복제가 시작되었으면 show slave status 명령을 사용하여 슬레이브DB 복제상태를 확인할 있으며 “Slave I/O thread”, “Slave SQL thread” 상태가 YES 표시되면 정상 작동이며 , NO라고 표시될 경우 비정상 작동이라고 판단할 있다.

 

[참고자료]

·       mysqldump — A Database Backup Program : https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html#mysqldump-transaction-options

 

 

2021-05-28 / Sungwook Kang / http://sungwookkang.com

 

MySQL, MysqlDump, MySQL Replication, MySQL HA, Replication, MySQL복제, 마스터 슬레이브

Split Brain

 

스플릿 브레인 (Split Brain) 클러스터로 구성된 시스템간의 네트워크가 일시적으로 동시에 단절되거나 기타 시스템상의 이유로, 클러스터 상의 모든 노드들이 각자 자신이 Primary라고 인식하게 되는 상황을 뜻한다.  관제 시스템에 의해 하트비트(Heartbeat)등으로 Alive 유무가 체크되는 서비스가 있다고 가정했을때, 하트비트 통신이 단절되어 서비스 클러스터가 장애 상태라고 인식하고 서비스를 동시에 구동하는 경우, 또는 독립적인 개의 시스템이 비정상적으로 구성되어 서로가 Primary라고 믿게되는 현상을 모두 포함한다.

스플릿 브레인 현상이 발생하면, 노드가 동시에 Primary 되면서 이중 가동 현상이 발생한다. 이렇게 이중으로 가동되면서 노드들은 동시에 스토리지에 접근하기 때문에 데이터 동기화 복제에 비정상 적인 트랜잭션이 발생할 있으며, 예상하지 못한 다양한 문제로 전체 서비스가 불능 상태에 빠질 있다.

일반적으로 LB 중심으로 구성되어 특정 노드에 장애가 발생했을때 HA 제공하도록 구성된 토폴로지라면 스플릿 브레인 현상은 발생하지 않는다.  외에도 스플릿 브레인 현상을 방지하기 위해서는 노드에 구성된 쿼럼(Quorum) 홀수로 구성해 과반수 투표를 진행하거나 하트비트 네트워크를 서비스 네트워크와 통합하여 일관성을 유지할 있도록 한다.

 

Split Brain 대해서 설명된 글이 있으니 조금더 자세히 알고 싶으면 아래 링크를 참고 한다.

·       Split Brain - MariaDB Galera Cluster Case : https://bryan.wiki/290

 

 

2021-04-22 / Sungwook Kang / http://sungwookkang.com

 

Split Brain, 스플릿 브레인, 클러스터 단절, 클러스터 장애

B-tree vs Log-Structured Merge-Tree

 

데이터베이스에서 일반적으로 많이 사용되는 데이터 구조는 B-Tree LSM(Log-Structured Merged-Tree)이다.

B-Tree

B-Tree 데이터베이스에 널리사용되며, B-Tree 인덱싱 구조를 사용하면 데이터가 고정 크기 페이지 세그먼트로 디스크에 기록된다. 이러한 페이지 세그먼트의 크기느 4KB (DMBS마다 다를 있음) 이며 키별로 정렬된 Key-Value 가지고 있다. 단일 B-Tree노드는 페이지 범위에 대한 참조가 있는 배열과 같다. 배열의 최대 참조 수를 “branching factor” 한다. 페이지 범위는 다른 페이지 범위를 참조하는 다른 B-Tree 노드이다. 결국 리프수준에서 단일 페이지를 찾을 있다.

B-Tree 페이지 참조가 메모리가 아닌 디스크에 저장된다는 점을 제외하면 저수준 프로그래밍 언어의 포인터와 유사하다. B-Tree에서 삽입 삭제가 발생하면 branching factor 충족하기 위해(밸런스를 맞추기 위해) 노드를 개의 하위 트리로 분할 있다. 데이터베이스가 충돌하는 위험이 발생할 있다. 데이터베이스가 충돌하는 시나리오를 완화하기 위해 B-Tree 구현은 모든 단일 원자 데이터베이스 트랜잭션을 기록하는 WAL (Write-Ahead Log) 작성하여 기록을 추적한다.  WAL B-Tree 손상된 경우 B-Tree 상태를 복원 하는데 사용된다.

 

Algorithm

Average

Worst case

Space

O(n)

O(n)

Search

O(log n)

O(log n)

Insert

O(log n)

O(log n)

Delete

O(log n)

O(log n)

 

 

 

 

LSM Tree

LSM Tree Bitcask, MongoDB, Bigtable, Cassandra, InfluxDB SQLite4 같은 최신 관계형 비관계형 데이터베이스에서 사용하고 있는 인기있는 데이터 구조이다. LSM Tree 각각의 기본 저장 매체에 최적화된 개이상의 개별 구조로 데이터를 유지한다. 메모리에는 실제 디스크의 데이터 값을 포함하는 바이트 오프셋에 대한 참조 정보를 Key-Value  형태로 해시 테이블 (또는 해시 인덱스) 관리한다.

실제로 사용되는 대부분의  LSM Tree 여러 수준을 사용한다. 레벨 0 주로 메모리에 보관되며 트리를 사용하여 표시 있다. 디스크 데이터는 정렬된 상태로 실행될 있도록 구성되며 실행에는 인덱스 키별로 정렬된 데이터가 포함된다. 실행은 디스크에서 단일 파일로 표시되거나 범위가 겹치지 않는 파일 모음으로 표시 있다. 관련 값을 얻기 위해 특정 키에 대한 쿼리를 수행하려면 레벨0 트리에서 검색하고 실행을 수행해야한다.

 

Algorithm

Average

Worst case

Insert

O(1)

O(1)

Find-min

O(N)

O(N)

Delete-min

O(N)

O(N)

 

 

 

[참고자료]

·       B-Tree : https://en.wikipedia.org/wiki/B-tree

·       Log-structured merge-tree : https://en.wikipedia.org/wiki/Log-structured_merge-tree

 

 

 

2021-03-17 / Sungwook Kang / http://sungwookkang.com

 

B-Tree, LSM Tree, Data Structure, Log-Structured-Merged-Tree, Database Index, 자료구조, 데이터스트럭처, 데이터인덱스

Python Multiprocessing(Process) 사용한 데이터 처리 속도 개선

 

·       Version : MAC OS, Python 3.X, PIP3

 

대용량 데이터를 효율적으로 처리하기 위해서는 병렬 처리를 활용하는것이 좋다.  파이썬에서 병렬처리를 제공하는 대표적인 라이브러리는 Threading Multiprocessing 모듈이다. Threading 모들은 파이썬의 GIL(Global Interpreter Lock)라는불리우는 잠금 모델을 사용하기 때문에I/O 작업이 아닌 CPU 작업이 많을 경우 오히려 성능이 저하된다. 방식은 Lock 풀고 스레드를 교환하고 다시 Lock 거는 형태의 멀티스레드이기 떄문이다.

파이썬에서는 Multiprocessing 권장하고 있으며,   모듈에는 대표적으로 Pool Process 있지만 이번 글에서는 Process 대해서 다루기로 한다.

 

·       Pool 사용한 처리 속도 개선 : https://sungwookkang.com/1478

 

Process 하나의 프로세스에 하나의 함수를 할당하여 실행한다. Target= 파라메터에 작업을 할당하고, args=(agr1, ) 인수를 할당하여 프로세스 객체를 생성한다. start() 프로세스를 시작하여 join()으로 프로세스의 종료를 기다린다.

import os

import multiprocessing as mp

from multiprocessing import Pool, Process

import threading

import time

import datetime

 

def multiprocess():

    start = int(time.time())

 

    ojbect_list = []

    for i in range(1,12):

        task = Process(target=work_func, args=(i,))

        ojbect_list.append(task)

        task.start()

 

    for task in ojbect_list:

        task.join()

   

    end = int(time.time())

    print("***run time(sec) : ", end-start)   

   

    print("Number of Core : " + str(mp.cpu_count()))

   

 

def work_func(x):

    print("time : " + str(datetime.datetime.today()) +  " value :" + str(x)  + " PID : "  + str(os.getpid()))

 

if __name__ == '__main__':

# execute only if run as a script

   

    multiprocess()

 

 

코드를 실행한 결과를 살펴보면 실행마다 다른 프로세스(PID 각각 다름)에서 실행된것을 있다.

 

Pool Process 차이점은, Pool 경우 실행되어야 작업이 코어수 만큼 분할되고 코어수 만큼 프로세스가 생성되어 힐당받은 작업을 처리하는데, Process 경우 작업마다 새로운 프로세스가 할당되어 작업을 처리한다.

 

 

2021-03-02/ Sungwook Kang / http://sungwookkang.com

 

파이선파이썬, python, 병렬처리, Multiprocessing, Python Multiprocessing, 파이썬 병렬처리, 데이터 처리, Data Processing

 

Python Multiprocessing(Pool) 사용한 데이터 처리 속도 개선

 

·       Version : MAC OS, Python 3.X, PIP3

 

대용량 데이터를 효율적으로 처리하기 위해서는 병렬 처리를 활용하는것이 좋다. 대부분의 머신러닝/딥러닝에 사용되는 프레임워크들은 함수 내부에서 병렬처리가 가능하도록 설계되어 있기 때문에 시스템의 자원을 효율적으로 사용하지만, 일반적으로 많이 사용되는 데이터 가공 모듈인 pandas 같은 모듈은 병렬처리를 기본적으로 제공하지 않기 떄분에 별도의 병렬처리가 가능하도록 코딩을 해야한다.

 파이썬에서 병렬처리를 제공하는 대표적인 라이브러리는 Threading Multiprocessing 모듈이다. Threading 모들은 파이썬의 GIL(Global Interpreter Lock)라는불리우는 잠금 모델을 사용하기 때문에I/O 작업이 아닌 CPU 작업이 많을 경우 오히려 성능이 저하된다. 방식은 Lock 풀고 스레드를 교환하고 다시 Lock 거는 형태의 멀티스레드이기 떄문이다.

파이썬에서는 Multiprocessing 권장하고 있으며,   모듈에는 대표적으로 Pool Process 있지만 이번 글에서는 Pool 대해서 다루기로 한다.

 

아래 실습코드는 1에서 12까지 숫자를 1 간격으로 출력하는데, for 문을 사용한 싱글처리와 Pool 사용하여 병렬 처리를 하였을때의 처리 시간 할당된 프로세스를 확인한다.

import os

import multiprocessing as mp

from multiprocessing import Pool

import threading

import time

import datetime

 

def non_multiprocess():

    print("non multiprocess")

    start = int(time.time())

   

    for i in range(1,12):

        work_func(i)

 

    end = int(time.time())

 

    print("Number of Core : " + str(mp.cpu_count()))

    print("***run time(sec) : ", end-start)   

 

def multiprocess():

    print("non multiprocess")

 

     #멀티 프로세싱을 위한 CPU 숫자 확인 만들기

    num_cores = mp.cpu_count()

    pool = Pool(num_cores)

 

    start = int(time.time())

 

    ojbect_list = []

    for i in range(1,100):

        ojbect_list.append(i)

    #멀티 프로세싱 워커 호출

    pool.map(work_func, ojbect_list)

 

    end = int(time.time())

 

    #메모리 방지 위해 사용

    pool.close()

    pool.join()

 

    print("Number of Core : " + str(mp.cpu_count()))

    print("***run time(sec) : ", end-start)   

 

def work_func(x):

    print("time : " + str(datetime.datetime.today()) +  "value :" + str(x)  + " PID : "  + str(os.getpid()))

   

    time.sleep(1)

 

if __name__ == '__main__':

# execute only if run as a script

    #non_multiprocess()

    multiprocess()

   

 

 

코드를 실행하면 아래와 같은 결과를 확인할 있다. non multiprocess 라고 되어 있는 결과는 for문을 사용한 싱글 프로세스이며, 개의 프로세스(PID : 49650) 사용되었으며, 순차적으로 실행되어 12초의 시간이 소요된 것을 확인할 있다. Multiprocess 경우 동시에 6개의 프로세스(필자의 테스트 컴퓨터는 6core이다.) 할당되었으며 PID 다른것을 확인할 있다. 전체 실행시간은 2초가 소요된 것을 확인할 있다.

 

간단한 테스트에서는 Multiprocessing 대한 효과를 크게 느끼지 못할수도 있으나 데이터가 기하급수적으로 커질때에는 데이터 처리 속도에 따른 시간이 엄청나게 차이난다.

 

 

2021-03-01/ Sungwook Kang / http://sungwookkang.com

 

파이선파이썬, python, 병렬처리, Multiprocessing, Python Multiprocessing, 파이썬 병렬처리, 데이터 처리, Data Processing

 

Python에서 Yahoo 주식 데이터 가져오기

 

·       Version : MAC OS, Python 3.X, PIP3

 

Yahoo Finance(https://finance.yahoo.com/) 에서 제공하는 API 사용하여 Python에서 주식 데이터를 가져오는 방법에 대해서 알아본다.

 

Yahoo Finance API 종류가 다양하며 API에서 제공하는 데이터도 조금씩 다르다. 단순한 시계열 데이터 부터, 기업 재무제표를 제공하는 API 다양하게 제공한다. 다양한 파이썬 패키지로 제공되고 있으며 아래 링크에서 확인할 있다.

·       yahoo-finance-api : https://github.com/topics/yahoo-finance-api?l=python

이번 포스트에서는 일일 주가 데이터를 제공하는 yfinance라는 파이썬 패키지를 사용하였다.

pip3 install yfinance --user

 

패키지 설치가 완료 되었으면, yfinance import하고 원하는 종목명 날짜를 입력하면 데이터를 가져올 있다.아래 예시는 AAPL(APPLE inc) 주가 데이터를 2020 12 1일부터 데이터를 가져온다.

import yfinance as yf

yf.download('AAPL', start = '2020-12-01')

 

 

2 이상의 종목에 대한 데이터를 가져올 경우, list 형식으로 사용할 있다.

yf.download(['AAPL', 'F'],start = '2020-12-01')

 

 

배당이나, 분할, 애널리스트 평가 정보도 yfinance 패키지에서 확인할 있다.

aapl = yf.Ticker('AAPL')

 

배당 내역

aapl.dividends

분할 내역

aapl.splits

애널리스트 평가

aapl.recommendations

 

지금까지 파이썬으로 패키지를 사용하여 데이터를 가져오는것을 실습하였는데, 이렇게 수집된 데이터를 나만의 데이터베이스로 만들고, 각종 지표를 만들어서 비교해봄으로써, 의미있는 2, 3 데이터를 만들어내는것이 중요하다. 단순히 주가의 가격 변동이나 흐름이 아닌, 시장의 방향과 주가의 방향이 매칭되는 종목을 찾고, 다양한 변수를 대입하여 종목을 추천할 있는 알고리즘을 만든다면, 직감이나 일부 정보만을 가지고, 이른바 바라는 주식투자가 아닌 공학 관점에서 가까이 투자할 있지 않을까 생각해 본다.

 

 

 

2020-12-28/ Sungwook Kang / http://sungwookkang.com

 

파이선, 파이썬, python, 주식 데이터 가져오기, 파이썬 주식, 금융공학, 주식 분석, 미국 주식 

 

Python에서 Tesseract 사용하기

 

·       Version : MAC OS, Python 3.X, PIP3

 

이전 포스트에서 Tesseract 오픈소스 소프트웨어를 사용하여 이미지에 포함된 문자열을 추출하는 방법에 대해서 알아 보았다.

·       Tesseract 활용한 이미지 문자인식 : https://sungwookkang.com/1475

 

다른 포스트에도 언급한바 있지만, 이미지의 경우 배경 색상이나, 글꼴, 언어 타입에 따라 인식률에 차이가 크므로, 전처리 과정이 수반되어야 어느정도 정확도를 높일 있다. OpenCV 오픈소스로 공개된 다양한 이미지 처리 모듈을 사용하기 위해서는 파이썬을 활용할 있는데, 시작으로 파이썬에서 Tesseract 임포트하여 사용하는 방법을 설명한다. 이번 포스트의 내용을 따라하기 전에, Tesseract 프로그램이 설치되어 있어야 한다.

 

Python3.X PIP3 설치 한다. 그리고 아래 명령을 사용하여 Tesseract패키지를 설치 한다. 설치과정에서 Permission 문제가 발생하면 –user 명령을 함께 사용한다.

pip3 install pytesseract --user

pip3 install opencv-python --user

 

Python3 실행하여 아래 코드를 작성한다.

from PIL import Image

from pytesseract import *

import re

import cv2

 

img = Image.open('이미지파일명')

 

text = pytesseract.image_to_string(img,lang='euc') #한글은 'kor'

#간혹 lang 오류가 발생할경우, lang 파라메터 제거

#text = pytesseract.image_to_string(img)

 

print(text)

 

아래 결과는 인터넷에서 어느 식당에서 메뉴 사진을 찍은 이미지에서 메뉴와 가격을 추출한것이다. 아직 데이터가 정제되지 않은 상태이며 한글과 영어가 섞여 있는데, 한글은 판독하지 못한것을 확인할 있다.

 

실제 추출된 문자열에서 데이터로 활용하려면, 이미지 인식 개선, 다양한 문자열 인식, 데이터 가공을 통한 유요한 데이터 추출 등의 작업이 추가되어야 한다. 이러한 작업을 하나의 프로그램으로 만들기 위해서 오늘 실습한 코드에서 점진적으로 코드가 추가될 예정이다.

 

 

2020-12-18/ Sungwook Kang / http://sungwookkang.com

 

이미지 인식, OCR, Tesseract, 문자열 인식, OpenCV, 딥러닝, 머신러닝, 글자 인식, 이미지 분석, 파이선, 파이썬, python

 

Tesseract 활용한 이미지 문자인식

 

Tesseract 이미지로부터 텍스트를 인식하고 추출하는 소프트웨어이며 HP 연구에서에서 개발된 오픈소스 OCR 엔진이다. 현재까지도 LSTM(Long short-term memory) 같은 딥러닝 방식을 통해 텍스트 인식률을 지속적으로 개선하고 있다. Tesseract 사용하기 위해서는 관련 프로그램을 설치 해야한다. 프로그램은 아래 주소에서 다운로드 받을 있다.

·       https://github.com/tesseract-ocr/tesseract/wiki

 

필자의 경우 MAC OS에서 설치를 진행하였으며 home brew 사용하여 설치 하였다.

brew install tesseract

 

brew 설치한 경우 아래 명령으로 설치된 경로를 확인할 있다.

brew list tesseract

 

 

설치가 완료 되었으면, 이미지 파일을 읽어 문자열을 출력하도록 한다. 배경색상과 글자색상에 따른 이미지 인식률을 확인하기 위해 3가지 케이스를 테스트하였다. 실행명령은 아래와 같다.

tesseract /이미지경로/파일명 stdout

 

Image

Results

 

출력 결과를 살펴보면, 배경색과 글자색의 대비가 높을 수록 높은 인식률을 나타내고 있다. 또한 이미지속의 글자가 단순하고, 글꼴에 따라서도 인식률이 다르게 나타나는것을 확인할 있다. 글에는 포함되어 있지 않지만, 한글과 영어에 따른 인식률 차이도 발생함을 확인할 있었다.

이처럼 전체 텍스트 구조를 분석하고 인식하는 과정에 다양한 오차가 발생하기 때문에, 이미지의 인식률을 높이기 위한 전처리 과정이 필요하며, 대표적으로 OpenCV 사용하여 배경과 글자를 분리하여  작업을 진행할 있다.

 

 

 

2020-12-17/ Sungwook Kang / http://sungwookkang.com

 

이미지 인식, OCR, Tesseract, 문자열 인식, OpenCV, 딥러닝, 머신러닝, 글자 인식, 이미지 분석

 

Hive UDF (사용자 정의 함수)

 

·       Version : Hive

 

Hive UDF(User Define Function, 사용자 정의 함수) 사용자에게 HiveQL 확장할 있게 해주는 하이브의 강력한 기능이다. 자바를 이용해 구현하며 세션에 추가되면 마치 내장 함수처럼 동작하고 심지어 온라인 도움말도 제공할 있다. UDF 사용하면 하이브 쿼리가 동작하는 동일한 프로세스 안에서 마치 태스크처럼 돌아간다. 그러므로 효과적으로 동작하고 다른 시스템과의 통합 과정에서 발생하는 복잡함을 제거할 있다.

 

현재 하이브 세션에 로드된 내장함수는 SHOW FUNCTIONS 명령어를 사용하여 목록을 확인할 있다.

hive>show functions;

 

함수는 보통 자신을 설명하는 문서를 가지고 있으며 DESCRIBE FUNCTION 명령어를 사용하여 간략한 설명을 볼수 있다. EXTENDED 예약어로 확장 문서를 확인할 수도 있다.

hive>describe function concat;

 

hive>describe function extended concat;

 

함수를 사용할면 쿼리 안에서 필요한 인자를 넣고 간단히 이름으로 호출하면 된다. 어떤 함수는 지정된 개수의 인자를 받기도 하며, 어떤 함수는 인자와 데이터 형식을 받기도 하는등, 함수에 따라 필요 인수가 다를수 있다.

일반적으로 표준함수라 불리는, 하나의 로우 또는 하나 이상의 컬럼을 받아서 하나의 값을 반환하는 함수는 데이터형을 변환 (DOUBLE-> BIGINT)하거나 round(), floor(),  절대값을 계산하는 abs() 함수 같은 수학함수가 있으며, 대소문자 전환, 문자열 뒤집기, 문자열 연결등과 같은 문자열 조작 함수 등이 있다.

 

집계함수(aggregate function) 사용자 정의와 내장된 모든 집계 함수를 포함하여 0 이상의 로우 또는 하나 이상의 컬럼을 받아서 하나의 결과값을 반환한다. 대표적인 함수로 sum(), avg(), min(), max() 등이 있다.

 

테이블 생성함수(table generating function 0 또는 이상의 입력을 받아서 여러 컬럼 또는 로우를 결과값으로 생성한다. 대표적으로 array 함수가 있으며, explode() 함수는 배열을 입력받아서 배열의 요소를 ROW 반환한다.

 

2020-11-12 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, 하이브 사용자 함수, 하이브 UDF, Hive UDF, User Define Function, Hive Function

Hive Thrift Service (쓰리프트 서비스)

 

·       Version : Hive

 

Hive 하이브 서버(Hive Server) 또는 하이브 쓰리프트(Hive Thrift) 불리는 구성요소를 가지고 있다. 쓰리프트는 확장성과 서로 다른 언어간에 통신이 가능한 소프트웨어 프레임워크이다. 구성요소를 통해 클라이언트는 하나의 포트(Port) 하이브에 접근할 있다.

CLI 하이브를 접근하는 가능 일방적인 방식이다. CLI 모든 하이브 구성요소 설정이 로컬에 복사본으로 존재해야만 동작한다. 마찬가지로 하둡 클리아언트와 하둡 설정도 있어야 한다. 하이브 CLI HDFS 클라이언트, 맵리듀스 클라이언트, JDBC 클라이언트(메타스토어 접속용) 동작한다.

 

하이브 서비스는 쓰리프트를 이용한다. 쓰리프트는 인터페이스 언어를 제공한다. 쓰리프트 컴파일러는 인터페이스를 해석하여 다양한 언어로 네트워크 RPC 클라이언트 코드를 생성한다. 하이브는 자바로 작성되었고, 자바 바이트 코드(bytecode) 범용 플랫폼이므로 쓰리프트 서버를 위한 자바 클라이언트를 하이브 배포에 포함하고 있다. 클라이언트를 사용하는 방법중 하나는 자바 통합 개발 환경으로 프로젝트를 시작해 관련 라이브러리를 직접 포함시키거나 메이븐을 통해 가져오는 방법이 있다.

 

하이브 서비스는 쓰리프트를 통해 하이브 메타스토어에 접속한다. 일반적으로 사용자는 메타스토어를 직접 수정하는 메타스토어 메소드를 사용하지 말고 하이브를 통해 HiveQL 언어를 이용해야한다. 사용자는 테이블에 관한 메타 정보만 제공하는 읽기 전용 메소드를 사용하는것이 좋다.

 

하이브 CLI /tmp hadoop.tmp.dir 디렉터리에 .hivehistory 같은 산출물을 만들어 낸다. 하이브 서비스는 하둡 잡이 실행되는 시작점이기 때문에 하이브 서비스를 배치할 몇가지 고려할 점이 있다. 특히 클라이언트 장비에서하던 태스크 계획, 관리 작업이 서버에서 실행되기 때문에 여러 클라이언트의 동시 실행시 서비스 오버헤드를 줄이기 위하 부하 분산으로 TCP load balance 이용하거나 백엔스 서버의 pool 접속하는 프록시를 만들어 사용하는것이 좋다. 또한 하이브는 hive.start.cleanup.scratchdir 이라는 속성을 통해 재시작시 scratch 디렉터리를 비운다. 기본값은 false이며, true 변경하여 재시작시 디렉터리를 클린업 있다.

 

일반적으로 하이브 세션은 메타스토어로 이용하는 JDBC 데이터베이스에 직접 연결된다. 하이브는 쓰리프트 메타스토어(ThriftMetastore)라는 선택적 구성요소를 제공하는데, 이를 설치하면 하이브 클라이언트는 쓰리프트 메타스토어로 연결되고 쓰리프트 메타스토어가 JDBC 데이터베이스에 연결된다.

 

 

 

 

 

2020-11-08 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 쓰리프트, Hive Thrift, 하이브 관리, Hive Management

Hive 보안 인증, 권한 부여

 

·       Version : Hive

 

하둡은 보안강화를 위해 커버로스(Kerberos)인증을 지원한다. 커버로스 인증은 서버와 클라이언트 간의 상호 인증을 지원한다. 더이상 hadoop. job.ugi 속성을 설정하여 다른 사용자인척 없다. 하지만 이렇게 동작하려면 모든 하둡 구성요소는 커버로스 보안을 양쪽 끝에서 지원해야한다.  모든 하둡 에코 시스템이 커버로스 인증을 지원 못하듯이, 하이브 인증도 완전하지 않다. 하이브는 메타스토어에 접속하기 위해서 JDBC 데이터베이스 연결을 사용하거나 사용자를 대신해서 동작을 수행하는 쓰리프트를 사용한다. 쓰리프트 기반의 하이브 서비스 역시 다른 사용자인척 해야한다. 소유자와 그룹이 파일에 대한 소유권을 갖는 하둡의 파일 소유 모델은 테이블에서 로우나 컬럼 기반 방식으로 접근을 허용하고 금지하도록 구현된 많은 데이터베이스의 방식과 다르다.

앞에 설명한 파일 소유 모델 때문에 파일과 디렉터리의 소유가 서로 다른 사용자라면 파일에 퍼미션(permission) 부여하는 일이 중요하다.  HDFS 퍼미션 시스템은  user, group, others 요소가 있으며 read, write, execute라는 퍼미션이 있다. 하이브는 hive.files.umask.value 속성을 가지고 있는데 설정으로 새롭게 생성하는 파일의 기본 퍼미션을 비트 마스크를 통해서 설정한다. Hadoop Hive 사용자의 구성에 따라 664 권한인 0002 파일 권한 비트 마스크를 만들 있다.

<property> 

  <name>hive.files.umask.value</name> 

  <value>0002</value> 

  <description>The dfs.umask value for the hive created folders</description> 

</property>

 

hive.metastore.authorization.storage.checks 속성을 true 설정하면 테이블 내부에 사용자가 지울 있는 퍼미션을 갖지 못한 파일이 있을때 하이브는 해당 테이블을 드롭하는 것을 방지한다. 속성의 기본값은 false 이며 true 설정해야 한다.

<property> 

  <name>hive.metastore.authorization.storage.checks</name> 

  <value>true</value> 

  <description>Should the metastore do authorization checks against 

  the underlying storage for operations like drop-partition (disallow 

  the drop-partition if the user in question doesn't have permissions 

  to delete the corresponding directory on the storage).</description> 

</property>

 

동시에 Hive hive.metastore.execute.setugi 가능한 true 설정한다. 안전하지 않은 모드에서 속성을 true 설정하면 메타 스토어가 사용자 그룹의 권한을 정의하는 DFS 작업을 수행한다.

 

Hive 인증을 활성화 하는 방법은 hive.security.authorization.enabled true 설정한다. 기본값은 false이다.

<property> 

  <name>hive.security.authorization.enabled</name>  

  <value>true</value> 

  <description>Enable or disable the hive client authorization</description> 

</property>

 

hive.security.authorization.createtable.owner.grants 속성에서는 테이블 생성자가 접근할 있는 권한을 구성한다. 기본값은 null이며, ALL 설정하여 사용자가 자신이 만든 테이블에 액세스 있도록 한다.

<property> 

  <name>hive.security.authorization.createtable.owner.grants</name> 

  <value>ALL</value> 

  <description>The privileges automatically granted to the owner whenever 

  a table gets created.An example like "select,drop" will grant select 

  and drop privilege to the owner of the table</description> 

</property> 

 

아래 스크립트는 Hive명령으로 사용자 인증을 활성화 한다. 권한이 없을 경우 아래 예제 스크립트와 같이 테이블 생성시 오류가 발생한다.

hive> set hive.security.authorization.enabled=true;   

 

hive> CREATE TABLE auth_test (key int, value string);   

 

Authorization failed:No privilege 'Create' found for outputs { database:default}.   

Use show grant to get more details

 

권한을 부여하기 위해서는 아래 스크립트를 사용할수 있다. 사용자(USER), 그룹(GROUP), 역할(ROLES) 같은 다양한 주제에 권한을 부여할 있다.

hive> set system:user.name; 

 

system:user.name=hadoop 

 

hive> GRANT CREATE ON DATABASE default TO USER hadoop; 

 

hive> CREATE TABLE auth_test (key INT, value STRING); 

 

Confirm the permissions we have with the SHOW GRANT command:

hive> SHOW GRANT USER hadoop ON DATABASE default;   

database default   

principalName hadoop   

principalType USER   

privilege Create   

grantTime Sun May 06 17:18:10 EDT 2018   

grantor hadoop

 

사용자별로 퍼미션을 부여하는 작업은 사용자와 테이블이 많을수록 관리 부담이 증가한다. 이런경우 그룹 단위로 퍼미션을 부여할 있다. 하이브에서 그룹은 사용자의 번째 POSIX 그룹과 동일하다.

hive> CREATE TABLE auth_test_group(a int,b int); 

 

hive> SELECT * FROM auth_test_group;

 

Authorization failed:No privilege 'Select' found for inputs 

{ database:default, table:auth_test_group, columnName:a}. 

Use show grant to get more details. 

hive> GRANT SELECT on table auth_test_group to group hadoop; 

hive> SELECT * FROM auth_test_group; 

OK 

Time taken: 0.119 seconds

 

사용자와 그룹 퍼미션이 충분히 유연하지 않은경우 역할(role) 사용할 있다. 사용자에게 역할을 부여하고 특권이 역할에 부여될수 있다. 시스템 외부에서 제어하는 그룹과는 달리 역할은 하이브 내부에서 제어되므로 좀더 유연성을 제공한다.

hive> set system:user.name; 

 

system:user.name=hadoop 

 

hive> GRANT CREATE ON DATABASE default TO USER hadoop; 

 

hive> CREATE TABLE auth_test (key INT, value STRING); 

 

Confirm the permissions we have with the SHOW GRANT command:

hive> SHOW GRANT USER hadoop ON DATABASE default;   

database default    

principalName hadoop   

principalType USER   

privilege Create   

grantTime Sun May 06 17:18:10 EDT 2018   

grantor hadoop

 

기본적으로 파티션 테이블의 권한은 테이블의 권한을 따르거나  파티션에 대한 권한 메커니즘을 설정할 있다. 테이블 속성의 PARTITION_LEVEL_PRIVILEGE true 설정하여 사용할 있다.

hive> ALTER TABLE auth_part 

> SET TBLPROPERTIES ("PARTITION_LEVEL_PRIVILEGE"="TRUE"); 

Authorization failed:No privilege 'Alter' found for inputs 

{database:default, table:auth_part}. 

Use show grant to get more details.

 

일반 사용자는 쿼리를 수행하기 위해서 스스로 특권을 부여하는 번거로움 없이 테이블을 생성하고 싶을 것이다. 또는 기본 동작으로 모든 특권을 부여하여 사용하고 싶을 것이다. 아래 스크립트는 SELECT DROP 특권을 자신 소유의 테이블에 자동으로 권한을 부여한다.

<property> 

  <name>hive.security.authorization.createtable.owner.grants</name> 

  <value>select,drop</value> 

</property>

 

비슷하게 특정 사용자는 생성한 테이블에 대한 특권을 자동으로 부여받을수 있다. 아래 스크립트는 sungwook, sqlmvp 사용자가 모든 테이블을 읽을수 있는 권한을 부여한다. 그리고 tom 테이블 생성만 가능하다.

<property> 

  <name>hive.security.authorization.createtable.user.grants</name> 

  <value>sungwook,sqlmvp:select;tom:create</value> 

</property>

 

동일한 구성을 그룹 권한 역할 권한에도 적용할 있다.

hive.security.authorization.createtable.group.grants 

hive.security.authorization.createtable.role.grants

 

권한을 회수하는 방법은 아래 스크립트를 사용한다.

revoke create on database default from user sungwook;

revoke select on database default from group sungwook; 

 

 

 

[참고자료]

·       Hive - Authority Management (Authorization) : https://www.programmersought.com/article/1095315821/

 

 

2020-10-27 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, 하이브 보안, 하이브 인증, 하이브 권한, Hive Security, Hive Authorization, Hive Authority Management

Hive 잠금(lock)

 

·       Version : Hive

 

HiveQL SQL 유사하지만 잠금(locking) 대한 메커니즘은 완전히 다르다. SQL 비교한다면 매우 부족한 lock 모델을 가지고 있다. 하둡이 제한된 의미의 이어쓰기 (append) 지원하고 있지만 전통적으로는 write-once(한번쓰면 변경이 불가능하다는 의미) 특성을 가지고 있기 때문에 이러한 특성과 맵리듀스의 스트리밍 읽기 방식으로 인해 세밀한 잠금에 대한 접근은 불필요하기 때문이다.

그러나 하둡은 다중 사용자 시스템이기 때문에 잠금과 코디네이션이 필요할수도 있다. 예를들어 INSERT OVERWRITE 쿼리는 테이블의 모든 내용을 덮어쓰고 다른 사용자가 동시에 테이블에 쿼리를 시도하면 쿼리가 실패하거나 잘못된 결과를 반환할 있기 때문에 명시적으로 테이블에 잠금이 필요할 수도 있다.

하이브는 아파치 주키퍼(Apache Zookeeper) 이용하여 잠금을 제공한다. 주키퍼는 분산 코디네이션을 구현한 오픈소스로 Kafka 분산 코디네이션이 필요한 환경에서 많이 사용 한다. 하이브에서 주키퍼를 코디네이션으로 사용하려면 주피커 쿼럼 노드를 등록해야한다. hive-site.xml에서 설정할 있다.

#통신할 주키퍼 목록을 등록, 읽기/쓰기 잠금을 위해서만 필요

<property>

  <name>hive.zookeeper.quorum</name>

  <value>hadoopcluster01:2181,hadoopcluster02:2181</value>

</property>

 

#동시성을 제공할지 설정, 최소 하나의 주키퍼가 등록되어 있어야 한다.

<property>

  <name>hive.support.concurrency</name>

  <value>true</value>

</property>

 

설정으로 하이브는 쿼리를 실행할때 자동으로 잠금이 지원되며 현재 모든 잠금 목록을 확인하기 위해서는 아래 스크립트를 실행한다.

hive> show locks;

hive>show locks 테이블명 extended;

 

동시성 기능이 true 설정되어 있는 경우 하이브는 자동으로 가지 종류의 잠금 기능을 제공한다. 테이블을 읽을 때에는 공유 잠금(shared lock) 사용하고, 테이블을 수정할 때는 배타적 잠금(exclusive lock) 사용한다. 테이블이 파티션닝 되어 있을때 파티션에 대한 베타적 잠금을 얻게 되면 파티션이 수정되는 동안 테이블 삭제 시도와 같은 동시 변경이 발생되지 못하도록 테이블 자체에 공유 잠금을 건다. 베타적 잠금은 테이블의 모든 파티션에 영향을 미친다.

 

명시적으로 잠금을 관리할수도 있으며 아래 스크립트는 명시적으로 베타 잠금을 생성한다.

hive>lock table 테이블명 exclusive;

 

명시적 잠금 해제는 unlock 명령을 사용한다.

hive>unlock table 테이블명;

 

 

[참고자료]

https://cloudera.ericlin.me/2015/05/how-table-locking-works-in-hive/

 

 

 

 

2020-10-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, 하이브락, hive lock, 하이브 잠금

MySQL InnoDB Buffer Pool Resizing Online

 

·       Version : MySQL 5.7.5, 8.0

 

MySQL 5.7.5 부터 InnoDB 버퍼풀의 크기를 서비스 가동중에도 동적으로 조절할 있다. 동적으로 버퍼풀 확대 또는 축소를 제공하기 위해 청크 크기를 정의하는 새로운 변수인 innodb_buffer_pool_chunk_size 도입되었으며, 변수는 동적이 아니며 잘못 구성되면 원하지 않는 상황이 발생할 수도 있다.

아래 그림은 innodb_buffer_pool_size, innodb_buffer_pool_instances , innodb_buffer_pool_chunk_size 상호작용하는 방식을 나타낸것이다.

 

버퍼풀은 여러 인스턴스를 보유할 있으며 인스턴스는 청크로 분할된다. 인스턴스의 수는 1 ~ 64 까지 있으며 청크의 양은 1000개를 초과하지 않도록 해야한다. 따라서 3GB RAM 있는 서버에서, 8개의 인스턴스가 있는 2GB 버퍼 기본값(128M) 청크를 가지고 있는 경우 인스턴스당 2개의 청크를 얻게 된다. 뜻은 16개의 청크가 있음을 의미한다.

 

현재 설정되어있는 버퍼풀 크기를 확인하는 방법은 아래 스크립트를 사용한다.

mysql> show global variables like 'innodb_buffer_pool_size';

+-------------------------+------------+

| Variable_name           | Value      |

+-------------------------+------------+

| innodb_buffer_pool_size | 1073741824 |

+-------------------------+------------+

 

버퍼 크기를 조절하는 방법은 아래 스크립트를 실행한다.  이때 파라메터는 바이트 값이므로 설정시 주의 한다.

mysql> set global innodb_buffer_pool_size=1610612736;

 

 

 

[참고자료]

·       InnoDB Buffer Pool Resizing: Chunk Change : https://www.percona.com/blog/2018/06/19/chunk-change-innodb-buffer-pool-resizing/

 

 

 

 

2020-10-20 / Sungwook Kang / http://sungwookkang.com

 

MySQL, Buffer Pool, innodb_buffer_pool_size, innodb_buffer_pool_instances , innodb_buffer_pool_chunk_size, 버퍼풀 사이즈 조절

Hive 투기적 실행(Speculative execution)

 

·       Version : Hive

 

Hive에서 투기적 실행(Speculative execution)이라 불리는 기능은 하나의 잡을 중복된 태스크로 구성하여 동시에 수행 시키는 하둡의 기능이다. 같은 데이터를 중복하여 복사하기 때문에 많은 리소스를 사용하며, 대부분의 데이터는 버려진다. 기능의 목적은 느리게 동직하는 태스크 트래커를 제거함으로써 개별 태스크의 결과가 빨리 도출되고 결과적으로 전체 수행을 향상시키는데 있다.

, 동일한 태스크를 여러노드에서 실행함으로써, 특정 노드가 느리더라도 (장비 노후 또는 기타 문제로) 다른 노드에서 먼저 끝나면 해당 결과를 사용하고 나머지 노드는 중지 시킨다. 그래서 전체적으로는 수행시간이 단축된다.

Speculative execution 기능 활성화는 mapred-site.xml에서 아래 속성을 true 설정한다.

mapreduce.map.speculative

mapreduce.reduce.speculative

 

Speculative execution 기능은 실시간성이 중요한 잡의 경우 활성화 하여 사용하는 것이 전체적인 응답시간 향상에 이득이 있다. 하지만 입력 데이터 때문에 오래 걸리는 또는 리듀스 태스크에는 높은 오버헤드로 인해서 사용하지 않는것을 추천한다.

 

 

[참고자료]

·       https://community.cloudera.com/t5/Support-Questions/what-is-speculative-execution/td-p/241741

·       https://www.slideshare.net/Hadoop_Summit/t-325p210-cnoguchi

 

 

2020-10-19 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, MapReduce최적화, Map태스크, Reduce 태스크, 하이브 최적화, 투기적 실행, mapreduce.map.speculative, mapreduce.reduce.speculative, Speculative Execution

Hive 자바 가상 머신 재사용

 

·       Version : Hive

 

하둡에서 맵리듀스 태스크를 실행하면 기본적으로 자바 가상 머신이 실행되고 위에서 또는 리듀서 태스크를 실행한다. 하둡의 기본 설정은 일반적으로 포크(forked) 자바 가상 머신을 사용한다. 자바 가상 머신은 가동할 오버헤드가 있기 때문에, 가상 머신의 재사용은 하이브 성능과 매우 밀접한 관계가 있다. 특히 작은 파일을 처리해야하는 경우나 태스크 수행시간이 짧은 작업의 경우 자바 가상 머신을 재사용하면 매우 효율이 좋다. 만약 수십, 수백번의 태스크를 가진 잡을 수행할때 자바 가상 머신 인스턴스를 재사용한다면 동일한 잡에 N 재사용된다. 가상 머신의 재사용 설정은 하둡의 mapred-site.xml에서 설정할 있다.

mapred.job.reuse.jvm.num.tasks= 10

자바 가상 머신 하나당 번의 태스크를 수행할지 설정 -1 설정할 경우 제한이 없음.

 

자바 가상 머신을 재사용할 경우, 잡을 실행할때마다  가상 머신이 새로 가동되는 오버헤드를 줄일 있지만, 예약된 태스크 슬롯을 잡이 완료할 때까지 점유하고 있는 단점이 있다. 예를들어 잡이  병렬로 실행될때, 먼저 끝난 가상 머신은 유휴 상태로 대기하게 되고 마지막 작업이 완료되기 전까지다른 잡이 사용하지 못하는 상태가 된다. 물론 다른 잡은 다른 자바 가상 머신을 생성해서 사용하지만, 이러한 불균형이 지속적으로 발생한다면 리소스 병목이 발생할 있다.  

 

 

 

2020-10-14 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, MapReduce최적화, Map태스크, Reduce 태스크, 하이브 최적화, 자바 가상 머신, JVM

Hive Mapper, Reduce 개수 최적화

 

·       Version : Hive

 

하이브는 쿼리를 이상의 맵리듀스 잡으로 나누어 병렬로 처리한다. 맵리듀스는 다수의 맵퍼와 리듀서 태스크로 실행되는데 맵퍼와 리듀서의 수는 입력하는 데이터 크기, 데이터 수행 연산 종류 다양한 변수에 의존적이다. 너무 많은 맵퍼와 리듀서 태스크는 잡을 초기화 하고, 스케줄링하고 실행하기 위해 많은 오버헤드를 유발한다. 반대로 너무 적은 태스크는 클러스터가 가진 병렬처리의 장점을 활용하지 못하게 된다.

 

리듀스 단계가 있는 하이브 쿼리를 실행하면 리듀서 수를 출력한다. GROUP BY 항상 리듀서 단계가 필요하기 때문에 해당 구문이 포함한스크립트를 실행하면 사용된 맵퍼와 리듀서의 개수를 확인할 있다.

INFO  : Hadoop job information for Stage-1: number of mappers: 5; number of reducers: 1

INFO  : 2020-09-29 22:31:55,395 Stage-1 map = 0%,  reduce = 0%

INFO  : 2020-09-29 22:32:04,712 Stage-1 map = 20%,  reduce = 0%, Cumulative CPU 5.03 sec

INFO  : 2020-09-29 22:32:05,749 Stage-1 map = 60%,  reduce = 0%, Cumulative CPU 12.13 sec

INFO  : 2020-09-29 22:32:09,885 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 19.8 sec

INFO  : 2020-09-29 22:32:16,080 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 25.89 sec

INFO  : MapReduce Total cumulative CPU time: 25 seconds 890 msec

INFO  : Ended Job = job_1591911716086_1525

INFO  : MapReduce Jobs Launched:

INFO  : Stage-Stage-1: Map: 5  Reduce: 1   Cumulative CPU: 25.89 sec   HDFS Read: 610485 HDFS Write: 775295 HDFS EC Read: 0 SUCCESS

INFO  : Total MapReduce CPU Time Spent: 25 seconds 890 msec

INFO  : Completed executing command(queryId=hive_20200929223144_877a1f4b-329b-4418-831d-89bcdc466f30); Time taken: 33.485 seconds

INFO  : OK

 

하이브는 입력 크기에 따라 리듀서 개수를 정한다. fs -count 명령을 사용하여 하둡에서 사용하려는 파일을 지정하여 예상 리듀서의 개수를 확인할 있다.

hadoop fs -count /user/data/nclick/file.txt

 

결과

0            1           12469765 /user/data/nclick/file.txt

 

리듀서의 개수는 하이브 속성중  hive.exec.reducers.bytes.per.reducer 설정된 수자를 파일 크기와 나눈값으로 계산할 있다. 설정 값은 사용자마다 다를 있다. 아래 스크립트는 hive.exec.reducers.bytes.per.reducer 속성값을 수정하는 명령이다. 단위가 바이트임을 주의한다.

set hive.exec.reducers.bytes.per.reducer=75000000

 

쿼리의 단계에서 입력 데이터 크기보다 훨씬 많은 데이터를 만들어내는 경우가 있다. 단계에서 과도한 데이터를 만들어내면 입력 데이터로 추정한 기본 리듀서의 수는 부족할 있으며 비슷하게 함수가 입력 데이터의 많은 부분을 필터링 수도 있다. 그러면 기본값보다 적은 리듀서만 있어도 된다.리듀서의 태스크 수는 mapred.reduce.tasks 설정값으로 조절할 있다.

 

하둡 클러스터에는 태스크를 할당하는 고정된 크기의 슬롯이 있다. 개의큰 잡이 하둡의 모든 슬롯을 점유하면 다른 잡이 시작되지 못할 있다. hive.exec.reducers.max 설정 값을 조절하여 쿼리가 너무 많은 리듀서 자원을 사용하는 것을 예방할 있다.

 

하둡은 맵과 리듀스 태스크를 기동하고 스케줄링하는데 정도 오버헤드가 발생한다. 성능 테스트를 수행할때 이러한 요인을 염두해 두어야 하며 특히 잡의 크기가 작을수록 이러한 부분을 염두해서 테스트를 진행해야한다.

 

 

 

2020-09-29 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, MapReduce최적화, Map태스크, Reduce 태스크, 하이브 최적화

HDFS Cluster Balancing(데이터 블록 분포의 불균형 해소)

 

·       Version : HDFS

 

HDFS 시스템은 여러대의 노드가 클러스터로 동작하기 때문에 시간이 지날수록 데이터 노드의 블록 분포에 대한 불균형이 발생할 있다. 불균형 상태의 클러스터는 맵리듀스의 로컬리티에 영향을 주기 때문에 자주 사용되는 데이터노드에 많은 부하를 주게 된다. 따라서 이러한 블록의 불균형 분포를 해결하기 위해 밸런서 작업으로 블록을 재분배 하여 전체적으로 블록을 고르게 유지할 있도록 다른 노드로 블록을 이동한다. 이때 데이터 유실을 방지하기 위해 데이터 블록 복제본의 배치전략은 유지된다. 밸런서를 실행하는 명령은 아래와 같다.

sudo -u hdfs hdfs balancer

 

 

노드의 균형은 노드들의 이용률(노드에서 사용중인 공간 비율과 저장공간의 비율), 클러스터의 이용률(클러스터에서 사용중인 공간과 저장공간의 비율) 비교하여 임계치 보다 적을때 까지 실행된다. 임계치는 기본 10% 이며 클러스터에는 오직 하나의 밸런서만이 실행될 있다. 임계치 변경은 아래 명령으로 변경할 있다.

sudo -u hdfs hdfs balancer -threshold 5

 

밸런서 작업중 노드 이동에 대한 기본 대역폭은 1MB/s 이지만 hdfs-site.xml에서 dfs.balance.bandwidthPerSec 속성에서 대역폭을 설정 있으며 단위는 byte이다. 아래 명령으로도 설정이 가능하다.

dfsadmin -setBalancerBandwidth  newbandwidth

 

 

 

[참고자료]

·       How-to: Use the New HDFS Intra-DataNode Disk Balancer in Apache Hadoop : https://blog.cloudera.com/how-to-use-the-new-hdfs-intra-datanode-disk-balancer-in-apache-hadoop/

·       HDFS Balancers : https://docs.cloudera.com/documentation/enterprise/5-12-x/topics/admin_hdfs_balancer.html

 

 

 

 

2020-09-25 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, 데이터 블록 불균형, 노드 밸런서, 하둡 밸런서, Hadoop Balancer, Cluster Balancing, 하둡 튜닝, 하둡 관리, HDFS 관리

Hive LIMIT 튜닝 (데이터 샘플링으로 빠르게 응답하기)

 

·       Version : Hive

 

하이브에서 현재 저장되어 있는 데이터의 일부분을 확인하려고 LIMIT 절을 자주 사용한다. RDB 경우 데이터를 ROW단위로 읽기때문에(정확히는 페이지 단위) ROW단위로 처리하면서LIMIT 결과를 (Sort, Group 연산을 하지 않았을 경우) 빠르게 응답할 있다.  하지만 하이브의 경우 데이터 전체에 대해 쿼리를 수행하고 일부 결과만을 반환하기 때문에 불필요한 리소스 낭비가 크다. 그래서 최대한 LIMIT 명령을 피하는 것이 좋다.

만약 limit 자주 사용할 경우 hive-site.xml 파일에서 hive.limit.optimize.enable설정을 통해서  LIMIT 사용할 경우 원본 데이터를 샘플링 있다.

<property>

       <name>hive.limit.optimize.enable</name>

       <value>false</value>

       <description>Whether to enable to optimization to trying a smaller subset of data for simple LIMIT first.</description>

</property>

 

hive.limit.optimize.enable 옵션을 True 설정하면 hive.limit.row.max.size hive.limit.optimize.limit.file 제어할 있다.

<property>

       <name>hive.limit.row.max.size</name>

       <value>100000</value>

       <description>When trying a smaller subset of data for simple LIMIT, how much size we need to guarantee each row to have at least.</description>

</property>

 

<property>

       <name>hive.limit.optimize.limit.file</name>

       <value>10</value>

       <description>When trying a smaller subset of data for simple LIMIT, maximum number of files we can sample.</description>

</property>

 

하지만 기능은 JOIN이나 GRPUP BY 같이 리듀스 과정이 필요한 모든 쿼리에서는 결과 값이 달라지기 때문에 주의해야 한다.

 

 

 

2020-09-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, Hive tunning, 하이브 튜닝, limit tunning, Limit Optimize, limit sampling

HDFS 데이터노드 블록 스캐너 (손상된 블록을 검색하여 수정)

 

·       Version : HDFS

 

HDFS 에서 데이터를 쓰거나 읽을때 체크섬을 사용하여 데이터 손상을 확인하고 수정한다. 이러한 작업으로 데이터 손상을 감지 있지만 해당 작업은 데이터를 쓰거나 읽을때만 발생하므로 클라이언트가 데이터를 요청하기 전에는 손상된 부분을 찾는것이 쉽지 않다. 이러한 손상된 부분을 찾기 위해 모든 데이터노드는 블록스캐너를 실행하여 데이터노드에 저장된 모든 블록을 주기적으로 점검한다. 작업으로 문제 있는 블록은 클라이언트가 읽기 전에 삭제하거나 수정한다.

데이터 블록 스캐너는 점검할 블록 리스트를 관리하며 체크섬 오류를 찾기 위해 모든 블록들을 점검한다. 스캐너는 데이터노드의 디스크 대역폭을 보존하기 위한 조절 메커니즘을 사용한다. 데이터 블록 스캔 주기는 hdfs-site.xml 파일에 dfs.datanode.scan.period.hours 속성 값으로 제어할 있며 단위는 시간(hour)이다. 속성값을 0 으로 설정시 데이터 블록 스캔 작업을 비활성화 한다.

블록 스캐너가 실행될때마다 보고서가 생성되며 데이터 노드의 인터페이스 URL에서 보고서를 확인할 있다.

http://datanode:50075/blockScannerReport

 

 

 

2020-09-22 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, 체크섬 오류, 하둡 데이터 복구, 데이트 블록 스캔, Data block scan, Corrupted blocks, Block Scanner report

Hive EXPLAIN (실행계획) 사용

 

·       Version : Hive

 

하이브에서 EXPLAIN 명령을 사용하면 실행계획을 확인할 있다. , 쿼리를 어떻게 맵리듀스 잡으로 변환하지를 살펴 있다. 실행계획을 사용하는 방법은 아래 스크립트 처럼 쿼리문 앞에 EXPLAIN 명령을 함께 실행한다.

EXPLAIN

SELECT

       col_1, date_local, count(*) as cnt

FROM tbl_a

where col_1 = 'aaa.com'

group by date_local, col_1;

 

아래 실행 계획은 쿼리를 실행하였을때 반환된 결과이다.

1      STAGE DEPENDENCIES:

2        Stage-1 is a root stage

3        Stage-0 depends on stages: Stage-1

4     

5      STAGE PLANS:

6        Stage: Stage-1

7          Map Reduce

8            Map Operator Tree:

9                TableScan

10                 alias: tbl_a

11                 filterExpr: (col_1 = 'aaa.com') (type: boolean)

12                 Statistics: Num rows: 5275084 Data size: 1039193932 Basic stats: COMPLETE Column stats: PARTIAL

13                 Filter Operator

14                   predicate: (col_1 = 'aaa.com') (type: boolean)

15                   Statistics: Num rows: 2637542 Data size: 485307728 Basic stats: COMPLETE Column stats: PARTIAL

16                   Select Operator

17                     expressions: date_local (type: string)

18                     outputColumnNames: date_local

19                     Statistics: Num rows: 2637542 Data size: 485307728 Basic stats: COMPLETE Column stats: PARTIAL

20                     Group By Operator

21                       aggregations: count()

22                       keys: date_local (type: string), 'aaa.com' (type: string)

23                       mode: hash

24                       outputColumnNames: _col0, _col1, _col2

25                       Statistics: Num rows: 1010 Data size: 291890 Basic stats: COMPLETE Column stats: PARTIAL

26                       Reduce Output Operator

27                         key expressions: _col0 (type: string), 'aaa.com' (type: string)

28                         sort order: ++

29                         Map-reduce partition columns: _col0 (type: string), 'aaa.com' (type: string)

30                         Statistics: Num rows: 1010 Data size: 291890 Basic stats: COMPLETE Column stats: PARTIAL

31                         value expressions: _col2 (type: bigint)

32           Reduce Operator Tree:

33             Group By Operator

34              aggregations: count(VALUE._col0)

35               keys: KEY._col0 (type: string), 'aaa.com' (type: string)

36               mode: mergepartial

37               outputColumnNames: _col0, _col1, _col2

38               Statistics: Num rows: 202 Data size: 58378 Basic stats: COMPLETE Column stats: PARTIAL

39               Select Operator

40                 expressions: 'aaa.com' (type: string), _col0 (type: string), _col2 (type: bigint)

41                 outputColumnNames: _col0, _col1, _col2

42                 Statistics: Num rows: 202 Data size: 58378 Basic stats: COMPLETE Column stats: PARTIAL

43                 File Output Operator

44                   compressed: false

45                   Statistics: Num rows: 202 Data size: 58378 Basic stats: COMPLETE Column stats: PARTIAL

46                   table:

47                       input format: org.apache.hadoop.mapred.SequenceFileInputFormat

48                       output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

49                       serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe

50    

51       Stage: Stage-0

52         Fetch Operator

53           limit: -1

54           Processor Tree:

55             ListSink

56    

 

·       1 ~ 2 : 하이브 잡은 하나 이상의 스테이지(stage) 구성된다. 스테이지 사이에는 의존관계가 있으며 복잡한 쿼리는 많은 스테이지로 구성되며 많은 시간이 소요된다. 스테이지는 맵리듀스 스테이지, 샘플링(sampling) 스테이지, 병합 스테이지, limit 스테이지 하이브가 필요한 일을 하는 스테이지로 구성된다. 하이브는 스테이지를 하나씩 실행한다.

·       5 : STAGE PLANS 절은 매우 길고 복잡하다.

·       6 : 잡을 위한 처리 묶음이고 맵리듀스를 통해 실행된다.

·       7 : Map Operator Tree: 이후의 모든 부분은 잡의 부분에서 실행한다.

·       9 : TableScan 태스크는 테이블을 입력으로 받아 결과 컬럼을 만든다.

·       13 : Filter Operator에서 조회 조건을 필터 한다

·       16 : Select Operator에서 출력할 대상을 선정한다.

·       20 : Group By Operator에서 쿼리에서 요청한 카운트 작업을 한다.

·       32 : Reduce Operator Tree : 이후의 부분은 모두 리듀스 부분에서 실행한다.

·       33 : Reduce에서도 Group By Operator 확인하 있는데, 맵에서 전달받은 값을 count 한다.

·       43, 48 : 마지막으로 파일을 출력하며, 해당 문자열 출력 포맷을 사용한다.

·       51 : 쿼리에서 limit 절이 없기 때문에 Stage-0 no-op 스테이지 이다.

 

2020-09-21 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, Hive, 쿼리 실행계획, Hive 쿼리, Hive Query execution plan

Hive 인덱스(index)

 

·       Version : Hive

 

하이브 인덱스는 연산 속도를 향상시키기 위해 컬럼에 인덱스를 생성할 있으나, RDBMS 인덱스랑 다르게 기능이 많이 제한적이다. 하이브는 인덱스 데이터를 원본 테이블이 아닌 별도 테이블에 저장한다. 그래서 인덱스 생성시 별도의 디스크 공간이 필요하고 생성에 따른 비용이 발생한다. 그래서 인덱스를 생성할때 사용 유무 효율을 고려해서 생성해야 한다.

하지만 하이브에서 인덱스는 논리적 파티션의 크기가 작고 개수가 많은 경우 파티셔닝을 대신해서 사용할 있으며, 맵리듀스의 잡의 입력으로 사용할 테이블 블록을 푸루닝(pruning)하는데 도움을 있다. 위에서 언급했듯이 모든 쿼리가 인덱스로 효율적인 것은 아니므로 실행계획을 분석하여 쿼리가 어떤 인덱스를 사용하는지 확인이 필요하다.

 

아래 스크립트는 인덱스를 생성하는 예제이다. AS 절은 인덱스를 구현한 자바 클래스를 인덱스 핸들러로 지정한다.

CREATE INDEX ix_tbl_a

ON TABLE tbl_a (col_1)

AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'

WITH DEFERRED REBUILD;

 

인덱스 핸들러는 인덱스 데이터를 무조건 테이블에 저장하지 않는다. 테이블에 저장하려면 IN TABLE 절을 함께 명시한다.

CREATE INDEX ix_tbl_a

ON TABLE tbl_a (col_1)

AS 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'

WITH DEFERRED REBUILD

IN TABLE tbl_a_index_table

PARTITION BY (par = 'XX');

 

WITH DEFERRED REBUILD 인덱스가 비어있는 상태에서 시작한다. ALTER INDEX 구문을 사용하여 언제든지 리빌드가 가능하다. 만약 파티션을 생략하면 모든 파티션에 대해서 인덱스 리빌드가 발생한다.

ALTER INDEX ix_tbl_a

ON TABLE tbl_a

PARTITION (par = 'XX')

REBUILD;

 

인덱스 삭제는 아래 명령을 사용한다.

DROP INDEX IF EXISTS ix_tbl_a ON TABLE tbl_a;

 

아래 명령은 테이블에 생성된 모든 인덱스 정보를 나타낸다.

SHOW FORMATTED INDEX ON tbl_a;

 

 

 

 

2020-08-27 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, HIVE Index, Hive 인덱스, 하이브 인덱스, 하이브 튜닝

Hive View

 

·       Version : Hive

 

하이브에서 (View) 일반 RDBMS 뷰와 동일하게 데이터를 저장하지 않는 논리적 테이블 구조이다. 뷰는 테이블과 같은 데이터베이스에 저장되기 때문에 이름은 데이터베이스 내에서 유니크해야한다.  아래 스크립트는 하이브에서 뷰를 생성하는 예제이다.

create view vw_a

as

select

       col_1, col_2, col_3

from tbl_a

where col_1 = 'a';

 

뷰를 생성할때 새로운 컬럼 이름 전체나 일부분에 COMMENT 추가할 수도 있다. 뷰는 원본 테이블로 부터 주석을 상속받지 않는다. 뷰는 INSERT LOAD 명령의 대상으로 사용할 없으며 읽기 전용이다.

 

하이브는 뷰를 먼저 수행한 후에 쿼리를 수행한다. 그러나 옵티마이저는 뷰와 쿼리절을 하나의 실제 쿼리로 결합하여 실행할 수도 있다. 하지만 하나의 쿼리로 실행되었다고 하더라도 뷰와 뷰를 사용하는 쿼리 둘다 ORDER BY 절이나 LIMIT 절을 가지고 있으면 뷰의 개념이 적용되어 절을 먼저 수행한다.

 

 

 

2020-08-24 / Sungwook Kang / http://sungwookkang.com

 

 

Hadoop, Big Data, 하둡, 빅데이터, 데이터분석, HDFS, 하둡 파일 시스템, Hive, 하이브, 하이브쿼리, HiveSQL, HIVE view, 하이브 , Hive , 하이브 테이블

+ Recent posts