MySQL에서 자동으로 파티션을 추가하기 위해 MySQL의 event와 procedure를 활용한다.

 

1) 프로시져 생성

2) event 생성

 

1. 프로시저 생성

파티션된 테이블에 maxvalue 파티션이 없는 경우와 maxvalue 파티션이 있는 경우에 대해 각각 파티션을 추가하는 프로시저이다. 

1) maxvalue 가 없는 파티션인 경우

maxvalue가 없는 파티션 테이블

CREATE TABLE sales (
    sale_id INT NOT NULL,
    sale_date DATETIME NOT NULL,
    customer_id INT NOT NULL,
    amount DECIMAL(10,2),
    PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (TO_DAYS(sale_date)) (
    PARTITION p_2025_01 VALUES LESS THAN (TO_DAYS('2025-02-01')),
    PARTITION p_2025_02 VALUES LESS THAN (TO_DAYS('2025-03-01')),
    PARTITION p_2025_03 VALUES LESS THAN (TO_DAYS('2025-04-01')),
    PARTITION p_2025_04 VALUES LESS THAN (TO_DAYS('2025-05-01'))
);

 

자동으로 매월 새로운 파티션을 추가하는 프로시저

DELIMITER //

CREATE PROCEDURE pr_monthly_add_partition(IN partition_time DATETIME)
BEGIN
    SET @sql = CONCAT(
        'ALTER TABLE sales ADD PARTITION (',
        'PARTITION p_', DATE_FORMAT(DATE_SUB(DATE_FORMAT(partition_time, '%Y%m%d'), interval  1 month), '%Y_%m'), 
        ' VALUES LESS THAN (', TO_DAYS(partition_time), '));'
    );
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END //

DELIMITER ;

 

파티션 추가를 위한 프로시저 호출

CALL pr_monthly_add_partition('2025-06-01');

 

2) maxvalue 가 있는 파티션인 경우

maxvalue가 있는 파티션 테이블

CREATE TABLE sales_max (
    sale_id INT NOT NULL,
    sale_date DATETIME NOT NULL,
    customer_id INT NOT NULL,
    amount DECIMAL(10,2),
    PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (TO_DAYS(sale_date)) (
    PARTITION p_2025_01 VALUES LESS THAN (TO_DAYS('2025-02-01')),
    PARTITION p_2025_02 VALUES LESS THAN (TO_DAYS('2025-03-01')),
    PARTITION p_2025_03 VALUES LESS THAN (TO_DAYS('2025-04-01')),
    PARTITION p_2025_04 VALUES LESS THAN (TO_DAYS('2025-05-01')),
    PARTITION p_maxvalue VALUES LESS THAN MAXVALUE
);

 

DELIMITER //

CREATE PROCEDURE pr_monthly_add_partition_max(IN partition_time DATETIME)
BEGIN
    SET @sql = CONCAT(
        'ALTER TABLE sales_max REORGANIZE PARTITION p_maxvalue INTO(\n',
        'PARTITION p_', DATE_FORMAT(partition_time, '%Y_%m'), ' VALUES LESS THAN (', TO_DAYS(partition_time), '),\n',
        'PARTITION p_maxvalue', ' VALUES LESS THAN MAXVALUE);');
    
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
END //

DELIMITER ;

 

파티션 추가를 위한 프로시저 호출

CALL pr_monthly_add_partition_max('2025-06-01');

 

2. event 생성

위에서 생성한 프로시저를 event로 등록하여 필요한 시점에 수행되도록 한다.

event를 수행하기 위해서는 event_scheduler가 ON 으로 설정되어 있어야 한다.

 

이벤트 스케줄러 활성화

SET GLOBAL event_scheduler = ON;

 

매달 1일 자동 실행되는 EVENT 생성

매달 1일에 자동으로 파티션을 추가하는 event를 생성한다. event는 매달 1일 00:00:00 에 수행된다.

CREATE EVENT ev_monthly_add_partition
ON SCHEDULE EVERY 1 MONTH
STARTS TIMESTAMP(LAST_DAY(CURRENT_DATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY)

ON COMPLETION PRESERVE COMMENT '매달 1일에 파티션 추가 EVENT'
DO CALL pr_monthly_add_partition(DATE_FORMAT(LAST_DAY(CURRENT_DATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY, '%Y-%m-%d'));

 

만일, 매달 1일 01:00 수행하기를 원하면

STARTS TIMESTAMP(LAST_DAY(CURRENT_DATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY)를

STARTS TIMESTAMP(LAST_DAY(CURRENT_DATE() - INTERVAL 1 MONTH) + INTERVAL 25 HOUR) 로 수정하면 된다.

위와 같은 방법으로 수행하기를 원하는 시분초를 지정할 수 있다.

 

'MySQL' 카테고리의 다른 글

MySQL uptime  (0) 2025.03.27
MySQL event란  (0) 2024.12.05
MySQL Lock 발생  (0) 2023.09.22
MySQL - stored procedure 성능  (0) 2023.06.29
MySQL - Delimiter  (0) 2023.04.10

DATE, DATETIME, TIMESTAMP 데이터타입의 컬럼으로 파티션을 생성, 추가, 삭제 하는 예제입니다.

 

 

파티션테이블 생성

1) DATE, DATETIME 컬럼으로 파티션

아래는 월별 파티션 예제입니다.

1-1) TO_DAYS 함수 사용

CREATE TABLE sales (
    sale_id INT NOT NULL,
    sale_date DATE NOT NULL,
    customer_id INT NOT NULL,
    amount DECIMAL(10,2),
    PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (TO_DAYS(sale_date)) (
    PARTITION p_2024_01 VALUES LESS THAN (TO_DAYS('2024-02-01')),
    PARTITION p_2024_02 VALUES LESS THAN (TO_DAYS('2024-03-01')),
    PARTITION p_2024_03 VALUES LESS THAN (TO_DAYS('2024-04-01')),
    PARTITION p_2024_04 VALUES LESS THAN (TO_DAYS('2024-05-01')),
    PARTITION p_maxvalue VALUES LESS THAN MAXVALUE
);

Range 파티션은 값으로 int 형 데이터가 와야 하기 때문에 TO_DAYS 함수를 사용.

 

설명:

  • TO_DAYS(sale_date) 함수는 분할을 위해 날짜를 숫자 값으로 변환
  • 각 파티션은 특정 월(예: 2024년 1월, 2024년 2월 등)을 기준으로 정의
  • p_maxvalue 파티션은 2024년 4월보다 큰 모든 데이터를 적재

 

✔ TO_DAYS 함수를 사용하는 이유 : Range 파티션은 값으로 int 형 데이터가 와야 하기 때문

 

1-2) 날짜형식의 String으로 사용

DATE 또는 DATETIME 열을 분할 열로 사용하여 RANGE COLUMNS로 테이블을 분할합니다. 

CREATE TABLE sales_1 (
    sale_id INT NOT NULL,
    sale_date DATE NOT NULL,
    customer_id INT NOT NULL,
    amount DECIMAL(10,2),
    PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE COLUMNS(sale_date) (
    PARTITION p_2024_01 VALUES LESS THAN ('2024-02-01'),
    PARTITION p_2024_02 VALUES LESS THAN ('2024-03-01'),
    PARTITION p_2024_03 VALUES LESS THAN ('2024-04-01'),
    PARTITION p_2024_04 VALUES LESS THAN ('2024-05-01'),
    PARTITION p_maxvalue VALUES LESS THAN MAXVALUE
);

 

2) TIMESTAMP 컬럼으로 파티션

UNIX_TIMESTAMP() 함수를 사용해서 파티셔닝 한다.

MySQL 8.4에서는 UNIX_TIMESTAMP() 함수를 사용하여 TIMESTAMP 열의 값을 기준으로 RANGE로 테이블을 분할할 수 있다.

CREATE TABLE quarterly_report_status (
    report_id INT NOT NULL,
    report_status VARCHAR(20) NOT NULL,
    report_updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)
PARTITION BY RANGE ( UNIX_TIMESTAMP(report_updated) ) (
    PARTITION p5 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-04-01 00:00:00') ),
    PARTITION p6 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-07-01 00:00:00') ),
    PARTITION p7 VALUES LESS THAN ( UNIX_TIMESTAMP('2009-10-01 00:00:00') ),
    PARTITION p8 VALUES LESS THAN ( UNIX_TIMESTAMP('2010-01-01 00:00:00') ),
    PARTITION p9 VALUES LESS THAN (MAXVALUE)
);

 

 

파티션 추가

1) 파티션 테이블이 MAXVALUE로 구성되어 있는 경우에는 REORGANIXE PRTITION 명령어로 기존 MAXVALUE 파티션을 나눈다.

ALTER TABLE sales REORGANIZE PARTITION p_maxvalue INTO(
    PARTITION p_2024_05 VALUES LESS THAN (TO_DAYS('2024-06-01')),
    PARTITION p_maxvalue VALUES LESS THAN MAXVALUE);

 

2) 파티션 테이블이 MAXVALUE로 구성되어 있지 않은 경우에는 ADD PRTITION 명령어로 파티션을 추가한다.

ALTER TABLE sales ADD PARTITION (
    PARTITION p_2024_05 VALUES LESS THAN (TO_DAYS('2024-06-01'))
);

 

파티션 삭제

삭제하고자 하는 파티션을 DROP PARTITION 명령어로 삭제한다. 아래는 p_2024_01 파티션을 삭제하는 예제이다.

ALTER TABLE sales DROP PARTITION p_2024_01;

 

MySQL DB의 구동시간을 알 수 있는 방법은 여러가지가 있다.

 

1) SHOW STATUS 로 확인

결과값은 초로 표시된다.

SHOW STATUS LIKE 'Uptime';
[결과값]
Uptime 144931

 

2) Dictionary Table 로 확인

performance_schema.global_status 의 Uptime 값은 초로 표시되기 때문에 초를 시분으로 변환하여 조회

-- Uptime 을 시분 형식으로 표시
SELECT TIME_FORMAT(SEC_TO_TIME(variable_value ),'%H시간 %i분') as Uptime

       FROM performance_schema.global_status 
       WHERE variable_name='Uptime';
[결과값]
40시간 16분

-- Uptime 을 datetime 형식으로 표시
SELECT FROM_UNIXTIME(UNIX_TIMESTAMP() - variable_value) as Uptime
       FROM performance_schema.global_status 
       WHERE variable_name='Uptime';
[결과값]
2025-03-25 07:31:29.000000

 

3) mysql 명령어로 확인

# mysql -u<user> -p<password> -e "status;" | grep -i "uptime"
[결과값]
Uptime:  2 days 26 min 56 sec

<user>, <password> 는 각자의 DB에서 사용하는 user와 패스워드를 입력

 

3) mysqladmin status 명령어로 확인

# mysqladmin status -u<user> -p<password> 
[결과값]
Uptime: 145329  Threads: 9  Questions: 46314  Slow queries: 0  Opens: 478  Flush tables: 3  Open tables: 399  Queries per second avg: 0.318

<user>, <password> 는 각자의 DB에서 사용하는 user와 패스워드를 입력

 

4) mysqladmin version 명령어로 확인

# mysqladmin version -u<user> -p<password> | grep -i "uptime"
[결과값]
Uptime:                 1 day 16 hours 24 min 51 sec

<user>, <password> 는 각자의 DB에서 사용하는 user와 패스워드를 입력

'MySQL' 카테고리의 다른 글

MySQL - 자동으로 파티션 추가 프로시저/Event  (0) 2025.03.31
MySQL event란  (0) 2024.12.05
MySQL Lock 발생  (0) 2023.09.22
MySQL - stored procedure 성능  (0) 2023.06.29
MySQL - Delimiter  (0) 2023.04.10

 

MySQL event란

MySQL 이벤트는 일정에 따라 실행되는 작업입니다. 예약된 이벤트라고 합니다. 이벤트를 만들면 주기적인 간격으로 실행할 SQL 문이 포함된 데이터베이스 객체를 만들고, 특정 시간에 시작합니다. Unix crontab (일명 " cron job " ) 또는 Windows 작업 스케줄러와 유사합니다.

 

Event 관리 - 생성/수정/삭제

1) Event Scheduler 활성화

이벤트를 실행하려면 Event Scheduler가 활성화되어 있어야 합니다. Event Scheduler가 활성화되어 있지 않다면 아래 명령어로 활성화시킵니다.

SET GLOBAL event_scheduler = ON;

 

2) Event 생성 권한

이벤트가 생성될 스키마에 대한 권한이 필요합니다. Event 생성 권한이 없다면 아래와 같이 EVENT 권한을 부여합니다. 이벤트는 schema 레벨의 권한이므로 테이블 레벨로 권한을 부여할 수 없습니다.

GRANT EVENT ON schemaname.* TO username@'%";

 

 

3) Event 생성

아래는 Event 생성 예시입니다.

CREATE EVENT myevent
    ON SCHEDULE AT TIMESTAMP(CURRENT_DATE) + INTERVAL 1 HOUR
    DO
      UPDATE myschema.mytable SET mycol = mycol + 1;

myevent라는 이름의 이벤트를 생성합니다 .

이 이벤트는 1시간에 한 번씩 mytable 테이블의 mycol 컬럼값을 1씩 증가시키는 SQL 명령문을 실행합니다. 

 

4) 이벤트 수정

이벤트를 수정하려면 'ALTER EVENT' 명령을 사용합니다.

이벤트의 여러 특성을 변경할 수 있습니다.

이 예제에서는 에서 실행되는 SQL 명령문을 myevent에서 모든 레코드를 삭제하고 하루에 한 번(01 시) 실행되도록 변경합니다.

ALTER EVENT myevent
    ON SCHEDULE
      AT TIMESTAMP(CURRENT_DATE) + INTERVAL 1 DAY + INTERVAL 1 HOUR
    DO
      TRUNCATE TABLE myschema.mytable;

 

5) 이벤트 비활성화

DISABLE 명령어로 Event를 비활성화합니다. 

ALTER EVENT myevent DISABLE;

 

6) 이벤트 Drop

DISABLE 명령어로 Event를 비활성화합니다. 

DROP EVENT myevent ;

 

7) Event 조회

데이터베이스의 모든 이벤트를 확인합니다.

SELECT * FROM information_schema.EVENTS;

 

 

CREATE EVENT 옵션

CREATE
    [DEFINER = user]
    EVENT
    [IF NOT EXISTS]
    event_name
    ON SCHEDULE schedule
    [ON COMPLETION [NOT] PRESERVE]
    [ENABLE | DISABLE | DISABLE ON {REPLICA | SLAVE}]
    [COMMENT 'string']
    DO event_body;

schedule: {
    AT timestamp [+ INTERVAL interval] ...
  | EVERY interval
    [STARTS timestamp [+ INTERVAL interval] ...]
    [ENDS timestamp [+ INTERVAL interval] ...]
}

interval:
    quantity {YEAR | QUARTER | MONTH | DAY | HOUR | MINUTE |
              WEEK | SECOND | YEAR_MONTH | DAY_HOUR | DAY_MINUTE |
              DAY_SECOND | HOUR_MINUTE | HOUR_SECOND | MINUTE_SECOND}

 

*** Event 생성 옵션 중 설명

- STARTS 와 ENDS 가 정의된 상태에서 ON COMPLETION NOT PRESERVE 옵션은 Event를 Drop 하고 

ON COMPLETION PRESERVE 옵션은 Event를 유지한다.

 

 

'MySQL' 카테고리의 다른 글

MySQL - 자동으로 파티션 추가 프로시저/Event  (0) 2025.03.31
MySQL uptime  (0) 2025.03.27
MySQL Lock 발생  (0) 2023.09.22
MySQL - stored procedure 성능  (0) 2023.06.29
MySQL - Delimiter  (0) 2023.04.10

 

 

  • Global privileges : 전역 권한은 서버의 모든 데이터베이스에 적용됩니다. 관리 권한은 사용자가 MySQL 서버의 작업을 관리할 수 있게 하고 특정 데이터베이스에만 국한되지 않기 때문에 글로벌 그룹에 속합니다.(mysql.user, information_schema.user_privileges)
  • Database privileges : 데이터베이스 권한은 MySQL 인스턴스의 특정 데이터베이스와 해당 데이터베이스 내의 모든 개체(예: 테이블, 컬럼, 뷰)에 적용됩니다. 데이터베이스 권한을 전역적으로 부여할 수도 있습니다. (mysql.db)
  • Proxy privileges : 프록시 권한을 사용하면 사용자는 다른 사용자에게 부여된 권한을 갖고 있는 것처럼 행동할 수 있습니다.
  • Privileges for database objects : 데이터베이스 개체(테이블, 열, 저장 루틴, 뷰 등)에 대한 권한은 특정 데이터베이스 내의 한 유형의 모든 개체 또는 특정 테이블이나 뷰와 같은 특정 개체에 적용될 수 있습니다. 데이터베이스 개체 권한을 전역적으로 부여할 수도 있습니다.

 

테이블이나 컬럼의 character set 이 상이한 경우 인덱스가 존재하더라도, Full Table Scan으로 수행될 수 있다.

 

1) character set이 다른 2개의 테이블 생성

country와 city라는 2개의 테이블을 생성한다. city의 CountryCode는 country 테이블의 Code값을 가지고 있다.

 CREATE TABLE `country` (
   `Code` char(3) NOT NULL DEFAULT '',
   `Name` char(52) NOT NULL DEFAULT '',
   `Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia',
   `Region` char(26) NOT NULL DEFAULT '',
    PRIMARY KEY (`Code`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ;

 

 CREATE TABLE `city` (
   `ID` int NOT NULL AUTO_INCREMENT,
   `Name` char(35) NOT NULL DEFAULT '',
   `CountryCode` char(3) NOT NULL DEFAULT '',
   `District` char(20) NOT NULL DEFAULT '',
   `Population` int NOT NULL DEFAULT '0',
   PRIMARY KEY (`ID`),
   KEY `CountryCode` (`CountryCode`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

 

2) JOIN

country와 city 테이블을 JOIN하여 조회한다.

 select *
 from country a, city b
 where a.code = b.CountryCode
 and a.code = 'AFG';

 

3) 실행계획 보기

MySQL Workbench 로 실행계획을 확인한다.

character set이 상이한 테이블을 join한 결과 인덱스가 존재함에도 Full Table Scan 하는 것을 볼 수 있다.

4) character set 변경

city 테이블의 character set을 country 테이블의 character set과 동일하게 변경한다.

 alter table city convert to character set utf8mb4;

 

5) 실행계획 확인

MySQL Workbench 로 실행계획을 확인한다.

정상적으로 인덱스 Scan을 확인할 수 있다.

6) 결론

Character Set이 상이한 경우에 정상적으로 인덱스를 타지 않을 수 있으므로, 특별한 경우가 아니라면 동일한 character set을 설정하도록 한다.

OS 환경

- Ubuntu  20.04 LTS- 4 vCPU, 8GB- Cloudera Manager  7(설치되는 OS에 맞게 설치)

- 30GB SSD Disk

- OS 버전에 따라 설치가 잘 안될 수 있으니 OS 선택 시 주의 필요.

 

1. 개요

2. SW, HW 환경

3. 설치

  . java 

sudo apt-get update
sudo apt-get install openjdk-8-jdk

  . python3 설치

sudo apt update
sudo apt install python3

  . eclipse

  . virtual Box

  . puTTy

  . Fileziller

  . Chrome

  . NTP 설치

  . 실습예제 및 소스 다운로드 : https://github.com/wikibook/bigdata2nd/archive/master.zip

 

*** 최초 Ubuntu 24.04 LTS 에 설치하려니 지원하지 않는다는 메시지 출력. Ubuntu 20.04 LTS로 변경

*** 아래는 Cloudera Manager 7 이 설치되는 OS 버전임.

Cloudera Manager supports the following 64-bit operating systems:

* Red Hat Enterprise Linux 7 (Update 6 or later recommended)
* Red Hat Enterprise Linux 8 (Update 2 or later recommended)
* Oracle Enterprise Linux 7 (Update 4 or later recommended)
* CentOS 7 (Update 4 or later recommended)
* CentOS 8 (Update 2 or later recommended)
* Ubuntu 18.04 LTS
* Ubuntu 20.04 LTSType 'back' to go back.

 

 

 

4.  VM 에 cloudera Manager 설치

1) /etc/hosts 파일에 서버 등록

각자의 서버 IP에 대한 hostname을 /etc/hosts 파일에 등록해 준다. FQDN 은 등록하지 않아도 된다.

172.31.5.7	aiserver01.domain.com	aiserver01
172.31.3.242	aiserver02.domain.com	aiserver02
172.31.3.225	aiserver03.domain.com	aiserver03

 

1) Cloudera Manager Server 설치

Cloudera Manager를 다운로드하고 CDP Private Cloud Base 클러스터를 설정한다.

아래의 명령어로 cloudera Manger 를 설치한다.

$ wget https://archive.cloudera.com/cm7/7.4.4/cloudera-manager-installer.bin
$ chmod u+x cloudera-manager-installer.bin
$ sudo ./cloudera-manager-installer.bin

설치 시 계속이어지는 화면이다. 화면이 길어서 2개의 화면으로 캡쳐했다.

설치가 완료되면 7180 포트로 브라우저에서 접속할 있다. 

http://localhost:7180/ 또는 localhost 대신 접속할 수 있는 IP로 접속해 보면 아래와 같은 로그인 화면을 볼 수 있다.

로그인 화면에 설치시에 화면에 보여진 admin 계정에 admin 패스워드를 입력하여 접속한다.

 

설치된 Cloudera manager는 60일 데모 버전이다. 로그인하면 아래와 같이 license file을 업로드 하거나
60일 trial 버전을 사용하거나 하는 선택화면이 나온다. 본 문서에서는 60일 trial 을 선택한다.

아래와 같은 화면이 나오는데 [계속] 버튼을 클릭한다.

 

클러스터 이름을 입력한다.

 

 

Agent를 설치할 Hosts를 네트워크 상에서 검색한다. 22번 Port로 검색하니 22번 Port로 통신이 되어야 한다.

/etc/hosts 파일에 등록한 hostname을 콤마로 구분하여 입력한 후 [검색] 버튼을 클릭한다.

 

리포지토리 선택

 

JDK 선택

JDK는 OpenJDK 8 버전을 설치하였으므로 "Manually manage JDK" 를 선택한다.

SSH 로그인 정보 설정

Agent가 설치될 서버에 접근할 수 있는 사용자 계정과 인증방법을 선택한다. 본문서에서는 인증키를 이용한다.

Private Key를 선택해 준다.

 

 

 

2) Cloudera Manager Agent 설치

- Cloudera Manager  서버의 7182 port와 agent가 통신하므로 port가 오픈되어 있어야 한다.

아래 화면은 Agent가 설치 완료된 화면이다.

 

 

Parcels 설치

다음 단계로 Parcels 가 설치되는 화면이다. 설치 시간이 오래 걸린다.

클러스터 인스펙트

클러스터 구성이 잘 되었는지 검사하는 과정이다.

네트워크 성능 검사는 ping 테스트를 수행하는데 방화벽이 설정되어 있을 경우, ICMP 프로토콜을  허용해 준다.

Network Performance 수행 시 Error가 발생했는데 확인해 보니 Cloudera Manager 에서 Python2 를 사용하고 있고, 이 부분에서 오류가 발생했다. Host 검사도 warning이 발생했는데 해결방법을 찾지 못해 무시하고 진행했다. 

 

설치할 서비스를 선택하는 화면이다.

본 문서에서는 "Data Engineering"을 선택했다. 각자의 사용 목적에 따라 설치하면 된다.

 

역할 할당

서버별로 서비스할 역할을 할당해 주는 화면이다.

kafka,Atlas, Data Analytics Studio, HBase, HDFS, Hive, Hive on Tez, Hue, Cloudera Management Service, Oozie, Ranger, Solr, Tez, YARN (MR2 Included), ZooKeeper 서비스에 대한 각 서버의 역할을 할당한다.

 

아래는 본 문서에서 할당한 역할들이다.

 

데이터베이스 설정

본 문서에서는 "내장된 데이터베이스 사용 "을 선택했다. 화면에 제시된대로 패스워드는 따로 저장해 둔다.

 

 

 

 

 

 

1)  /etc/apt/sources.list.d/cloudera.manager 파일을 생성한 후 아래 내용을 입력한다.

    내용 중 /myUsername:myPassword 부분은 본의의 https://www.cloudera.com/ 의 계정과 패스워드를 입력한다.

    단, 주의할 점은 계정과 패스워드에 특수문자는 반드시 퍼센트 인코딩(percent encoding) 문자로 변경해야 한다.

    예를 들면, 계정이름이 name@email.com 이라면 '@' 특수문자는 '%40' 으로 퍼센트 인코딩 문자로 변경해야 한다. 

# Cloudera Manager 7.11.3
# Changeme: change username and password below to match your license
deb [arch=amd64] https://myUsername:myPassword@archive.cloudera.com/p/cm7/7.11.3/ubuntu2004/apt bionic-cm7.11.3 contrib

 

Import the repository signing GPG key (substitute the correct URL):

wget https://[username]:[password]@archive.cloudera.com/p/cm7/[**Cloudera Manager version**]/ubuntu2004/apt/archive.key
sudo apt-key add archive.key

 

- 위의 명령어에서 username, password, [**Cloudera Manager version**] 부분은 위와 동일하게 Cloudera URL의 계정과 패스워드 그리고 설치할 Cloudera Mnager 버전을 기입한다. 본 문서에서는 7.11.3 버전을 설치한다.

 

 

https://www.cloudera.com/downloads/cdp-private-cloud-trial/cdp-private-cloud-base-trial.html

--> 

--

 

 

 


wget https://gosea01%40naver.com:%21Gosea0070@archive.cloudera.com/p/cm7/7.11.3/ubuntu2004/apt/archive.key

 

 

 

Ubuntu 20 Repository:
https://username:password@archive.cloudera.com/p/cm7/7.11.3/ubuntu2004/apt
Repository file:
https://username:password@archive.cloudera.com/p/cm7/7.11.3/ubuntu2004/apt/cloudera-manager.list

환경

서버 : 2 vCPU, 4G Memory, 30G Disk 마스터 3대

OS : Ubuntu 24.04 LTS

Redis : redis-cli 7.0.15 ( redis-cli -v 또는 redis-cli 로 접속 후 info 명령어 수행후 redis_server 확인)

 

Redis 설치

각각의 서버에 Redis server를 설치한다.

$ sudo apt upgrade
$ sudo apt install redis-server

 

 redis.conf 파일 수정

각 서버의 /etc/redis/redis.conf 파일을 아래와 같이 수정한다. <master_IP> 와 <redis_password> 부분은 각자의 IP와 패스워드를 입력한다.

port 7000
bind <master_IP> -::1
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
requirepass <redis_password>
appendonly yes

 

Create a Redis Cluster

아래 명령어 수행 시 

redis-cli --cluster create master01_ip:7000 master02_ip:7000 master03_ip:7000

 

" [ERR] Node ip_addr:7000 DENIED Redis is running in protected mode ... " 오류가 발생했다.

  • 원인 : 호스트를 개방해줘도 redis에 protected mode가 가동중이기때문에 외부 접속이 안된다
  • 조치 :    

          1. redis가 설치된 우분투 사용 곧 외부접속이 아닌 내부접속 사용 : 물리적으로 다른 서버를 사용하므로 해당없음
          2. 보호모드 사용 중지 : /etc/redis/redis.conf 파일의 protecte mode yes를 protecte mode no로 변경
          3. redis 비밀번호를 설정하여 외부접속 : /etc/redis/redis.conf 의 requirepass <password> 설정

 

본 문서에서는 3번째 방법을 사용했다. 위에 redis.conf 파일 수정 부분에  requirepass <redis_password> 이 부분을 먼저 설정한 경우에는 이 오류가 발생하지 않는다. 단 수정 후 redis-server를 재기동해야 한다.

 

"[ERR] Node ip_addr:7000 NOAUTH Authentication required.

  • 원인 : redis-cli 수행 시 패스워드가 설정되어 있지 않음.
  • 조치 :   -a 'redis_password' 처럼 -a 옵션으로 패스워드 입력후 명령어 수행

의문점 : 각각의 master에서 수행해야 하는 것인지? 하나의 마스터에서만 수행하면 되는지? 일단, 하나의 마스터에서 수행하였다. 

               그리고 각각의 redis-server 정보를 info cluster 명령어로 확인해 보니 cluster_enabled:1 로 설정되었다.

               하나의 마스터에서만 수행하면 된다.

 

아래 화면은 cluster가 구성된 화면인다. Master 3대가 조인되었고 각 서버당 대략 5461개의 slot이 할당되었다.      

 

" Waiting for the cluster to join" 메시지가 출력된 상태로 진행이 되지 않을 경우

Every Redis Cluster node requires two TCP connections open. The normal Redis TCP port used to serve clients, for example 6379, plus the port obtained by adding 10000 to the data port, so 16379 in the example.

--> 방화벽 OPEN. 만약 다른 포트(7000)를 사용했다면 앞에 1을 붙여(17000) port가 오픈되어 있어야 한다.

 

 

 

 

테스트

set 테스트

redis-server -h [서버IP] -p 7000 -c -a [비밀번호] 를 입력하여 redis-server 에 클러스터 모드로 접속한다. (-c 입력 필수)

클러스터 모드로 접속하지 않으면 key setting 할 경우 아래처럼 오류가 발생한다.

[master01_ip]:7000> set id "hi. nice to meet you"
(error) MOVED 7568 [master02_ip]:7000

set id "hi. nice to meet you"는 key slot이 7568번이라서 2번 노드에 할당되어야 하는데, 클러스터 모드로 접근하지 않아 redis-cli 가 다른 노드에 접속하지 못하여 발생하는 오류이다.

 

아래처럼 -c 옵션으로 클러스터 모드로 접속한다.

redis-cli -h <master01_ip> -p 7000 -a <redis_password> -c

 

 

클러스터 모드로 redis-cli 접속한 후 아래와 같이 set 명령어를 수행하면 redis 프롬프트가 할당된 슬롯이 있는 해당 서버로 접속되는 것을 볼 수 있다. 아래 예제는 master02 서버로 접속하여 get 하는 명령어이다.

[master01_ip]:7000> set id "hi. nice to meet you"
-> Redirected to slot [7568] located at [master02_ip]:7000
OK
[master02_ip]:7000> get id
"hi. nice to meet you"

--> sharding 으로 데이터를 관리하므로 데이터가 있는 서버로 접속한다.

 

Redis Cluster 에 데이터를 저장하고 불러오는 Python 프로그램 

1) redis-py-cluster 라이브러리를 설치

pip install redis-py-cluster


오류 : rediscluster 모듈 실치 시 아래와 같은 오류가 발생했는데, 

pip install rediscluster 명령어가 아닌 pip install redis-py-cluster 명령어를 수행했다.

python3.12 버전에 맞는 rediscluster 는 pip install redis-py-cluster 명령어로 설치해야 한다.

ubuntu@ip-172-31-11-88:~$ pip install rediscluster
Defaulting to user installation because normal site-packages is not writeable
Collecting rediscluster
  Using cached rediscluster-0.5.3.tar.gz (9.9 kB)
  Preparing metadata (setup.py) ... error
  error: subprocess-exited-with-error
  
  × python setup.py egg_info did not run successfully.
  │ exit code: 1
  ╰─> [10 lines of output]
  .... 하략 ....

 

 

아래는 Redis 클러스터에 데이터를 설정하는 Python 예제 코드이다.

from rediscluster import RedisCluster

# Redis 클러스터 노드 구성
startup_nodes = [
    {"host": "master01_ip", "port": "7000"},
    {"host": "master02_ip", "port": "7000"},
    {"host": "master03_ip", "port": "7000"}
]

# Redis 클러스터 초기화
try:
    redis_cluster = RedisCluster(startup_nodes=startup_nodes, password=<redis_password>, decode_responses=True)
except Exception as e:
    print(f"Could not connect to Redis cluster: {e}")
    exit(1)

# 데이터 설정
key = "example_key"
value = "example_value"

try:
    redis_cluster.set(key, value)
    print(f"Key '{key}' set with value '{value}'")
except Exception as e:
    print(f"Could not set data in Redis cluster: {e}")

 

 

 

설명

+ Recent posts