묻고 답해요
140만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Cache Aside + Write Around 전략에서 궁금한 점이 있습니다~
Cache Aside 전략이redis에 원하는 데이터가 있는지 확인있으면 해당 데이터로 응답없으면 db에서 조회 후 응답 + 레디스에 해당 데이터 저장 그런데 Write Around 전략에서 쓰기(조회를 제외한) 작업의 경우redis에 반영하지 않고, DB에만 반영하는데특정 데이터가 Cache Aside 전략에 따라 db에서 조회되어 응답 후 redis에도 해당 데이터가 저장되어 있는 상태라면,해당 데이터를 수정하는 작업을 하게 될 경우redis에는 반영하지 않고 db에만 반영하게 되면만약 해당 데이터를 조회하려고 할 때 Cache Aside 전략에 의하면 가장 먼저 redis에 해당 데이터가 있는지 확인하는데 여기서 redis에 존재하니까 redis의 데이터로 응답을 해주면 db에 있는 원본 데이터는 수정되어 있으니 데이터 정합성 문제가 생기는 것 아닌가요? 감사합니다!!
-
미해결실전! Redis 활용
레디스 사용관련 질문
레디스 데이터 타입 별 사용방법 많은 도움이 되었습니다. 그러다 궁금한것이 있습니다. Q. 사이드 프로젝트로 쇼핑몰을 만드려고 합니다 프론트: 리액트 벡엔드 api서버: 스프링부트2.8 api서버에 레디스를 연결해 최근 검색어 캐싱 + 구매에 의한 재고 감소 동시성 처리를 하려고 합니다. 이때 벡엔드 api 서버(스프링부트)에 레디스를 연결하는게 맞나요 아니면 별도의 서버를 하나 더 구축해 레디스를 연결하는게 맞나요?? 사이드 프로젝트인 상황에 맞게 어떻게 하는게 바람직한지 궁금합니다
-
미해결실습으로 배우는 선착순 이벤트 시스템
kafka Producer 실행 중 에러 시 redis count 정합성 이슈
안녕하세요! 섹션3 Producer 관련 강의를 보다가 궁금한 점이 생겼습니다. redis를 활용해 count 증가 후 선착순에 들어 kafka 로 이벤트를 발행하는 도중 네트워크 오류 등의 문제가 발생한다면 count 값만 늘어나고 쿠폰 생성이 안될 것 같습니다. 이 경우, 실무에서는 어떤 식으로 처리하시나요??(redis쿼리 -> kafka 이벤트 발행)의 원자성을 보장해줘야 될 것 같다는 생각이 들었습니다.kafka의 이벤트 발행 부분을 try...catch로 감싸서 redis의 count를 감소시키는 로직을 작성하는게 가장 간단해보입니다.그런데, 해당 롤백 로직에서 에러가 발생할수도 있기 때문에 카운트 증가 -> 이벤트 발행의 원자성을 보장하기 어려울 것 같습니다. 추가) kafka 이벤트 발행 실패 시 userId, eventId, count 값을 로그로 남겨 추후 kafka 이벤트를 재발행하는 방법도 있을 것 같습니다.이때, 재실행은 로그에서 데이터를 추출 개발자가 수동 혹은 배치 등의 프로그램을 작성해 정합성을 맞추는걸까요?? 실무에서 어떤 식으로 실패한 요청을 다시 성공시키는지 궁금합니다
-
미해결15일간의 빅데이터 파일럿 프로젝트
Zeppelin 쿼리 도중 fb303 에러
안녕하세요. Zeppelin 노트북을 통해, 쿼리를 날리는 실습을 하고 있습니다. SHOW TABLES 등과 같은 쿼리는 잘 작동하고 있습니다.하지만, 몇몇 테이블에 대해 아래와 같이 접근을 시도하면 그 이후 모든 쿼리가 작동하지 않습니다.예를들어 3개의 테이블이 있다고 하면, managed_smartcar_drive_info1managed_smartcar_drive_info2managed_smartcar_drive_info3 managed_smartcar_drive_info1 에 대해SELECT * FROM managed_smartcar_drive_info1 LIMIT 10은 몇 번을 시도하여 잘 되지만, SELECT * FROM managed_smartcar_drive_info2 LIMIT 10혹은SELECT * FROM managed_smartcar_drive_info3 LIMIT 10에 대해 시도하면 fb303 에러가 뜨고 있습니다. 그 후 SELECT * FROM managed_smartcar_drive_info1 LIMIT 10를 다시 실행하면, 동일하게 에러가 발생합니다. putty를 통한 HIVE, HUE를 통한 임팔라와 하이브에서 모두 정상적으로 작동하지만, Zeppelin에서만 문제가 발생하고 있습니다. restart를 하여도, 기존에 정상 작동하던 테이블 및 쿼리만 정상작동하며, 오류를 야기하는 테이블 및 쿼리는 다시 시도해도 동일한 결과가 나오고 있습니다. thrift, fb303모두 종속성을 설정해도 잘 안되는 것 같습니다 ㅠㅠ
-
미해결실습으로 배우는 선착순 이벤트 시스템
test 과정에서 오류가 발생합니다.
코드는 3번정도 체크해서 강의 내용과 같은 방식으로 작성하였습니다.db는 mysql>maria로만 바꿨습니다.앞에서 질문들에서 나왔던 것처럼 숫자가 출력되지않는 현상이 발생합니다.https://github.com/zhzkal2/coupon_study혹시몰라서 깃 코드도 올려둡니다.환경은 윈도우 환경이라서docker-compose 로 세팅했어요.도커데스크탑에서 consumer생성을 했고인텔리제이 kafka 플러그인으로 컨슈머랑 토픽 둘다 확인했습니다.
-
해결됨실전! Redis 활용
Rate Limiter 예제에 대해 질문있습니다!
Rate Limiter 강의 그림으로 된 예제에 대해 질문있습니다!트랜젝션 시작을 알리는 "MULTI" 명령어 이후 "EXPIRE 1.1.1.1:10 60 / EXEC" 코드가 있습니다! 제가 잘못 이해한 걸 수도 있지만, 이렇게 하면 요청마다 만료 시간이 다시 1분으로 초기화되는 것이 아닌지 궁금합니다. 그러면 1분 안에 요청 수를 제한하는 것이 아니라 1분 안에 요청이 없으면 만료되는 형식이 될 것 같은데 제가 생각한 것이 맞을까요?
-
미해결실습으로 배우는 선착순 이벤트 시스템
도커 환경설정에 대해서
위 오류가 발생하고스택오버플로우중국 플랫폼 사이트 갓대희님 블로그 등 모든 사이트를 찾아보았으며,하이퍼 바이저 실행여부, svm 실행 여부, wsl 재설치, 도커 데스크탑 버전이슈도 있었으므로 버전 변경 등 할수있는 모든 방법을 전부 실행하였으나 해결되지 않았습니다.도커 데스크탑을 사용하지 않고 진행하는 방법이 있는지 궁금합니다. 현재 제 윈도우 11 21h2 환경에서는 도커데스크탑의 설치가 불가하다고 판단이 되는데 수업에 대해서 진행이 가능한지 궁금합니다.
-
해결됨하루만에 배우는 AWS REDIS
강사님께서 보고있는 파일은 어디서 볼 수 있나요?
다음과 같은 양식으로 남겨주세요.질문을 한 배경 : 자료가 어디있는지 못찾겠습니다질문내용 : 강사님이 보고계신 AWS Serverless 파일은 어디서 볼 수 있나요?
-
미해결15일간의 빅데이터 파일럿 프로젝트
듣고있는 와중에 질문있습니다.
이 과정은 가이드 주시는데로 모든 프로그램을 다운받고 같이 따라해야 이수되는 교육인가요? 자바 다운로드에 들어가도 알려주신 버젼 대비 훨씬 더 업데이트 된 버전만 가능한 것 같네요. 꼭 정확하게 일치된 버젼을 설치해야 하는지요?
-
미해결실전! Redis 활용
Bitmap - User Online Status(온라인 상태 표시)에 질문 드립니다.
사용자가 온라인 된 경우 1로 bit를 업데이트 하고이후에 통신이 되지 않으면 비트값이 추가로 업데이트 되지 않는다 설명하셨는데그 사이에 어떤 동작으로 통신이 되지 않는지 여부를 확인하는지, 비트는 어떻게 처리되는지에 대한 설명이 없어 이해가 어렵네요.매 분마다 요청이 온다는 가정하에 비트값을 매분마다 1씩 업데이트 하는데, 해당 요청이 없어서 비트값이 더 이상 업데이트 하지 않게 되면, 해당 시간만큼 오프라인 상태였다이 시나리오가 맞을까요?그렇다면 서버에서 임의의 시간, 예시로 3분 이상 미 접속시 오프라인이라 평가하여 커뮤니티 웹, 온라인 게임이나 채팅 등의 사용자의 온라인 여부가 필요한 서비스에서 해당 값을 참고하여 특정 시간에서 부터 bit 증가가 없다면 오프라인이라 평가하게 된다고 보면 될까요?그런데 이렇게 하면 시:분으로 시작하는 key로 부터 bit는 접속하게 되는 분 단위가 되는거고, 다른 사용자가 이 사용자의 온라인 상태를 알고자 한다면, 현재 시간에서 key와 bit를 연산한 시간을 비교해야 온라인인지 여부를 알 수 있게 되는건데 제가 이해하고 있는게 맞는지 알고 싶습니다.
-
미해결실전! Redis 활용
Hash - Login Session(로그인 세션)에 대해 질문 드립니다.
해당 클래스의 주된 내용은 동시 로그인 제한으로 이해를 했습니다.그런데 설명을 해주시는 부분에 있어서 set-cookie 부분에서 부터 이해가 잘 되지 않네요.먼저 설명 부분에 있어서set-cookie로 session id를 보내고갑자기 결제가 필요한 유료 api에 접근을 요청하고redis의 캐시에서 해당 유저가 프리미엄 등급임을 확인하고유료 api 요청을 처리한다 하셨는데동시 로그인 제한이라면 pc나 모바일 등 여러 장비에서 접속하는 session의 처리를 의미하는거라 생각이 됩니다.그리고 redis의 캐시로 프리미엄 등급을 확인한다는것도 이해가 되지 않는게 해당 데이터는 캐시로 다뤄질 데이터가 아니지 않나요?초반 설명하셨던 동시 로그인 제한이란 소주제의 목적이다이어그램을 통해 설명한 내용과 다른것 같습니다.혹시 제가 이해한게 잘못된 것인지 알고 싶습니다.n(로그인 세션)
-
해결됨실전! Redis 활용
String - Fixed Window Rate Limiter(비율 계산기) 에 질문 드립니다.
1.1.1.1:10 으로 key가 만들어 졌을 때, 만료가 11분이 되는건가요?설명에는 10분에서 11분까지로 알려주시던데20이라는 요청 제한 수는 프로그램에서 관리하는 수가 되는거죠?다이어 그림에 expire 1.1.1.1:10 60 / exec 의 의미는 무엇인가요?
-
해결됨실전! Redis 활용
Sorted Sets에 대해 질문 합니다.
ZRANGE points 0 -1 REV WITHSCORES위 명령어를 입력하면 ERR syntax error가 발생합니다.gpt로 확인하니 ZREVRANGE points 0 -1 WITHSCORES를 제시해주고결과도 역순으로 출력이 됩니다.rev 지원이 안되는거 같은데 버전의 차이 등의 이슈가 있는 것인지 알고 싶습니다.
-
미해결실습으로 배우는 선착순 이벤트 시스템
Redis의 INCR 사용 해도 Race condition이 잡히지 않는 문제
안녕하세요! 강사님 덕분에 현재 진행중인 프로젝트 코드에 동시성 문제 잘 적용하고 있습니다. 다름이 아니라, 현재 MSA 프로젝트를 하고 있어 쿠폰 쪽 DB는 쿠폰만 쓰기 때문에 부하에 따른 걱정은 덜어도 될 것 같아 카프카가 아닌 Redis의 INCR 명령어를 통해서 선착순 쿠폰 로직의 Race condition 문제를 잡아보려고 하고 있는데요.질문에 앞서 프로젝트 환경을 말씀드리자면 강의와 동일하게 docker pull redis 해서 이미지로 다운받아 실행했고, 6380 포트로 연결해줘서 yml 설정과 Config 설정 또한 해줬습니다. INCR 키 값을 살짝 바꿔서 coupon_count:{couponId} 가 되도록 해줬습니다. 문제는 1000개의 쓰레드로 요청을 날렸을 때 여러번의 요청 테스트는 통과가 안된다는 점입니다.. 쿠폰 발급이 100개 되어야하는데 102, 103번 애매하게 되고 있습니다. (postman으로 API 요청 날릴 때마다 해당 키 값의 value가 1씩 잘 증가하는 것은 확인했습니다) RDB 상에서도 100개의 발급 내역이 잘 들어오고 있구요. (물론 테스트가 DB에 영향을 미치면 안되지만요ㅠㅠ)이런 경우는 왜 그런건가요?? 코드도 첨부 하겠습니다. 감사합니다!!/* * 선착순 쿠폰 발급 */ @Transactional public CouponIssuedResponseDto issueFirstComeCoupon(CouponIssuedRequestDto request) { // 쿠폰 ID로 쿠폰을 찾고, 존재하지 않으면 예외 처리 Coupon coupon = couponRepository.findById(request.couponId()) .orElseThrow(() -> new CustomException(ErrorCode.COUPON_NOT_FOUND)); // 발급 가능한 쿠폰 수량 확인 -> Redis Long currentCount = couponCountRepository.getCount(request.couponId()); if (currentCount > coupon.getMaxQuantity()) { throw new CustomException(ErrorCode.COUPON_ISSUE_LIMIT_EXCEEDED); } // 새로운 쿠폰 발급 -> Redis에서 수량 증가 Long newCount = couponCountRepository.increment(request.couponId()); if (newCount > coupon.getMaxQuantity()) { throw new CustomException(ErrorCode.COUPON_ISSUE_LIMIT_EXCEEDED); } CouponIssued issued = CouponIssued.builder() .coupon(coupon) .userId(request.userId()) .issuedAt(LocalDateTime.now()) .build(); CouponIssued saved = couponIssuedRepository.save(issued); return CouponIssuedResponseDto.fromEntity(saved); }@Repository public class CouponCountRepository { private final RedisTemplate<String, Long> redisTemplate; public CouponCountRepository(RedisTemplate<String, Long> redisTemplate) { this.redisTemplate = redisTemplate; } public Long increment(Long couponId) { String key = "coupon_count:" + couponId; return redisTemplate.opsForValue().increment(key, 1); } public Long getCount(Long couponId) { String key = "coupon_count:" + couponId; Long count = redisTemplate.opsForValue().get(key); return count != null ? count : 0L; } }@BeforeEach public void setUp() { // Redis 초기화 redisTemplate.opsForValue().set("coupon_count:10", 0L); } @AfterEach public void tearDown() { couponRepository.deleteAll(); couponIssuedRepository.deleteAll(); redisTemplate.delete("coupon_count:10"); // 테스트 끝난 후 Redis 데이터 삭제 } @Test public void multipleUserIssueCoupon() throws InterruptedException { // Given // 쿠폰을 생성 Coupon coupon = Coupon.builder() .name("Test Coupon") .couponCode("TEST100") .discountRate(10) .maxQuantity(100L) .issuedQuantity(0L) .expiresAt(LocalDateTime.now().plusDays(30)) .couponType(CouponTypeEnum.FIRST_COME) .build(); couponRepository.save(coupon); Long couponId = coupon.getCouponId(); // 고정된 couponId 사용 Long userId = 1L; // 고정된 userId 사용 // When int threadCount = 1000; ExecutorService executorService = Executors.newFixedThreadPool(50); CountDownLatch latch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { executorService.submit(() -> { try { CouponIssuedRequestDto request = new CouponIssuedRequestDto(10L, userId); couponIssuedService.issueFirstComeCoupon(request); } catch (CustomException e) { // Expected exception when limit is exceeded } finally { latch.countDown(); } }); } latch.await(20, TimeUnit.SECONDS); // Then Long count = redisTemplate.opsForValue().get("coupon_count:10"); System.out.println("coupon_count:10 = " + count); // 디버깅용 로그 추가 assertThat(count).isNotNull(); // count가 null이 아닌지 확인 assertThat(count).isEqualTo(100); // 발급된 쿠폰의 수를 확인 long issuedCount = couponIssuedRepository.count(); assertThat(issuedCount).isEqualTo(100); }
-
미해결15일간의 빅데이터 파일럿 프로젝트
회귀분석 관련 질문 드립니다.
R을 이용한 회귀분석 강의에서 smartcarMaster2Income에 있는 capacity를 feature로 income이라는 lable을 예측하는 것으로 이해했는데 분석에 사용된 데이터를 통해 얻은 모델을 검증하는 과정에서 Test파일을 가지고 predict를 하고나서 동일한 파일과 비교를 하는게 잘 이해가 되지 않아서 질문 드립니다. 모델을 검증?추론?할때는 lable값이 없는 데이터를 넣고 그 결과가 실제데이터(test파일)과 얼마나 가까운지를 확인하는 것이 아닌가요?
-
미해결실습으로 배우는 선착순 이벤트 시스템
카프카 토픽 생성오류
https://www.inflearn.com/questions/1126638 위의 링크와 같이 저도 토픽 생성이 안되는데요환경은Mac M2 환경입니다.
-
미해결실습으로 배우는 선착순 이벤트 시스템
redis 를 사용하여 문제점 해결하기
redis 를 사용하여 문제점 해결하기 7:25 의 도표를 보고있습니다.Thread - 1 이 실행이 end - 10:02 가 되면 Thread - 2 가 start - 10 : 02 가 되고 incr coupon_count 가 된다고 나와있습니다. 동기식으로 돌아가게 되면 , 속도적인 측면에서 괜찮을까요 ?? 만약에 사용자가 동시다발적으로 쿠폰 발급을 클릭하게 되면 동기식으로 했을때 괜찮을까요 ??
-
미해결실습으로 배우는 선착순 이벤트 시스템
프로젝트셋팅
안녕하세요 강의 잘 듣고있습니다.설정 하실때 ,api 와 consumer 두개로 나눠서 하셨는데 ,하나의 src 밑에 있는 프로젝트로 진행을 할수가 있을까요 ?? 코드를 봤는데 중복된게 많아서 api 와 consumer 로 나누지 않고 하나의 src 밑에서 작성해도 되지않을까 생각했습니다.
-
미해결실습으로 배우는 선착순 이벤트 시스템
test 오류 발생하는 분들을 위한 해결 방법!
test를 돌릴 때, kafka consumer가 반응을 하지 않으면 이전 테스트에서 사용한 값 때문일 수도 있습니다! 저 같은 경우는 테스트가 순식간에 끝나버려서 의심을 했는데요.redis-cli에 접속하신 뒤 `flushall` 명령어를 친 뒤에 테스트를 진행해보시면 해결 됩니다!
-
해결됨실전! Redis 활용
데이터 타입 활용 - 온라인 상태 표시 [Bitmap] 관련 질문
안녕하세요. 강의를 잘 보고 있는 와중에 온라인 상태 표시 관련한 궁금증이 생겨서 질문을 남기게 됐습니다. (※ 다른 분이 남겨주신 온라인 상태 표시 질문 글도 읽었습니다.) Bitamps의 장점은 하나의 key에서 offset을 사용하여 값을 비트별로 나눠서 읽고 쓰기 때문에 적은 메모리와 빠른 비트 연산을 제공한다고 생각이 되는데요.올려주신 예시를 보면 key는 계속해서 바뀌고 있고, offset도 전혀 사용하지 않는 것 같습니다.해당 상황에서도 일반적인 Strings 대신에 Bitamps를 쓰신 특별한 이유가 있는지 궁금합니다.