묻고 답해요
137만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
Cacheable key값 설정에서 null
@Cacheable(cacheNames = "getBoards", key = "'boards:page:' + #page + ':size:' + #size", cacheManager = "boardCacheManager") public List<Board> getBoards(int page, int size) { Pageable pageable = PageRequest.of(page - 1, size); Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable); return pageOfBoards.getContent(); } }여기서 key = "'boards:page:' + #page + ':size:' + #size"레디스에 저장되는 키값은 "getBoards::boards:page:null:size:null" 이렇게 저장이 됩니다. 혹시 null이 들어가는 이유가 있을까요? page와 size의 데이터도 잘 넘어오고 레디스에서 저 키값으로 조회를 하면 안에 데이터는 잘 들어가 있습니다. #page와 #size가 null인 이유가 있을까요?
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
파라미터에 있는 값이 아닌 외부에 있는 값을 캐시 key에 넣을 수 있나요?
파라미터에 있는 값이 아닌 외부에 있는 값을 캐시 key에 넣을 수 있나요?
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
CacheManager 는 한 번만 등록하나요? 아니면 각 도메인마다 등록하나요?
안녕하세요, 좋은 강의 감사합니다. Spring Boot 에서 Redis 세팅 추가하는 편에서, CacheManager 를 하나만 등록해서 사용하고 있습니다. 그리고 이를 활용하는 API 가 1개 뿐인데, 이름이 boardCacheManager 로 정확히 Board 도메인에 대한 전용 CacheManager 인 것처럼 보입니다. 도메인 별로 CachaManager 를 각각 만들면서 사용을 하는 게 좀 더 바람직한 방법인가요?만약 그렇다면, 각 도메인 별로 설정을 관리하고 유지보수성을 높이기 위함인가요?만약 CachaManager 를 도메인 별로 값이나 타입을 다르게 적용하지 않고 프로젝트 전체에 대해서 동일하게 적용을 하기로 결정했다면, 그때에도 CacheManager 를 각각 적용해야 할 이유가 혹시 있을까요? 인터넷 기사나 블로그 등에서는 이렇게도 하고 저렇게도 하는 것 같습니다. 선생님의 의견이나 또 실무 상의 고려사항이 있는지 궁금합니다.
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
windows 에서 설치하는 분들, Permission denied 에러가 나는 경우 참고해주세요
windows 실습 환경에서 admin 계정이 아닌 경우에는 기본적으로 .rdb 파일에 대한 권한이 읽기만 설정되어 있는 것 같습니다.그런데, redis 자체가 .rdb 에 대한 snapshot 생성을 시도하려고 하는데 이때 쓰기 권한이 없어서 예외를 발생시킵니다. 처음 실습할 때는 (어차피 본격적으로 쓰는 건 Linux 에서 쓸 거라고 생각하고)무시하다가, 이후에 Spring Boot Project 실습할 때 같은 이유로 캐싱 자체가 안 되는 현상이 있었습니다.따라서 무시할 게 아니라 쓰기 권한을 부여해야 합니다. 관련된 내용을 사진 첨부드리니 참고 부탁드립니다.또한 해당 내용은 windows 에서 설치하고 PING 으로 확인할 때부터 나타나는 현상이므로, 혹시라도 제안드리자면 노션의 redis 설치 가이드 페이지에서 권한 문제 트러블슈팅으로 추가로 적어주시면 공유하기에 좋을 듯 합니다. Mac 은 잘 모르겠습니다...ㅎㅎdump.rdb 등 .rdb 확장자 파일에서 우클릭 후 속성 클릭 [보안] 탭으로 이동한 후 편집 클릭(현재 사용 중인 계정을 클릭하면 현재 부여된 사용 권한도 확인 가능)현재 사용 중인 계정을 찾아서 사용 권한에 수정과 쓰기 등등 필요한 권한 부여(잘 모르겠으면 모든 권한 클릭) 후 저장
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
LettuceConnectionFactory 를 RedisConnectionFactory 의 빈으로 등록하지 않는 특별한 이유가 있나요?
안녕하세요, 좋은 강의 감사합니다. 강의시간 3:10LettuceConnectionFactory 라는 게 있어서 한 번 들여다봤는데, RedisConnectionFactory 를 구현하는 객체로 보입니다. 이왕이면 RedisConnectionFactory 빈의 구현체로 등록하고, 또 RedisConnectionFactory 를 의존하도록 설계하고 싶은 욕구가 생겨서 그렇게 해봤는데, 일단 별 문제는 안 생긴 것 같습니다.LettuceConnectionFactory 를 실제로 RedisConnectionFactory 의 구현체로 등록해도 상관없나요? 아니면 혹시나 혹시나, RedisConnectionFactory 의 빈으로 등록하면 안 되는 이유가 있는 건가요?@Bean public RedisConnectionFactory lettuceConnectionFactory() { return new LettuceConnectionFactory(new RedisStandaloneConfiguration(host, port)); }
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
페이지 데이터 캐싱할때 질문
페이지 데이터 캐싱할 때, 아래처럼 컨텐트만 보내는 게아니라@Cacheable(cacheNames = "getBoards",key = "'boards:page:'+ #page + ':size:' + #size", cacheManager = "boardCacheManager") public List<Board> getBoards(int page, int size) { Pageable pageable = PageRequest.of(page - 1, size); Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable); return pageOfBoards.getContent(); }아래처럼 Page 객체 자체를 보내야,실제로 페이징 처리가 가능할텐데요@Cacheable(cacheNames = "getBoards",key = "'boards:page:'+ #page + ':size:' + #size", cacheManager = "boardCacheManager") public Page<Board> getBoards(int page, int size) { Pageable pageable = PageRequest.of(page - 1, size); Page<Board> pageOfBoards = boardRepository.findAllByOrderByCreatedAtDesc(pageable); return pageOfBoards; }이렇게 하면, Page 역직렬화시 오류가 발생하는데, 이렇게 Page<Board>를 보내줘야 할 때는 어떻게 보내야할지 모르겠습니다. 정확히 캐싱의 역직렬화가 어디까지 가능한지 파악이 잘 안되서..gpt한테 물어보니, Page 같은 특수한 객체는 역직렬화 방법이 없고, db에서 찾은 page를 분해해서 이걸 다시 dto로 감싸서 보내라는데, 이런 방식밖에 없는건지.. Page 데이터 보내실때 어떻게 보내시는지 궁금합니다.
-
미해결비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
RDS관련
java.lang.NullPointerException: Cannot invoke "org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(java.sql.SQLException, String)" because the return value of "org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.sqlExceptionHelper()" is null at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:116) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:290) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:123) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:77) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.boot.model.relational.Database.<init>(Database.java:45) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:221) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:189) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:171) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1431) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1502) ~[hibernate-core-6.5.2.Final.jar!/:6.5.2.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.12.jar!/:6.1.12] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.1.12.jar!/:6.1.12] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.12.jar!/:6.1.12] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.12.jar!/:6.1.12] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.12.jar!/:6.1.12] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:954) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.12.jar!/:6.1.12] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.3.jar!/:3.3.3] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.3.jar!/:3.3.3] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.3.jar!/:3.3.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.3.jar!/:3.3.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.3.jar!/:3.3.3] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.3.jar!/:3.3.3] at redis_in_spring.practice.PracticeApplication.main(PracticeApplication.java:10) ~[!/:0.0.1-SNAPSHOT] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:569) ~[na:na] at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102) ~[practice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64) ~[practice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT] at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40) ~[practice-0.0.1-SNAPSHOT.jar:0.0.1-SNAPSHOT]2024-08-27T12:34:29.323Z ERROR 4899 --- [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)2024-08-27T12:34:29.325Z WARN 4899 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)2024-08-27T12:34:29.333Z INFO 4899 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]2024-08-27T12:34:29.377Z INFO 4899 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.2024-08-27T12:34:29.432Z ERROR 4899 --- [ main] o.s.boot.SpringApplication : Application run failedorg.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)// ...Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] due to: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)// ...Caused by: org.hibernate.HibernateException: Unable to determine Dialect without JDBC metadata (please set 'jakarta.persistence.jdbc.url' for common cases or 'hibernate.dialect' when a custom Dialect implementation must be provided)application.yml을 깃허브에 올라가지 않도록 처리한 후 EC2에서 직접 작성하는 식으로 해봤는데요. 위와 같은 에러가 계속 발생하는데 무슨 문제때문에 저 에러가 발생하는 것인지 도무지 원인을 모르겠습니다.[서비스]에서 MySQL80이 실행되는 것은 확인했습니다.인텔리제이에서 DataSource 지정시에도 Test Connection이 성공했지만 데이터 역시 안 뜨는 상황입니다.
-
미해결실습으로 배우는 선착순 이벤트 시스템
쿠폰 발급 유저 흐름에 대한 질문
쿠폰이 발급되고 바로 사용하려는 유저가 있다면 어떻게해야하나요? 실무에서 보통의 경우 어떻게 처리하는지 궁금한데요.예를 들어서, 쿠폰이 생성되려면 시간이 다소 소요될 수 있다는 안내 문구와 같은 정책으로 안고가는지.. 아니면 다른 좋은 방법이 있는지 궁금합니다.강의 내용 흐름레디스를 통해서 싱글 스레드로 쿠폰 개수 확인제한 범위 안이라면 클라이언트에게 쿠폰 발급 성공 응답비동기로 처리량을 조절하면서 쿠폰 데이터를 저장실제 유저가 아직 쿠폰 발급이 안되었는데, 쿠폰 사용 시도이 경우 어떻게 대응하는지 궁금합니다.
-
해결됨비전공자도 이해할 수 있는 Redis 입문/실전 (조회 성능 최적화편)
redis 클라우드 선택기준
현재 진행중인 프로젝트에서, NCP server로 spring과 db가 구동되고 있는데요.로컬에서 Redis를 적용시키고 있는 와중에, redis 클라우드를 어느곳을 선택해야할지 고민입니다.aws, ncp, redislabs 등등 ncp 자체에도 있을뿐만 아니라, 다른 클라우드 서비스도 많은데, 어떤 기준으로 골라야될지 잘 모르겠습니다. 성능상 aws를 ncp로 연결하는게 안좋을 거 같지만서도, ncp와 aws도 사용해봤다는 걸로 어필할 수 있는 요소가 될수 있을거 같다는 생각이 들어서요 . 그러나 성능/비용 둘다 안좋은데 왜 굳이 따로 썻냐고 이런부분을 지적받을 수도 있을거 같고요.. 조언부탁드립니다.
-
미해결실습으로 배우는 선착순 이벤트 시스템
수량 조절에 대한 질문이 있습니다.
안녕하세요! 먼저 강의 잘 들었습니다. 좋은 강의 만들어주셔서 감사합니다. 해당 강의에서 쿠폰 수량 조절을 Redis로 진행을 하는데 이에 대해 근본적으로 궁금한 점과 전체적으로 제가 이해한 것이 맞는지 여쭙고 싶습니다. 쿠폰 재고의 동시성을 싱글스레드 기반인 Redis를 통해 100개까지 생성해준다. -> 여기서 X-lock을 사용하는 비관적락을 사용해도 문제가 없지 않나요? Redis를 사용했을 때 장점은 직접적인 DB락을 걸지 않아 데드락이나 다른 위험을 방지할 수 있다는 것인가요?(강의에는 해당되지 않지만) 동시성 제어를 위해 비관적락, 낙관적락(x), Redis를 통한 수량제어 이렇게 해볼 수 있을 거 같은데 언제 Redis를 선택할지 감이 잘 오지 않습니다.강의에서 DB에 10,000개가 들어와서 서버 사용률이 높아졌는데, 결국 카프카로 보내 컨슈머들이 처리를 하게 된다면 똑같이 DB에는 10,000개의 부하가 오지 않나요? 단지 흐름 제어용이라고 보면 될까요? (카프카가 익숙하지 않습니다.)쿠폰의 재고가 아닌 만약 사용자가 상품을 구매할 때에도 해당 강의에 내용을 적용해볼 수 있을 것 같습니다.상품 구매할 때 중복 구매를 방지한다고 하면 Redis에 Set 키 값으로 [product:1(pid):member:1] 이런식으로 하면 마찬가지로 실수로 같은 사용자의 중복 결제도 막아볼 수 있을 것 같습니다! (의도라면 시간을 같이 넣어 조절해도 될 거 같아요) 잘 이해한게 맞을까요?
-
해결됨비전공자도 이해할 수 있는 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를 연산한 시간을 비교해야 온라인인지 여부를 알 수 있게 되는건데 제가 이해하고 있는게 맞는지 알고 싶습니다.