묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨대기업 근무하며 경험한 Redis를 야무지게 사용하는 방법 [이론편]
Redis의 클러스터 동작 방식 ( Hash Slot과 관련 )
강의를 들으면서 제가 아는 해시 테이블의 개념과 조금 헷갈려서 질문을 남깁니다. 일반적으로 해시 테이블은 특정한 값이 들어오면 어떤 연산을 통해 해싱을 합니다. 그리고 해싱된 값을 통해 이 데이터가 어떠한 버킷의 어떤 슬롯에 담기는지를 정하게 됩니다.그리고 여기에서 논리적으로 해시충돌이 일어나면 이를 해결할 수 있습니다. 여기에서는 데이터가 실제로 담기기 때문에 이러한 충돌이 발생할 수 있고 해결 또한 해야하죠. 근데 Redis의 클러스터에서는 어떤 데이터가 들어온다면 모듈러 연산을 통해 얻은 해시 값이 특정 노드에 속하는지를 판단한다고 강의를 들었습니다. 예) 노드 A : 0~ 4819 노드 B: 4820~16383 이 때 해싱을 통해 얻은 값이 4819라면 해당 데이터는 노드A에 속하게 되고 노드A에 연결된 DB에 데이터가 저장이 되겠죠 ?( DB의 Cluster 구동 방식을 검색해보니 각각의 노드마다 DB를 별도로 샤용한다고 했습니다. )이 때 해쉬 슬롯은 단순히 너는 노드A로 가라. 너는 노드B로 가라 라고 연결다리 역할만 하는건지 궁금합니다.실제로 해쉬 슬롯은 노드를 나누기 위한 논리적인 숫자에 불과하며 실제 슬롯에는 그 어떠한 값도 저장하고 있지 않는 것인지가 너무 헷갈립니다.. 제가 해쉬 테이블의 개념만 너무 생각해서 그런건지 잘 모르겠습니다 ..
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
안녕하세요. 실무에서 JPA 사용법
안녕하세요. 강의 잘 수강하고 있습니다. 현재 회사에서 MyBatis를 주로 사용하고 있습니다. 제가 JPA에 대한 실무 경험이 없다보니 실무에서는 어떻게 JPA를 사용하는지 궁금하여 질문을 드렸습니다. 질문제가 생각할 때 이번 프로젝트는 복잡한 부분이 없어서 단순히 연관 관계가 필요 없다고 생각하는데 복잡한 실무에서 연관관계를 사용하는지 유무가 궁금하다. (상황마다 다르겠지만 일반론 기준) 거의 모든 Repository에서 네이티브 쿼리를 사용을 하였는데 실무에서 native Query를 많이 사용하는지 궁금하며 QueryDsl은 실무에서 어떤 방식으로 사용하는 궁금합니다. ( 크게 런타임 타입 체킹이 필요가 없다면 거의 다 native Query로 풀 수 있을거 같은데 QueryDSL을 사용한 경험을 듣고 싶습니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
혹시 26분 30초 경에 대해서 추가적인 강의 찍으실 예정이실까요??
학습 관련 질문을 최대한 상세히 남겨주세요!고민 과정도 같이 나열해주셔도 좋습니다.먼저 유사한 질문이 있었는지 검색해보세요.인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.너무너무 흥미진진하게 보고 있었는데, 이 내용이 꼭 좀 있으면 좋겠습니다...!ㅠ 테이블을 분리한다면 테이블의 명칭은 각각 어떻게 네이밍 되는지.. 게시글이 1년 단위로 테이블이 분리된다고 했을떄, 테이블을 동적으로 생성하는 어떤 전략이 있는지.. (아니면 직접 1년 지날때마나 만드는 것인지) 등등.. 사소한 것부터 궁금한 것이 너무 많아서요...!
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
COUNT 테이블 Lock 관련 문의
안녕하세요.우선 니즈에 맞는 좋은 강의를 찾아서 기분이 좋네요. 감사합니다.게시글 , 댓글 , 좋아요 수 를 따로 테이블을 만들어 관리한다는 것은 처음 알게되었고 좋은 방법이라고 생각합니다.강의에서는 비관적 락, 낙관적 락을 이용해서 동시성 문제를 해결하셨는데, 실무에서도 COUNT 테이블에 비관적 락, 낙관적 락을 많이 사용하나요 ?대규모 트래픽에서는 성능 문제로 비관적 락을 잘 사용하지 않을 것 같았거든요.낙관적 락을 사용하기에는 충돌이 많을 것 같구요.(그저 제 상상입니다. ㅎㅎ;) 의견 부탁드립니다.감사합니다.
-
해결됨실전! Redis 활용
Streams 삭제 관련 질문
안녕하세요! 동현님강의 잘 듣구 있습니다~!! Streams 자료구조를 설명할 때 append-only log 에 consumer groups 과 같은 기능을 더한 자료구조라고 설명해주셨는데요.append-only log 는 데이터를 오직 추가(append)만 할 수 있는 자료구조라고 추가로 설명해주셨습니다! 그런데 xdel 같은 명령어로 이벤트를 삭제할 수 있다고 설명해주셨는데요.오직 추가만 할 수 있는 자료구조 라고 인식했는데, 갑자기 삭제 명령어가 있어서 헷갈립니다! 감사합니다.
-
해결됨실전! Redis 활용
ZSet 다이어그램 질문
안녕하세요~!zadd를 통해서 TeamC 의 score는 50으로 저장한 것 같은데, 다이어그램은 100으로 되어 있어서 질문 남깁니다!
-
미해결15일간의 빅데이터 파일럿 프로젝트
kernel:BUG 에러 관련 문의
지금 빅데이터 탐색 과정을 진행중입니.현재 3개의 가상머신 기반으로 실습중이며 server01은 가상 CPU 8개, server02와 server03는 가상 CPU 4개 그리고 메인메모리는 모두 동일하게 16기가씩 할당하였습니다.그럼에도 불구하고 리소스가 부족한지 server01가상머신에서 아래와 같은 에러가 발생하며 진도가 잘 나가지 못하는 상황입니다.kernel:BUG: soft lockup - CPU#0 stuck for 951s!혹시 상기 에러와 관련하여 조언이 있으실지 문의드립니다.감사합니다.
-
미해결15일간의 빅데이터 파일럿 프로젝트
Oozie설치시 ShareLib업로드 에러
안녕하세요?이젠 또 Oozie설치에서 문제가 생겼습니다. 이슈는 ShareLib업로드 관련 에러이며 몇번이나 시도했지만 동일한 에러가 지속적으로 빌생해서 문의드리며 스크린샷은 아래에 추가하였습니다.조언부탁드리며 감사합니다.
-
미해결15일간의 빅데이터 파일럿 프로젝트
Hue 설치시 python27패키지를 찾을 수 없음
안녕하세요? 강의를 보면서 레포설정은 문제없이 된 것 같은 데 No package python27 available.라는 에러가 자꾸 뜨고 설치가 진행이 되지 않다보니 여기 발목이 잡힌 상태입니다. 아래에 스크린샷을 주가했습니다.이상한건 레포지토리 검색을 해 보면 scl관련 레포지토리는 안보이는데 이게 정상인지요?그럼 지도편달 부탁드립니다.감사합니다.
-
해결됨실습으로 배우는 선착순 이벤트 시스템
강사님 강의를 듣고 실제 프로젝트에서 이벤트 응모 시스템을 만들어 봤습니다.
안녕하세요 강사님!강사님의 동시성 이슈와 선착순 이벤트 시스템 강의를 듣고 실제 프로젝트에서 이벤트 응모 시스템을 만들어 봤습니다. 아래는 제가 해당 이벤트 응모 시스템을 만들면서 겪었던 이슈와 고민을 블로그 글로 적었습니다.우선 강사님 덕분에 프로젝트 잘 끝낼 수 있어서 감사했습니다.블로그 글을 쓰면서 든 생각은 여기서 더 개선 시킬점은 없을까? 좀 더 고민 해볼만한 부분은 없을까? 라는 생각이 들었습니다.개발에 정답은 없지만 그래도 좋은 방향은 있다고 생각해서 최근에 제가 쓴 글을 다시 보면서 어떤 부분을 고치면 좋을까 라는 생각을 하고 있습니다.혹시 강사님께서 제 글을 보시고 만약 면접관이시라면 어떤식으로 질문이 들어올 수 있을지 특히 꼬리 질문에 대해 얘기를 해주실 수 있을까요 해주신 내용을 바탕으로 깊게 고민을 해보고 면접 대비도 하고 싶습니다.
-
해결됨실전! Redis 활용
안녕하세요 Pub/sub과 분산 락에 대해 질문이 있습니다.
안녕하세요 강사님 우선 아래 질문한 내용에 대해 구글에서 이것저것 찾아보고 GPT도 다 돌려봤는데 도저히 이해가 안가서 강사님께 여쭤봅니다.강의에서 분산 락과 Pub/Sub 개념을 복습한 후, 이전에 Redisson을 사용해 구현했던 분산 락 로직을 정리하고 있습니다. 그 과정에서 RedissonLock 클래스의 tryLock 메서드를 살펴보다가 PublishSubscribe 클래스의 subscribe 메서드까지 코드를 따라가게 되었습니다.이와 관련하여 다음 몇 가지 질문이 생겼습니다:PublishSubscribe 클래스의 subscribe 메서드를 보면 세마포어를 사용하는데, 여기서 세마포어의 역할이 무엇인지 잘 이해가 되지 않습니다. 왜 이 시점에서 세마포어를 사용하는 건가요?CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId); 코드에서 threadId로 무언가를 구독합니다. 정확히 무엇을 구독하는지 잘 모르겠습니다. 구독 대상과 구독의 목적이 무엇인지 궁금합니다.tryLock 메서드의 아래쪽 코드를 보면 while (true)로 락을 반복적으로 시도하는 모습이 마치 스핀락처럼 보입니다. 저는 Redisson의 분산 락이 Lettuce의 스핀락과는 다르다고 생각했는데, 실제 구현을 보니 스핀락과 비슷한 방식으로 동작한다고 봐도 될까요?RedissonLock 클래스의 tryLock 메서드 @Override public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException { long time = unit.toMillis(waitTime); long current = System.currentTimeMillis(); long threadId = Thread.currentThread().getId(); Long ttl = tryAcquire(waitTime, leaseTime, unit, threadId); // lock acquired if (ttl == null) { return true; } time -= System.currentTimeMillis() - current; if (time <= 0) { acquireFailed(waitTime, unit, threadId); return false; } current = System.currentTimeMillis(); CompletableFuture<RedissonLockEntry> subscribeFuture = subscribe(threadId); try { subscribeFuture.get(time, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { if (!subscribeFuture.cancel(false)) { subscribeFuture.whenComplete((res, ex) -> { if (ex == null) { unsubscribe(res, threadId); } }); } acquireFailed(waitTime, unit, threadId); return false; } catch (ExecutionException e) { acquireFailed(waitTime, unit, threadId); return false; } try { time -= System.currentTimeMillis() - current; if (time <= 0) { acquireFailed(waitTime, unit, threadId); return false; } while (true) { long currentTime = System.currentTimeMillis(); ttl = tryAcquire(waitTime, leaseTime, unit, threadId); // lock acquired if (ttl == null) { return true; } time -= System.currentTimeMillis() - currentTime; if (time <= 0) { acquireFailed(waitTime, unit, threadId); return false; } // waiting for message currentTime = System.currentTimeMillis(); if (ttl >= 0 && ttl < time) { commandExecutor.getNow(subscribeFuture).getLatch().tryAcquire(ttl, TimeUnit.MILLISECONDS); } else { commandExecutor.getNow(subscribeFuture).getLatch().tryAcquire(time, TimeUnit.MILLISECONDS); } time -= System.currentTimeMillis() - currentTime; if (time <= 0) { acquireFailed(waitTime, unit, threadId); return false; } } } finally { unsubscribe(commandExecutor.getNow(subscribeFuture), threadId); } // return get(tryLockAsync(waitTime, leaseTime, unit)); }PublishSubscribe 클래스/** * Copyright (c) 2013-2022 Nikita Koksharov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.redisson.pubsub; import org.redisson.PubSubEntry; import org.redisson.client.BaseRedisPubSubListener; import org.redisson.client.ChannelName; import org.redisson.client.RedisPubSubListener; import org.redisson.client.codec.LongCodec; import org.redisson.client.protocol.pubsub.PubSubType; import org.redisson.misc.AsyncSemaphore; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * * @author Nikita Koksharov * */ abstract class PublishSubscribe<E extends PubSubEntry<E>> { private final ConcurrentMap<String, E> entries = new ConcurrentHashMap<>(); private final PublishSubscribeService service; PublishSubscribe(PublishSubscribeService service) { super(); this.service = service; } public void unsubscribe(E entry, String entryName, String channelName) { AsyncSemaphore semaphore = service.getSemaphore(new ChannelName(channelName)); semaphore.acquire().thenAccept(c -> { if (entry.release() == 0) { entries.remove(entryName); service.unsubscribe(PubSubType.UNSUBSCRIBE, new ChannelName(channelName)) .whenComplete((r, e) -> { semaphore.release(); }); } else { semaphore.release(); } }); } public void timeout(CompletableFuture<?> promise) { service.timeout(promise); } public void timeout(CompletableFuture<?> promise, long timeout) { service.timeout(promise, timeout); } public CompletableFuture<E> subscribe(String entryName, String channelName) { AsyncSemaphore semaphore = service.getSemaphore(new ChannelName(channelName)); CompletableFuture<E> newPromise = new CompletableFuture<>(); semaphore.acquire().thenAccept(c -> { if (newPromise.isDone()) { semaphore.release(); return; } E entry = entries.get(entryName); if (entry != null) { entry.acquire(); semaphore.release(); entry.getPromise().whenComplete((r, e) -> { if (e != null) { newPromise.completeExceptionally(e); return; } newPromise.complete(r); }); return; } E value = createEntry(newPromise); value.acquire(); E oldValue = entries.putIfAbsent(entryName, value); if (oldValue != null) { oldValue.acquire(); semaphore.release(); oldValue.getPromise().whenComplete((r, e) -> { if (e != null) { newPromise.completeExceptionally(e); return; } newPromise.complete(r); }); return; } RedisPubSubListener<Object> listener = createListener(channelName, value); CompletableFuture<PubSubConnectionEntry> s = service.subscribeNoTimeout(LongCodec.INSTANCE, channelName, semaphore, listener); newPromise.whenComplete((r, e) -> { if (e != null) { s.completeExceptionally(e); } }); s.whenComplete((r, e) -> { if (e != null) { value.getPromise().completeExceptionally(e); return; } value.getPromise().complete(value); }); }); return newPromise; } protected abstract E createEntry(CompletableFuture<E> newPromise); protected abstract void onMessage(E value, Long message); private RedisPubSubListener<Object> createListener(String channelName, E value) { RedisPubSubListener<Object> listener = new BaseRedisPubSubListener() { @Override public void onMessage(CharSequence channel, Object message) { if (!channelName.equals(channel.toString())) { return; } PublishSubscribe.this.onMessage(value, (Long) message); } }; return listener; } } 감사합니다.
-
해결됨실전! Redis 활용
분산 락에 대해 질문 있습니다.
이전에 분산 락을 구현해본 경험이 있습니다.그때는 간단하게 구현을 하다보니 분산 락에 대해 꼬리 질문이 들어 온다면 어떤 질문들이 들어올지 궁금합니다.강사님께서 생각하시기에 분산 락 관련하여 질문을 한다면 혹시 어떤 식으로 질문을 하실지 궁금합니다.
-
미해결15일간의 빅데이터 파일럿 프로젝트
머하웃 추천 ml 실행 안됨
안녕하세요! 머하웃에서 실행하는 추천 잡이 실행이 안되어서 질문 남깁니다..! 제가 시도한 방법은 다음과 같습니다휴에서 보이는 잡들 모두 제거하고 실행클라우데라에서 클러스터1을 재시작하고 실행우지를 종료하고 실행이 방법들로는 해결되지 않았습니다.. 어찌해야 할 지 모르겠어 질문 남깁니다..!!
-
미해결15일간의 빅데이터 파일럿 프로젝트
Storm관련 NoClassDefFoundError문의
현재 실시간 데이터 수집부분에서 Storm Topology를 배포하는 단계에서 다음의 스크린샷과 같은 에러가 발생하였습니다. 참고로 저는 storm 버전 0.9.7을 설치하여 실습을 진행중이며 에러 관련 스크린샷은 아래와 같습니다.어떻게 해결하면 좋을지 문의드립니다. 제공하여주신 jar파일에 의존성을 추가해서 해당 의존성을 다운로드해야 할 지 아니면 스톰의 버전을 정확하게 맞추어야 할 지 고민이 되어서 문의드립니다. 감사합니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
메시지 이벤트 발행시 에러 발생 관련 질문이 있습니다.
이번에 면접을 보면서 확실하게 대답을 못해서 고민 끝에 선생님에게 질문 드립니다. 우선 시나리오 말씀드리자면 client 가 해당 게시글에 "좋아요" 등록을 하게 된다면 좋아요 등록 관련 DB 테이블에 insert 동시에 outbox 테이블에도 insert 하도록 설계 되어 있습니다. commit 이 정상적으로 발생되면 kafka 서버에게 이벤트 메시지를 발행 하게 되는데요. 만약 갑자기 이벤트 발행시 kafka 서버가 죽었다고 하면 복구 될때 까지 기다리다가 retry 통해 아직 메시지 발행 하지 못한 메시지 outbox 테이블에 조회해서 메시지 발행 하면 문제가 없을 것 같은데요. 하지만 다시 처음부터 설명하면 client 가 좋아요 등록 후 DB 서버가 죽어서 "좋아요" 관련 테이블 및 "outbox" 테이블에 insert 를 못했다고 가정 했을때 어떻게 대처 해야 하는지 역으로 질문 받았습니다. 일단 DB 서버가 죽었으면 빠르게 고객에게 에러 메시지를 전달과 동시에 담당 개발자에게 빠르게 전달 할 수 있도록 전달 해야 한다고 했습니다. (회사에서 slack 메신저 사용하면 메신저 통해 알림) 혹시 이것보다 더 좋은 방법이 있을까요? 재대로 대답하지 못해 찜찜해서 이렇게 선생님에게 질문 드리네요.
-
해결됨개발자라면 알아야 할 redis 기본
레디스 pub/sub 질문
안녕하세요 강의 잘 듣고 있습니다제가 현재 채팅 프로그램을 만들고 있는데 채팅 서버가 하나이면 굳이 레디스를 사용할 필요가 없겠네요?
-
미해결15일간의 빅데이터 파일럿 프로젝트
5. 빅데이터 클러스터 구성2- CM 소프트웨어 설치 오류
안녕하세요, 선생님. Cloudera Manager 소프트웨어 설치 중 오류가 해결되지 않네요. 도움 부탁드려요! 오류 내용입니다.
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
실무에서의 락
안녕하세요. 현재 좋아요 부분에서 락에 관련해서 강의를 듣고 있습니다. 궁금한 점은 실무에서는 어떻게 사용을 하시는지 궁금합니다.왜냐하면 대부분 실무에서는 테이블 자체를 논리적 외래키로 전부 가져가는 경우를 많이 봤었습니다.외주를 부탁한 외부 업체 또한 낙관적 락을 사용하는 케이스를 봤구요. 강사님께서 일하시는 곳에서는 락의 3가지 케이스를 다양하게 필요에 맞게 사용하는 건가요?!
-
해결됨스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판
안녕하세요! 테스트 질문입니다
강의에서는 인기글을 테스트할때 DataInitializer클래스에서 아래와 같은 코드를 사용했습니다. void createComment(Long articleId, long commentCount) { while(commentCount-- > 0) { commentServiceClient.post() .uri("/v1/comments") .body(new CommentRequest.Create(articleId, "content",null, 1L)) .retrieve(); } }이렇게 사용해봤더니 카프카에 전달이 되지 않더라구요 void createComment(Long articleId, long commentCount) { while (commentCount-- > 0) { CommentRequest.Create request = new CommentRequest.Create(articleId, "content", null, 1L); try { // 요청 로깅 추가 ObjectMapper objectMapper = new ObjectMapper(); System.out.println("Request body: " + objectMapper.writeValueAsString(request)); commentServiceClient.post() .uri("/v1/comments") .body(request) .retrieve() .toBodilessEntity(); // 응답 처리 추가 } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }이렇게 사용해야 인기글 서비스에서 아래처럼 로그가 찍히는걸 확인했습니다. 어디를 확인해야할까요 .. 몇시간째 해결을 못해서 질문드려요!![HotArticleEventConsumer.listen] received message = {"eventId":136009554918850560,"type":"COMMENT_CREATED"
-
미해결15일간의 빅데이터 파일럿 프로젝트
리듀스가 네트워크를 타고 들어오는 경우
안녕하세요. 열강해주셨던 강의 들으며 공부하다 질문이 있어 글 남깁니다. 스파크에 대한 설명에서 '그리고 이 리듀스가 네트워크를 타고 들어온 로컬에 떨어진 앞에 리듀스의 결과를 다시 또 로컬로 떨어뜨린다'는 설명이 있었는데, 이 설명이 어떤 경우가 있는지 감이 잘 안와서 질문드립니다. 리듀스가 네트워크를 타고 들어온다는 것이 어떤 상황을 말하는건가요..? 감사합니다.