Category: Develop

0

Kafka Consumer

Kafka Consumer카프카에서는 Consumer 가 데이터를 가져가도 데이터가 사라지지 않는다. Kafka Consumer 는 기본적으로 Topic 의 데이터를 가져온다. 데이터를 가져오는 것을 Polling 이라고 한다. Partition Offset 위치 기록(Commit) Consumer Group 을 통해 병렬 처리 offset 메시지가 파티션 내에서 가지는 고유의 번호 offset 은 토픽 별로 파티션 별로 별개로 지정된다. Consumer 가 데이터를 어느지점까지 읽었는지 확인하는 용도로 사용한다. Consumer 가 데이터를 읽어가면 offset 을 Commit 한다. Consumer 가 Partition 의 읽은 위치(offset) 은 Kafka 의 __Consumer_offset 토픽에 저장된다. Consumer 가 중지가 되더라도 시작 위치를 알고 있으므로 다시 복구하여 데이터를 처리할 수 있다. Multiple Consumer Consumer 개수는 Partition 개수보다 적거나 같아야 한다. 여러 Partition 을 가진 Topic 에 대해 Consumer 가 병렬 처리하게 하기 위해서는 Consumer 가 Partition의 개수보다 작아야 한다. 다른 Consumer Group

0

Kafka Partitioner

Kafka Partitioner Producer 가 데이터를 보내면 무조건 Partitioner 를 통해 Broker 로 데이터를 보낸다. Recode 에 포함된 Message Key 혹은 Message 값에 따라서 Partition 의 위치가 결정된다. Producer 를 사용할때 Partitiooner 를 설정하지 않는다면 UniformStickyPartitioner 로 설정된다. Key 가 있는 Message Message Key 를 가진 레코드는 Partitioner 에 의해서 특정한 Hash 값이 생성된다. 해당 Hash 값을 이용해 어느 Partition 에 저장될지 결정된다. 동일한 Message Key 를 가진 Record 는 동일한 Hash 값을 만들기 때문에 항상 동일한 Partition 에 들어가는 것을 보장한다. 순서를 지켜서 데이터를 처리할 수 있는 장점이 있다. Partition 내부에서는 Queue 처럼 동작하기 때문에 순서를 지킬 수 있다. Key 가 없는 MessageRound Robin 형태로 데이터가 들어가게 된다. UniformStickyPartitioner 는 프로듀서에서 배치로 모을 수 있는 최대한의 Record 를 모아서 Partition 으로 데이터를 보내게 된다. Message Key 가 없는 Record 들은 Partition 에 적절히 분배된다.

0

Kafka Producer

카프카 프로듀서카프카 프로듀서는 브로커에 존재하는 토픽에 메시지를 전달하는 역할을 담당합니다. Topic 에 해당하는 메시지를 생성 후 해당 Topic으로 데이터를 publish 한다. 또한, 메시지 전송이 실패할 경우, 재전송을 한다. 카프카 프로듀서는 브로커로 메시지를 보낼때 파티션 Key 도 함께 보낼 수 있습니다. 브로커는 파티션 Key 의 유무에 따라 데이터를 저장하는 방식이 달라집니다. 파티션 Key 가 null 인 데이터 전송Topic 에 Partition 이 한개인 경우는 데이터들이 순차적으로 쌓이게 된다. Topic 에 Partition 이 여러개인 경우 Round Robin 형식으로 데이터가 쌓이게 된다. 파티션 Key 를 전송할 경우Kafka 는 Key 를 특정한 Hash 값으로 변형 시켜 Partition 과 1:1 매칭을 시킵니다. 각 파티션에 동일 Key 의 Value 만 쌓이게 된다. Partition 의 개수와 Key 의 개수가 일치하지 않는 경우 Key 와 Partition 의 매칭이 깨지게 돼 Key 와 Partition 연결은 보장되지 않습니다.

0

Kafka Replication

Kafka Broker카프카가 설치 돼 있는 서버 단위를 말한다. 보통 3개 이상의 Broker 로 구성해 사용하는 것을 권장 Replication 데이터의 복제를 의미한다 Replication 은 Partition 의 고가용성 을 위해 사용된다. 3개 이상의 Broker 를 사용할 때 Replication 은 3으로 설정하는 것이 좋다 Replication 이 1인 경우 Partition 이 원본 1개만 존재한다는 것이다. Replication 이 2인 경우 Partition 이 원본 1개와 복재본 1개 총 2개가 존재함을 의미한다. Replication 이 3인 경우 Partition 이 원본 1개와 복재본 2개 총 3개가 존재함을 의미한다. Broker 개수에 따라서 Replication 개수가 제한된다. Replication 의 개수는 Broker의 개수를 넘어설 수 없다. 원본 Partition 은 Leader Partition 이라 부르고, 복재본 Partition 은 Follower Partition 이라 부른다. Leader Partition 과 Follower Partition 을 합쳐서 ISR (In Sync Replica) 라고 부른다. Producer 가 Topic 의 Partition 에 데이터를 전달할 때 전달받는 주체가 Leader Partition 이된다. Replication 이 1인 경우 Partition 이 한개고 Replication 이 1인 Topic 이 존재하고 Broker 가 3대라면 Broker 3대 중 1대에 해당 Topic 정보가 저장된다.

0

Kafka 구조

Kafka 구조 Topic 데이터를 구분하기 위해 사용하는 논리적인 단위 (데이터 베이스의 테이블 명과 유사하다고 생각하면 된다.) Topic은 한개 이상의 partition으로 구성된다. 카프카에서는 데이터를 주고 받을 때 Topic 을 이용해 pub/sub 형태로 데이터를 주고 받는다. Partition 토픽에 속한 Record 를 실제 저장소에 저장하는 가장 작은 물리적인 단위 Consumer 가 Record 를 가져가더라도 Record 는 삭제되지 않는다. 파티션은 늘리는 것은 가능하지만 줄이는 것은 불가능하므로 파티션을 늘릴때는 주의 해야 한다. Record 파티션에 저장되는 데이터 Kafka Pub/Sub 모델 Kafka 를 사용하기 위해서는 Message 를 발행하는 Producer 와 Message 를 구독하는 Consumer 로 구성한다. Kafka 에서는 메시지를 발행하는 Publisher 를 Producer 로 메시지를 구독하는 Subscriber 를 Consumer 라고 부른다. Kafka 에서는 Consumer 가 데이터를 가져가도 데이터가 사라지지 않는다. Kafka Producer Kafka Producer 는 데이터를 Kafka 로 보내는 역할을 한다.

0

Kafka 설치

카프카 설치http://kafka.apache.org/ 주키퍼 실행bin/zookeeper-server-start.sh config/zookeeper.properties Properties 변경server.properties에서 Listner 설정을 추가해 줘야 한다. listeners=PLAINTEXT://127.0.0.1:9092 kafka 실행bin/kafka-server-start.sh config/server.properties

0

백준 15650 - N 과 M (2) - 순열

백준 15650 - N 과 M (2) - 순열 Post not found: algorithm/baekjoon/경우의수/15649-N과M-cpp Post not found: algorithm/baekjoon/경우의수/15650-N과M-cpp 링크https://www.acmicpc.net/problem/2606 문제 풀이 주어진 N 개에서 M 개를 뽑는 경우의 수를 다루는 조합 문제 백트레킹 을 이용해 만들 수 있는 모든 경우의 수를 만들어 줬다. 다만, 조합은 순서와 상관 없이 뽑은 상태가 같으면 같은 Case 로 분류가 된다. 때문에 현재 뽑은 위치(idx) 에서 앞에 있는 것들만 뽑게 하면 같은 경우의 수가 나오는 것을 방지할 수 있다. 전체 소스 코드#include <iostream>#include <vector>#define endl '\n'using namespace std;vector<int> v;vector<bool> check;// idx : 수열 탐색 현재 시작 위치를 알려주기 위한 변수// depth : 재귀 문이 몇번 호출 됐는지 확인하기 위한 변수// n : 수열 탐색의 마지막 위치를 확인하기 위한 값// m : 재귀 문을 최대 호출할 수 있는 횟수void nCr(int idx, int depth, int n, int m) { if (depth == m) { for (int value : v) { cout << value << " "; } cout << endl; return; } for (int i = idx; i < n; i++) { if (check[i] == true) { continue; } check[i] = true; v[depth] = i + 1; nCr(i + 1, depth + 1, n, m); check[i] = false; }}int main(void) { cin.tie(0); cout.tie(0); ios_base::sync_with_stdio(false); int n, m; cin >> n >> m; v = vector<int>(m); check = vector<bool>(n); nCr(0, 0, n, m); return 0;}

0

백준 15649 - N 과 M (1) - 순열

백준 15649 - N 과 M (1) Post not found: algorithm/baekjoon/경우의수/15649-N과M-cpp Post not found: algorithm/baekjoon/경우의수/15650-N과M-cpp 링크https://www.acmicpc.net/problem/2606 문제 풀이 주어진 N 개에서 M 개를 뽑아 나열하는 순열 문제. 백트래킹 을 이용해 만들 수 있는 모든 수열의 경우의 수 를 만들어 준다. check 를 이용해 똑같은 숫자를 여러 번 뽑는 중복 행위를 판단하고 v 배열을 통해 한 수열이 만들어지면 출력하도록 한다. v : 뽑은 숫자를 저장하기 위한 배열 check : 해당 숫자가 뽑혔는지 판단하기 위한 배열 전체 소스 코드

0

백준 1012 - 유기농 배추 (Python)

백준 1012 - 유기농 배추 (Python)링크https://www.acmicpc.net/problem/2606 전체 소스 코드def bfs(y, x): q = [] q.append([y, x]) check[y][x] = True while q: cntY, cntX = q.pop() for i in range(4): ny = cntY + dy[i] nx = cntX + dx[i] if 0 > ny or ny >= col or 0 > nx or nx >= row: continue if check[ny][nx] == False and field[ny][nx] == 1: q.append([ny, nx]) check[ny][nx] = Truetest_case = int(input())row = 0col = 0k = 0field = []check = []dy = [1, -1, 0, 0]dx = [0, 0, 1, -1]for t in range(test_case): row, col, k = map(int, input().split()) field = [[0] * row for _ in range(col)] check = [[False] * row for _ in range(col)] count = 0 for i in range(k): x, y = map(int, input().split()) field[y][x] = 1 for i in range(col): for j in range(row): if check[i][j] == False and field[i][j] == 1: count += 1 bfs(i, j) print(count)

0

백준 2606 - 바이러스 (Python)

백준 2606 - 바이러스 (Python)링크https://www.acmicpc.net/problem/2606 전체 소스 코드def bfs(start_node): q = [] q.append(start_node) check[start_node] = True count = 0 while q: node = q.pop(0) for i in range(1, node_num+1): if check[i] == False and field[node][i] == 1: q.append(i) count += 1 check[i] = True return countnode_num = int(input())line_num = int(input())field = [[0]*(node_num+1)for i in range(node_num+1)]check = [False]*(node_num+1)for i in range(line_num): a, b = map(int, input().split()) field[a][b] = 1 field[b][a] = 1print(bfs(1))

0

백준 2606 - 단지번호 붙이기 (Python)

백준 2667 - 단지번호 붙이기 (Python)링크https://www.acmicpc.net/problem/2667 전체 소스 코드def bfs(y, x): q = [] q.append([y, x]) check[y][x] = True count = 0 while len(q) > 0: count += 1 cntY = q[0][0] cntX = q[0][1] q.pop(0) for i in range(4): ny = cntY + dy[i] nx = cntX + dx[i] if 0 > ny or ny >= n or 0 > nx or nx >= n: continue if check[ny][nx] == False and field[ny][nx] != 0: check[ny][nx] = True q.append([ny, nx]) values.append(count)dy = [1, -1, 0, 0]dx = [0, 0, 1, -1]n = int(input())color = 0values = []check = [[False] * n for i in range(n)]field = [[0] * n for i in range(n)]for i in range(n): line = input() for j in range(len(line)): field[i][j] = int(line[j])for i in range(n): for j in range(n): if check[i][j] == False and field[i][j] != 0: color += 1 bfs(i, j)values.sort()print(color)for i in values: print(i)

0

MySQL - 사용자 생성

MySQL - 사용자 생성show databases; use mysql; 계정 생성 쿼리-- 내부에서만 사용할 계정 생성CREATE USER '계정 아이디'@'localhost' IDENTIFIED BY '비밀번호';-- 외부에서 사용할 계정 생성CREATE USER '계정 아이디'@'%' IDENTIFIED BY '비밀번호'; 권한 부여-- GRANT ALL PRIVILEGES ON *.* TO '계정 아이디'@'%';flush privileges;quit$$ CREATE DATABASE study_db default CHARACTER SET UTF8;

0

프로그래머스 - 양궁 대회 (Cpp)

https://programmers.co.kr/learn/courses/30/lessons/92342 프로그래머스 - 키패드누르기 Cpp 프로그래머스 - 키패드누르기 Python 유의 사항 화살을 맞춘 개수를 저장하고 정렬하는데 있어서 주의해야 한다. 정렬에 대한 가중치가 앞자리가 아닌 뒷자리 에 있으므로 값을 저장할 때 뒤집어서 저장한 후 내림 차순으로 정렬해 가장 큰 값을 가져와 해당 값을 뒤집으면 가장 낮은 점수를 많이 맞춘 순서대로 정렬된 값을 가져올 수 있다. #include <bits/stdc++.h>using namespace std;int max_diff = -1;vector<string> scores;int getValue(int idx) { return 10 - idx;}void calScore(vector<int> apeach, vector<int> ryan) { int diff = 0; int total_apeach = 0; int total_ryan = 0; for (int i = 0; i < 11; i++) { if (apeach[i] == 0 && ryan[i] == 0) { continue; } if (apeach[i] >= ryan[i]) { total_apeach += getValue(i); } else { total_ryan += getValue(i); } } if (total_ryan > total_apeach) { diff = total_ryan - total_apeach; } else { return; } string str; for (int i : ryan) { str += i + '0'; } reverse(str.begin(), str.end()); if (diff > max_diff) { max_diff = diff; scores.clear(); scores.push_back(str); } else if (diff == max_diff) { scores.push_back(str); }}void back_tracking(int depth, int idx, int n, vector<int>& apeach, vector<int>& ryan) { if (idx > 10) { return; } if (depth == n) { calScore(apeach, ryan); return; } ryan[idx] += 1; back_tracking(depth + 1, idx, n, apeach, ryan); ryan[idx] -= 1; back_tracking(depth, idx + 1, n, apeach, ryan);}vector<int> solution(int n, vector<int> info) { vector<int> answer; vector<int> ryan = vector<int>(11, 0); back_tracking(0, 0, n, info, ryan); if (max_diff == -1) { answer.push_back(-1); } else { sort(scores.begin(), scores.end(), greater<string>()); string str = scores[0]; reverse(str.begin(), str.end()); for (int i = 0; i < str.size(); i++) { answer.push_back(str[i] - '0'); } } return answer;}

0

프로그래머스 - K진수에서 소수 구하기 Python

문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/92335 프로그래머스 - K진수에서 소수 구하기 Python def is_prime(value): if value <= 1: return False for i in range(2, int(value**0.5)+1): if value % i == 0: return False return Truedef solution(n, k): answer = 0 str_value = '' stack = [] while n > 0: stack.append(n % k) n = n//k while len(stack) > 0: str_value += str(stack.pop()) sub_strs = str_value.split('0') for i in sub_strs: if i == '': continue if is_prime(int(i)): answer += 1 return answer

0

프로그래머스 - 주차 요금 계산

문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/92341 프로그래머스 - 주차 요금 계산 import mathlimit = 23*60 + 59def time_to_minute(time): times = list(map(int, time.split(':'))) return times[0] * 60 + times[1]def calCost(base_time, base_fee, per_time, per_fee, interval): if base_time > interval: return base_fee return base_fee + math.ceil((interval-base_time)/per_time)*per_feedef solution(fees, records): answer = [] fees = list(map(int, fees)) base_time = fees[0] base_fee = fees[1] per_time = fees[2] per_fee = fees[3] dict = {} time_dict = {} fee_dict = {} for line in records: words = line.split(' ') time = time_to_minute(words[0]) car_number = words[1] in_out = words[2] if in_out == 'IN': dict[car_number] = [time] else: dict[car_number].append(time) in_out_times = dict[car_number] if car_number in time_dict: time_dict[car_number] += (in_out_times[1] - in_out_times[0]) else: time_dict[car_number] = (in_out_times[1] - in_out_times[0]) for key, value in dict.items(): if len(value) == 1: if key in time_dict: time_dict[key] += (limit - value[0]) else: time_dict[key] = (limit - value[0]) for key, value in time_dict.items(): fee = calCost(base_time, base_fee, per_time, per_fee, value) if key in fee_dict: fee_dict[key] += fee else: fee_dict[key] = fee soredDict = sorted(fee_dict.items()) for value in soredDict: answer.append(value[1]) return answer