개발자로서 살아남기 52

개발자가 반드시 알아야하는 데이터베이스 - NOSQL vs RDBMS 간단 정리 feat Redis

개요사내에서 분산환경에서 데이터 저장소 선택과 활용이라는 강의를 들었는데, 굉장히 유용한 강의였고, 블로그거리가 많아서 좋았다 ㅋㅋ해당 강의에 대한 요약을 앞으로 2편정도 더 올릴 생각이다.오늘은 강의 초반내용인 RDBMS와 NOSQL의 특징 및 차이에 대해서 아주 간단하게 다뤄본다.RDBMS장점Relation 기반 높은 신뢰성 비교적 높은 성능 비교적 다양한 기능 관리편의성단점비용이 높음Schema 변경 어려움커질수록 느려진다확장성 부족 (처음 시작은 단일 장비 기준으로 만들어짐)NOSQL장점관계없는 데이터 처리에 최적화높은 확장성을 가지는 경우 많음Schemaless단점제한적인 일관성Join, Transaction 미지원관리비용이 큰 경우 있음NOSQL에 대해 자세히확장성/가용성모든 데이터의 신뢰성이..

개발자가 반드시 알아야하는 데이터베이스 - MYSQL에서 쿼리 최적화 하기 (1) - MYSQL Optimizer

개요사내에서 MYSQL 최적화에 대해 강의하는 시간이 있어, 수강하게 되었다.아래 내용은 강의 들은 내용을 간략하게 정리한 것이다.MYSQL Optimizer먼저 Optimizer 란 쿼리 실행 계획을 생성하고 최적화하는 역할을 수행하는 컴포넌트이다.Optimizer을 알아보기 전 MYSQL에 대해 간략히 짚고 넘어가자. MYSQL 서버의 구성도이다.Engine : 클라이언트와의 연결을 관리하는 Connection Management , SQL Parser, Query Optimizer 등 MYSQL에서 행동하는 모든 게 실행되는 곳이다. MEMORY : Engine 실행에 필요한 메모리 Storage Engine : DB의 핵심인 데이터가 저장되는 곳이다.  아래는 쿼리 실행 과정이다.  Optimiz..

Spring boot + JPA 환경에서 Insert 동시 요청 시 처리방법

개요 이전에 회사에서 멀티스레딩 환경에서 동시성 이슈 관련해서 글을 작성한 적이 있다. 그 때는 동시성 이슈 즉 insert 요청이 동시에 온다면 락(LOCK)을 걸어 처리하는 방법을 제시하였다. Spring boot + JPA 환경에서 비관적 vs 낙관적 Lock 선택하기 - https://code-killer.tistory.com/163 사내에서도 해당 방법으로 처리하려던 와중 큰 프로젝트에 참여하게 되었고, 위 이슈는 크리티컬하지 않았기 때문에, 추후 개선 이슈로 놔두었다. 큰 프로젝트가 마무리 되고, 해당 이슈를 다시 살펴보는데, 그땐 생각하지 못했던 의문들이 떠올랐다. "그때 당시에는 동시 요청이 오니까, 일단 락을 걸어 비동기로 처리를 해야겠다." 라고 단순히 생각했었는데 정확히 따지자면, 1..

ELK - primary shard is not active Timeout 에러

네트워크 팀에서 VM 머신 초기화로 인해 elastic이 꺼졌었다. 다시 재부팅 하는 과정에서 위와 같은 로그가 남았는데, 구글링 해보니 elasticsearch 구성파일 중cluster.initial_master_nodes 설정 문제였다. 해당 설정은 맨 처음 클러스터를 시작할 때만 적용하고 이후에, 지워야 하는 옵션임을 공식문서에서 확인하였다. https://www.elastic.co/guide/en/elasticsearch/reference/7.10/modules-discovery-settings.html 그 이후에 cluster의 상태를 보니 red 상태였다. 로그를 보니, 몇몇 샤드들이 활성화가 되지 않아있었다. 그말은 해당 샤드를 가지고 있는 노드가 클러스터에 안붙었다는 얘기인데, 계속 원인을..

ELK - Retrying individual bulk actions that failed or were rejected by the previous bulk request. retrying failed action with response code: 403 에러 발생

개요 6/11 09:17:33 이후부터 poker , classic, client 인덱스에 로그가 안남고 있는 걸 확인 logstash 로그 확인 결과, 아래와 같은 로그가 발생 중 [2023-06-12T16:00:13,910][INFO ][logstash.outputs.elasticsearch][main]{중략....} Retrying individual bulk actions that failed or were rejected by the previous bulk request.{중략....} retrying failed action with response code: 403 ({"type"=>"cluster_block_exception", "reason"=>"index [shrink-index-20..

ELK 인덱스 생명 주기(ILM) 설정하기

Index Lifecycle Policies(ILM)이란? 인덱스(다른 DB에선 테이블)을 사용자가 지정한 날짜, 크기, 문서 수 등에 도달하면 기존에 사용하던 인덱스를 처리(제거, 상태변경)하고, 새로운 인덱스를 할당한다. 현재 회사에서 사용하고 있는 ILM 정책은 인덱스 마다 다르지만, 제일 많이 사용하고 있는 게임 로그 데이터는 아래의 정책을 따른다. 인덱스 생성된지 15일이 지나면 warm 상태로 변경되어 단일 샤드로 축소 30일이 지나면 cold 상태로 변경되고, 읽기 전용 상태로 변하고, 용량이 감소 40일이 지나면 인덱스를 삭제 자세한 내용은 elastic 공식 문서를 참고하면 된다. https://www.elastic.co/guide/en/elasticsearch/reference/7.10..

비관적 락, 낙관적 락 사용시 deadlock 관련 이슈들

개요 스카우터 알람 설정 이후, 간헐적으로 에러가 발생하는 API가 2건 있었다. 급한 이슈는 아니였기에, 우선순위를 뒤로 미뤘었는데, 스카우터 알림방에 빨간색 에러 메시지를 보니까 도저히 그냥 지나칠 수 없었다..(개발자 특) 참고로 아래에 나오는 내용은 낙관적 Lock과 비관적 Lock을 알고 있어야 하는 내용이다. https://code-killer.tistory.com/163 멀티스레딩 환경에서의 동시성 이슈 첫번째 이슈는 select 쿼리 이후, 조건에 따라 insert을 하는 로직이였는데, 동시요청이 들어오면 당연한 결과지만, Duplicate primary Key 에러가 발생했다. Exception - org.springframework.dao.DataIntegrityViolationExce..

Spring boot + JPA 환경에서 비관적 vs 낙관적 Lock 선택하기

개요 회사에서 Spring boot + JPA + mysql 조합을 사용하는 프로젝트가 있는데, PK 중복 문제로 update 시 문제가 발생하였다. 추적 결과 기존 코드는 멀티스레딩 환경에서 조건적으로 동시성 이슈로 생기는 문제였다. 비관적 락, 낙관적 락을 사용하여 해당 이슈를 해결해보기로 한다. 비관적 락 이름 그대로 트랜잭션끼리 충돌을 발생한다고 가정(비관적 락)하여 우선 락을 거는 방법이다. DB의 Lock 기능을 이용한다. (쿼리에 Select for update 구문이 들어감) Lock을 획득할 때까지 트랜잭션은 대기하므로, Timeout 설정 가능 낙관적 락 이름 그대로 트랜잭션 끼리 충돌나지 않는다고 가정하고(낙관적 락)하여 커밋 시 충돌을 알 수 있다. DB Lock 기능을 이용하지 않..

Spring Boot + JPA 환경에서 변경 감지(dirty checking)와 병합(merge)

변경감지와 병합(merge) 병합은 대부분이 알고있는 엔티티 매니저의 merge 메서드이다. 여기서 변경감지(dirty checking)은 JPA의 특징 중 하나이며 entity의 값만 바꿔주면 알아서 변경감지(dirty checking)를 하여 update 쿼리문을 날린다. 준영속 엔티티 영속성 컨텍스트가 더는 관리하지 않는 엔티티 문제는 준영속 엔티티인 경우 JPA가 관리하지 않음으로 어떻게 update을 할 지 애매한 경우이다. 그 때는 2가지 방법을 이용할 수 있다. 변경 감지 기능 사용 병합(merge) 사용 변경 감지 기능 사용 @Transactional public void update(Long id, Entity entity) { // entity를 가져온다. Entity entity = ..

728x90