19,800원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
docker restart시에 java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
2024-04-22 21:51:48.515 ERROR 1928 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization. java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YESTerminal상에서 아래와 같이 Docker를 재시동해서Docker restart 8550a9a141fdDocker ps로 아래와 같이 제대로 동작하는 것도 확인했고igwangmin@igwangmin-ui-MacBookPro ~ % docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8550a9a141fd mysql "docker-entrypoint.s…" 2 days ago Up 17 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql컨테이너가 잘 작동하는것도 아래처럼 보았습니다.다른 게시물에서 알려주신 방법으로 Terminal을 확인했을때 아래와 같이 로그인을 하고 databases를 정상적으로 사용했지만 서버를 가동시켰을 때 하루 전에는 잘 작동했지만 다시 시작을 해보니 아래와 같이 오류가 발생합니다. 아래의 오류 구문이 발생합니다. 혹시 다른 방법이 있을까요?java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
네임드락 테스트 오류
저는 @Query 어노테이션의 값을 아래와 같이 강의 내용대로 따라했을 때 오류가 발생해서 public interface LockRepository extends JpaRepository<Stock, Long> { @Query(value = "select get_lock(:key, 3000)", nativeQuery = true) void getLock(String key); @Query(value = "select release_lock(:key)", nativeQuery = true) void releaseLock(String key); }아래와 같이 정합성이 맞지 않아서 테스트를 통과하지 못했습니다.그래서 구문을 아래와 같이 바꿔서 통과했는데 참고 하시길 바랍니다. ?1의 값은 key로의 값으로 고정되어 있는데 이럴 경우 문제가 없을지 궁금합니다.@Query(value = "select get_lock(?1, 3000)", nativeQuery = true) void getLock(String key); @Query(value = "select release_lock(?1)", nativeQuery = true) void releaseLock(String key);
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
Docker restart시 spring boot 연동이 안됩니다.
igwangmin@igwangmin-ui-MacBookPro ~ % docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8550a9a141fd mysql "docker-entrypoint.s…" 15 hours ago Exited (0) 11 hours ago mysql igwangmin@igwangmin-ui-MacBookPro ~ % docker container restart 8550a9a141fdaee67b6f7c586a24085c98a9b99512cb7a8901f0c23cf9082536 8550a9a141fdaee67b6f7c586a24085c98a9b99512cb7a8901f0c23cf9082536 igwangmin@igwangmin-ui-MacBookPro ~ % docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8550a9a141fd mysql "docker-entrypoint.s…" 15 hours ago Up 4 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysqlDocker restart를 한 후 Spring을 가동했을 때 아래와 같은 오류가 발생합니다. 2024-04-21 09:25:02.485 INFO 1378 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-04-21 09:25:03.641 ERROR 1378 --- [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization. java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-java-8.0.29.jar:8.0.29] at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.29.jar:8.0.29] at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:828) ~[mysql-connector-java-8.0.29.jar:8.0.29] at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:448) ~[mysql-connector-java-8.0.29.jar:8.0.29] at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-java-8.0.29.jar:8.0.29] 기존에 알려주신 방법인 아래와 같은 터미널 창에서 입력후 재실행하였으나 똑같은 오류가 발생해 혹시 다른 방법이 존재할까요igwangmin@igwangmin-ui-MacBookPro Mikor % docker exec -it mysql bash bash-4.4# mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 8 Server version: 8.3.0 MySQL Community Server - GPL Copyright (c) 2000, 2024, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> use stock_example; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | stock_example | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> use stock_example; Database changed mysql> Spring 버전은 아래와 같고 plugins { id 'org.springframework.boot' version '2.7.1' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.shop' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' configurations { compileOnly { extendsFrom annotationProcessor } } 도커 버전은 아래와 같습니다. igwangmin@igwangmin-ui-MacBookPro ~ % docker version Client: Docker Engine - Community Version: 26.0.0 API version: 1.44 (downgraded from 1.45) Go version: go1.22.1 Git commit: 2ae903e86c Built: Wed Mar 20 15:10:03 2024 OS/Arch: darwin/arm64 Context: desktop-linux Server: Docker Desktop 4.28.0 (139021) Engine: Version: 25.0.3 API version: 1.44 (minimum version 1.24) Go version: go1.21.6 Git commit: f417435 Built: Tue Feb 6 21:14:22 2024 OS/Arch: linux/arm64 Experimental: false containerd: Version: 1.6.28 GitCommit: ae07eda36dd25f8a1b98dfbf587313b99c0190bb runc: Version: 1.1.12 GitCommit: v1.1.12-0-g51d5e94 docker-init: Version: 0.19.0 GitCommit: de40ad0
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
Docker의 mysql과 스프링 연동이 안됩니다 (윈도우)
docker pull mysql:8.3.0 $ docker run --name mysql-container -e MYSQL_ROOT_PASSWORD=1234 -d -p 3305:3305 mysql:8.3.0 ... use stock_example로컬에 mysql이 이미 깔려있어서 포트번호를 3305로 바꿔서 만들었어요. 위와같이 도커 초기설정 후 만든 yml 파일입니다spring: jpa: hibernate: ddl-auto: create show-sql: true datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3305/stock_example username: root password: 1234 logging: level: org: hibernate: SQL: DEBUG type: descriptor: sql: BasicBinder: TRACE 이렇게하고 Application을 실행했는데 com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failureThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-j-8.3.0.jar:8.3.0] at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-j-8.3.0.jar:8.3.0] at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:815) ~[mysql-connector-j-8.3.0.jar:8.3.0] at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:438) ~[mysql-connector-j-8.3.0.jar:8.3.0] at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-j-8.3.0.jar:8.3.0] at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:189) ~[mysql-connector-j-8.3.0.jar:8.3.0] at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-5.0.1.jar:na] at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359) ~[HikariCP-5.0.1.jar:na] at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-5.0.1.jar:na] at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470) ~[HikariCP-5.0.1.jar:na] at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-5.0.1.jar:na] at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100) ~[HikariCP-5.0.1.jar:na] at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-5.0.1.jar:na] at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:428) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcIsolationDelegate.delegateWork(JdbcIsolationDelegate.java:61) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.getJdbcEnvironmentUsingJdbcMetadata(JdbcEnvironmentInitiator.java:276) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:107) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:130) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:238) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:215) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.boot.model.relational.Database.<init>(Database.java:45) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.getDatabase(InFlightMetadataCollectorImpl.java:223) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:191) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:170) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1432) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1503) ~[hibernate-core-6.4.4.Final.jar:6.4.4.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.5.jar:6.1.5] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.1.5.jar:6.1.5] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.5.jar:6.1.5] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.5.jar:6.1.5] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1833) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1782) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.5.jar:6.1.5] at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1234) ~[spring-context-6.1.5.jar:6.1.5] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) ~[spring-context-6.1.5.jar:6.1.5] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.5.jar:6.1.5] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.4.jar:3.2.4] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.4.jar:3.2.4] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.4.jar:3.2.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.4.jar:3.2.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.4.jar:3.2.4] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.4.jar:3.2.4] at com.example.stock.StockApplication.main(StockApplication.java:10) ~[main/:na]Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failureThe last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. 이런 오류가 나네요 ㅠㅠ 보면 연결이 안되는거 같은데 어디서 문제일까요..
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
Lock 해제 시점이 궁금합니다.
안녕하세요!Lock을 해제하는 시점이 궁금합니다.아래 단계에서 어느 시점 이전 혹은 이후 인지 알려주시면 감사드리겠습니다. 1) 트랜잭션 시작2) Lock 획득 후 비즈니스 로직 실행3) 트랜잭션 커밋 (혹시, 3번 이전에 Lock을 해제할 경우 이전과 동일한 동시성 문제가 발생할 것 같은데.. 우선 답변부탁드립니다!)
- 해결됨재고시스템으로 알아보는 동시성이슈 해결방법
프로젝트를 처음 시작시에 java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES) 오류가 발생합니다.
spring: jpa: hibernate: ddl-auto: create show-sql: true datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/stock_example username: root password: 1234 # JPA 쿼리가 어떻게 나가는지 logging: level: org: hibernate: SQL: DEBUG type: descriptor: sql: BasicBinder: TRACEyml 설정은 위와 같이 하고 docker 이미지 확인시에 아래와 같이 작동하고 있습니다. igwangmin@igwangmin-ui-MacBookPro ~ % docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 03d3fae9019b mysql "docker-entrypoint.s…" 4 days ago Up 16 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp mysql DB 조회 시에도 아래와 같이 나오는 데 혹시 제가 놓친 부분이 있을까요? mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | stock_example | | sys | +--------------------+ 5 rows in set (0.01 sec)
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
Redisson을 Ebedded로 실행하는 방법이 있을까요?
안녕하세요.Redisson을 이용해서 분산락을 적용하고 있습니다.로컬과 테스트 코드를 실행할 때, Redis를 로컬에서 띄우지 않으면 사용할 수가 없습니다. 그래서 implementation 'com.github.codemonstur:embedded-redis:1.4.2' 의존성을 추가해서 Redis를 embedded로 실행할 수 있도록 했습니다. 하지만 Redisson은 연결이 되지 않는것처럼 보여서요. 혹시 방법이 있을까요? 만약, embedded로 실행할 수 없다면 로컬, 테스트에서는 어떤 방식으로 진행하시는지 경험적 의견을 여쭤보고 싶습니다. 감사합니다. Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisson' defined in class path resource [org/redisson/spring/starter/RedissonAutoConfigurationV2.class]: Failed to instantiate [org.redisson.api.RedissonClient]: Factory method 'redisson' threw exception with message: java.util.concurrent.ExecutionException: org.redisson.client.RedisConnectionException: Unable to connect to Redis server: localhost/127.0.0.1:6379
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
테스트가 실패해요
하다가 안돼서 깃허브 소스 복붙하고 돌려도 테스트가 실패해요.
- 해결됨재고시스템으로 알아보는 동시성이슈 해결방법
docker ps시에 실행되는 이미지가 없다고 나옵니다.
docker ps시에 실행되는 이미지가 아래와 같이 존재하지 않습니다. 혹시 docker를 homebrew를 이용해 설치 한 후 desktop버전도 사이트에서 직접 깔아서 문제가 되는걸까여?
- 해결됨재고시스템으로 알아보는 동시성이슈 해결방법
docker version 오류
homebrew로 docker 설치하는 과정에서 docker version 확인 시에 아래와 같이 오류가 발생합니다. igwangmin@igwangmin-ui-MacBookPro ~ % brew list ==> Formulaeca-certificates libevent protobuf@21docker libfido2 xzdocker-completion lz4 zlibicu4c mysql zstdlibcbor openssl@3 ==> Casksdbeaver-community postmanigwangmin@igwangmin-ui-MacBookPro ~ % brew link docker Warning: Already linked: /opt/homebrew/Cellar/docker/26.0.0To relink, run: brew unlink docker && brew link dockerigwangmin@igwangmin-ui-MacBookPro ~ % docker versionClient: Docker Engine - CommunityVersion: 26.0.0API version: 1.45Go version: go1.22.1Git commit: 2ae903e86cBuilt: Wed Mar 20 15:10:03 2024OS/Arch: darwin/arm64Context: defaultCannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? 그래서 docker 자체를 아래와 같이 삭제하고 새로 시작했는데도 계속 같은 오류가 발생합니다.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
테스트 수행 결과가 항상 에러가 발생합니다.
안녕하세요. 해당 강의를 듣고 있는 수강생입니다. 제가 작성한 코드에서는 계속 테스트가 실패하여 강사님이 올려주신 코드를 기반으로 테스트를 재수행하였습니다. 그런데 여전히 해당 화면처럼 테스트가 실패하여서 어떤 문제일까하여 질문드립니다.코드 : https://github.com/sangyongchoi/stock-example 이슈 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.7.0) 2024-03-24 19:26:47.245 INFO 5004 --- [ main] c.e.s.facade.NamedLockStockFacadeTest : Starting NamedLockStockFacadeTest using Java 17.0.10 on windows with PID 5004 (started by ac2di in C:\Users\ac2di\Desktop\vscode\stock-example-main) 2024-03-24 19:26:47.247 INFO 5004 --- [ main] c.e.s.facade.NamedLockStockFacadeTest : No active profile set, falling back to 1 default profile: "default" 2024-03-24 19:26:48.250 INFO 5004 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode! 2024-03-24 19:26:48.252 INFO 5004 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2024-03-24 19:26:48.519 INFO 5004 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 257 ms. Found 2 JPA repository interfaces. 2024-03-24 19:26:48.532 INFO 5004 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode! 2024-03-24 19:26:48.535 INFO 5004 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode. 2024-03-24 19:26:48.553 INFO 5004 --- [ main] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.example.stock.repository.LockRepository. If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository. 2024-03-24 19:26:48.554 INFO 5004 --- [ main] .RepositoryConfigurationExtensionSupport : Spring Data Redis - Could not safely identify store assignment for repository candidate interface com.example.stock.repository.StockRepository. If you want this repository to be a Redis repository, consider annotating your entities with one of these annotations: org.springframework.data.redis.core.RedisHash (preferred), or consider extending one of the following types with your repository: org.springframework.data.keyvalue.repository.KeyValueRepository. 2024-03-24 19:26:48.554 INFO 5004 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 Redis repository interfaces. 2024-03-24 19:26:49.201 INFO 5004 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2024-03-24 19:26:49.275 INFO 5004 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.9.Final 2024-03-24 19:26:49.465 INFO 5004 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2024-03-24 19:26:49.622 INFO 5004 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-03-24 19:26:49.962 INFO 5004 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2024-03-24 19:26:49.986 INFO 5004 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect 2024-03-24 19:26:50.663 DEBUG 5004 --- [ main] org.hibernate.SQL : drop table if exists stock Hibernate: drop table if exists stock 2024-03-24 19:26:50.708 DEBUG 5004 --- [ main] org.hibernate.SQL : create table stock (id bigint not null auto_increment, product_id bigint, quantity bigint, version bigint, primary key (id)) engine=InnoDB Hibernate: create table stock (id bigint not null auto_increment, product_id bigint, quantity bigint, version bigint, primary key (id)) engine=InnoDB 2024-03-24 19:26:50.762 INFO 5004 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2024-03-24 19:26:50.775 INFO 5004 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-03-24 19:26:51.083 INFO 5004 --- [ main] org.redisson.Version : Redisson 3.17.4 2024-03-24 19:26:51.313 INFO 5004 --- [isson-netty-2-6] o.r.c.pool.MasterPubSubConnectionPool : 1 connections initialized for localhost/127.0.0.1:6379 2024-03-24 19:26:51.468 INFO 5004 --- [sson-netty-2-20] o.r.c.pool.MasterConnectionPool : 24 connections initialized for localhost/127.0.0.1:6379 2024-03-24 19:26:52.949 WARN 5004 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2024-03-24 19:26:54.634 INFO 5004 --- [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 1 endpoint(s) beneath base path '/actuator' 2024-03-24 19:26:54.714 INFO 5004 --- [ main] c.e.s.facade.NamedLockStockFacadeTest : Started NamedLockStockFacadeTest in 7.788 seconds (JVM running for 9.06) 2024-03-24 19:26:55.040 DEBUG 5004 --- [ main] org.hibernate.SQL : insert into stock (product_id, quantity, version) values (?, ?, ?) Hibernate: insert into stock (product_id, quantity, version) values (?, ?, ?) 2024-03-24 19:26:55.051 TRACE 5004 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1] 2024-03-24 19:26:55.052 TRACE 5004 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [100] 2024-03-24 19:26:55.052 TRACE 5004 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [0] 2024-03-24 19:26:55.251 DEBUG 5004 --- [ main] org.hibernate.SQL : select stock0_.id as id1_0_0_, stock0_.product_id as product_2_0_0_, stock0_.quantity as quantity3_0_0_, stock0_.version as version4_0_0_ from stock stock0_ where stock0_.id=? Hibernate: select stock0_.id as id1_0_0_, stock0_.product_id as product_2_0_0_, stock0_.quantity as quantity3_0_0_, stock0_.version as version4_0_0_ from stock stock0_ where stock0_.id=? 2024-03-24 19:26:55.253 TRACE 5004 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1] 2024-03-24 19:26:55.316 DEBUG 5004 --- [ main] org.hibernate.SQL : select stock0_.id as id1_0_, stock0_.product_id as product_2_0_, stock0_.quantity as quantity3_0_, stock0_.version as version4_0_ from stock stock0_ Hibernate: select stock0_.id as id1_0_, stock0_.product_id as product_2_0_, stock0_.quantity as quantity3_0_, stock0_.version as version4_0_ from stock stock0_ 2024-03-24 19:26:55.334 DEBUG 5004 --- [ main] org.hibernate.SQL : delete from stock where id=? and version=? Hibernate: delete from stock where id=? and version=? 2024-03-24 19:26:55.335 TRACE 5004 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1] 2024-03-24 19:26:55.335 TRACE 5004 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [0] 2024-03-24 19:26:55.437 INFO 5004 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2024-03-24 19:26:55.441 INFO 5004 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2024-03-24 19:26:55.514 INFO 5004 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.테스트 수행 시 콘솔 출력 창도 같이 첨부드립니다. 감사합니다.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
yml 설정 내용 공유
혹시 귀찮으신분들 있으실까봐 공유드립니다.2칸(뎁스) 는 주의부탁드려요 spring: jpa: hibernate: ddl-auto: create show-sql: true datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/stock_example username: root password: 1234 # JPA 쿼리가 어떻게 나가는지 logging: level: org: hibernate: SQL: DEBUG type: descriptor: sql: BasicBinder: TRACE
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
Pessmistic Lock 획득 순서가 보장되는지 궁금합니다
안녕하세요 강사님.다름이 아니라 Pessmistic Lock 획득을 요청한 쓰레드 순서가 쓰레드1, 쓰레드2 쓰레드3이고 이때 쓰레드1이 먼저 락을 획득한 후 락을 해제하면,먼저 요청한 쓰레드2가 락을 반환한받는지 궁금합니다.제가 gpt 및 postgresql, spring data jpa 공식문서를 검색했을 땐, 락 획득 요청대로 락 획득 순서가 보장된다는 내용은 없었어서,혹시 이부분에 대해 알고계신지 궁금하여 질문 올립니다.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
네임드락 선점 시간 설정
안녕하세요! 네임드락 사용 시 락 선점 시간 설정에 있어 궁금한 부분이 생겨 질문 드립니다. Named Lock 활용해보기 강의 25초 부분에 "선점 시간이 끝나야 락이 해제된다" 고 언급해주셨는데, 이 선점 시간을 어떻게 설정하는지 궁금합니다. "get_lock" 명령어에 주는 파라미터는 해당 lock 을 획득하기 위해 대기하는 시간의 최대값으로 알고 있습니다. 그래서 hikariCp 에서 얻어온 커넥션을 점유할 수 있는 최대 시간 설정 값도 찾아봤는데 찾지 못했습니다.별도의 타이머를 구현해서 타이머가 끝나면 해제로직을 실행시켜야 되는걸까요??혹은, @Transactional 의 timeout 설정 값을 통해 선점 시간을 설정하는 방법도 가능할 것 같습니다.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
분산 DB 에서 비관적 락을 통한 동시성 제어
안녕하세요. 분산락을 언제 쓰는게 좋을지 고민하다가 몇 가지 궁금증이 생겨 질문드립니다.분산 DB 환경이 무엇을 의미하는지?흔히 분산 DB 환경에서 낙관적, 비관적 락으로 동시성 문제를 해결하기 힘들다고 얘기하더라고요. 여기서 말하는 분산 DB 라는 것이 샤딩에 의해 여러 DB 서버가 있는 것인지, 동일한 데이터를 저장하는 DB 서버가 여러 대 있는 환경을 의미하는 것인지 모르겠습니다.예를 들어, Ticket 이란 데이터를 저장하는데 동일한 ticket 데이터가 DB server 1, DB server 2 에 저장되어 있는 환경일까요??만약 분산 DB 가 샤딩인 경우 비관적 락으로도 동시성 이슈를 해결할 수 있을 것 같은데 맞을까요?아래 그림처럼 ticketId = 1 인 티켓을 예매하기 위한 요청이 동시에 올 경우 입니다. 처음 x-lock 을 잡은 요청이 끝나야 뒤늦게 온 요청이 해당 티켓의 잔여 수량을 확인하고 예매 하기 때문에 샤딩으로 인한 분산 DB 에서는 비관적 락으로 동시성 이슈를 해결할 수 있을 것 같습니다.동일한 Ticket 데이터가 여러 DB 서버에 중복되어 저장된 분산 DB 환경에서는 분산락을 사용해야 될 것 같습니다.그러나, 샤딩은 동일한 Ticket 데이터에 접근하기 위해서는 동일한 서버로 접근하기 때문에 비관적 락으로도 충분히 해결 가능할 것 같아서 질문 드립니다!
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
PessimisticLock을 분산락으로 활용하는 질문에 대한 답변 남기겠습니다.
github repository url: https://github.com/developer-yoni/ecommerce/tree/study/concurrency/redis여기서 study/concurrency/redis 브랜치를 확인해주시면 됩니다.StockServiceTest의 400번째 라인부터 503번째 라인까지테스트 코드가 작성되어 있습니다.큰 흐름은 동시성 이슈가 발생가능한 Stock에는 Lock을 걸지 않고,다른 Entity인 Market Entity에 PessimisticLock을 걸어,PessimisticLock을 분산락으로 활용하려는 시도 입니다.여기서 4_1 테스트는 Market에 PessimisticLock을 거는 트랜잭션과 Stock의 재고를 감소시키는 트랜잭션을 하나의 트랜잭션으로 묶었고,4_2 테스트는 별개의 트랜잭션으로 분리했습니다.이때 질문은 다음과 같습니다Q1. 동시성 이슈가 일어나지 않는 다른 Entity에 PessimisticLock을걸어 분산락처럼 활용하는게 문제가 되지 않을지 궁금합니다.혹시 문제가 된다면 , 어떤 측면에서 문제가 될지 궁금합니다.왜냐하면 어차피 동시성 이슈가 일어날 수 있는 측면의 값을 커밋하여 update함과 동시에PessmisticLock을 반환하는 것이니 문제가 되지 않을것이라고 생각했기 때문입니다.Q2. PessimisticLock을 건 트랜잭션이 커밋되거나 롤백될 때 비로소 PessmisticLock이 반환된다는 점을 근거로,4_2 테스트에서는 일부로 재고감소를 먼저 커밋한 후,Market의 PessimisticLock을 커밋하여,반드시 업데이트가 이뤄난 후 락을 반환하는것을 의도하였습니다.그러나 제 의도와 다르게 4_2 테스트는 계속 lock이 걸려있는?흐름을 보이면서 테스트에 실패합니다.그원인을 잘 모르겠습니다.바쁘신 와중에 답변 달아주셔서 감사합니다 강사님.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
혹시 PessimisticLock을 NameLock처럼 분산락으로 활용할 수는 없을까요?
질문의 의도처럼 변경하고자 하는 Entity는 A인데,사실 Entity B에 PessimisticLock을 획득하고, 획득한 쓰레드들에 한해서만 A를 변경하게 하면 PessimisticLock을 분산락으로 활용할 수 있을것 같았습니다.그러나 사실, 제가 테스트해본 결과 동시성 이슈가 발생해서, 그 원인을 모르겠습니다.제 생각은 PessimisticLock을 얻지 못한 쓰레드는 계속 대기하면서 변경하고자 하는 Entity B를 변경할 수 없을것이라고 생각했습니다.@Transactionalpublic void decrease2(Long id, Long quantity) {//0. 여기서 동일한 UserEntity에 대해 PesimisticLock을 건다 userRepository.findByIdWithPessimisticLock(userId); //1. stock 조회 Stock stock = stockRepository.findByIdAndEntityStatus(id, EntityStatus.ACTIVE).orElseThrow(() -> new ApiException(ApiCode.CODE_000_0011, "재고 감소시, 요청값으로 들어온 stockId로 Stock 조회 실패")); //2. 재고 감소 // 여기서 stock.decreaseInventoryQuantity(quantity); //3. 갱신된 값을 저장 stockRepository.saveAndFlush(stock); // 마지막에 트랜잭션 커밋 되야 -> Pessimistic Lock이 반환된다}
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
강의의 NamedLockStockFacade의 decrease()에서 @Transactional을 붙인 이유 질문
안녕하세요 강사님.제가 gpt를 통해 확인한 결과는, MySQL의 getLock(), releaseLock()은 트랜잭션 상태와는 무관하게 동작할 수 있다는 것이었습니다. 또한 NamedLockStockFacade에서 호출하는 StockService.decrease()는 REQUIRES_NEW에 의해 별도의 트랜잭션으로 관리되고 커밋 됩니다.따라서 StockService.decrease()에 의해 재고가 감소한 후,NamedLockStockService에서 releaseLock()으로 락을 반환할 때 예외가 터져도, 이미 커밋된 재고감소는 롤백되지 않을 것 같습니다.그럼에도 NamedLockStockFacade에서 @Transactional을 붙이신 별도의 의도가 있는지 궁금합니다.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
OptimisticLockStockService에서 @Transactional을 붙이게 되면 무한루프에 빠지는 이유 질문
안녕하세요 강사님. 강사님 강의를 예전에 들었는데 , 현업에서 실제 동시성 처리를 하려고 다시 보니 예전에 안보이던게 보이는 것 같습니다. 감사합니다.제가 질문하고 싶은 부분은 강의를 들으면서 습관적으로 OptimisticLockStockService에서 @Transactional을 붙였는데 무한루프에 빠졌습니다. 앞의 질문에 대한 답변으로 강사님이 보내주신 답변을 힌트로 그 원인을 생각했는데 , 이부분에 대해 피드백을 주시면 감사하겠습니다.제가 이해한 바로는 OptimisticLockStockFacade에 @Transactional을 붙이게 되면,트랜잭션이 재시도 로직을 포함해서 묶이면서, version 차이로 재시도를 할 때 새로운 버전으로 Stock을조회해와야 하는데, 아직 Transactional이 유지되고 있으니깐, Entity Manager에 있는 이전에 실패한 version의 Stock을 가지고 다시 update를 실패해서 무한루프에 빠진다고 생각했습니다.
- 미해결재고시스템으로 알아보는 동시성이슈 해결방법
saveAndFlush 와 synchronized
https://www.inflearn.com/questions/655574위에 질문에서 saveAndFlush를 사용한 이유에 "save 메소드를 사용하게 된다면 데이터베이스에 바로 flush 가 되는것이 아니기때문에 synchronized 를 이용한 방법을 테스트할 때 오류가 날것입니다." 라고 답변해주셨는데 save를 사용하든 saveAndFlush를 사용하든 문제가 발생하지 않나요?flush를 바로 해준다고 데이터베이스에 커밋이 되는게 아니기때문에 충분히 동시성 문제가 생길 수 있다고 생각됩니다. 결국 아래 코드에서 saveAndFlush를 사용하든 save를 사용하든 실패하는것인데 왜 saveAndFlush를 사용하면 오류가 안난다고 하신건지 궁금합니다.@Transactional public synchronized void decrease(Long id, Long quantity) { Stock stock = stockRepository.findById(id).orElseThrow(); stock.decrease(quantity); stockRepository.saveAndFlush(stock); }