인덱스

인덱스의 필요성

  • 인덱스는 데이터를 빠르게 찾을 수 있는 하나의 장치이다.

B-트리

  • 인덱스는 보통 B-트리라는 자료 구조로 이루어져있다.
  • B-트리는 이진 탐색 트리의 일종으로 탐색 성능을 높이기 위해 균형있게 높이를 유지하는 균형 트리 입니다.
  • 규칙에 따라 여러개의 자식노드를 가질 수 있다.

인덱스가 효율적인 이유와 대수확장성

  • 인덱스가 효율적인 이유는 효율적인 단계를 거쳐 모든 요소에 접근할 수 있는 균형 잡힌 트리 구조와 트리 깊이의 대수확장성 때문이다.

인덱스 만드는 방법

  • MySQL의 경우 클러스터형 인덱스와 세컨더리 인덱스가 있다.
  • 클러스터형 인덱스
    • 테이블당 하나를 설정할 수 있다.
    • primary key 옵션으로 기본키를 만들면 클러스터형 인덱스를 생성할 수 있다.
    • 기본키가 아닌 unique not null 옵션을 붙이면 클러스터형 인덱스로 만들 수 있다.
  • 세컨더리 인덱스
    • 명령어를 기반으로 만들면 세컨더리 인덱스를 만들 수 있다.
    • 여러개의 필드 값을 기반으로 쿼리를 많이 보낼 때 생성해야 하는 인덱스

인덱스 최적화 기법

  • 인덱스는 비용이다.
    • 인덱스는 두 번 탐색하도록 강요한다. 인덱스 리스트 그다음 컬렉션 순으로 탐색하기 때문에 관련 읽기 비용이 들게 된다.
    • 컬렉션이 수정되었을 때 인덱스도 수정되어야 한다. 이때 많은 비용이 발생
    • 그렇기 때문에 쿼리에 있는 필드에 무작정 인덱스를 설정하는 것은 답이 아니다.
    • 데이터 양이 많을수록 인덱스를 사용하는 것은 비효율적이다.
  • 항상 테스팅 하라
    • EXPLAIN 함수를 통해 인덱스를 만들고 ㅜ커리를 보낸 이후에 테스팅을 하며 걸리는 시간을 최소화 해야 한다.
  • 복합 인덱스는 같음, 정렬, 다중 값, 카디널리티 순이다.
    • 여러 필드를 기반으로 조회를 할 때 복합 인덱스를 생성하는데, 이 인덱스를 생성할 때는 순서가 있고, 생성 순서에 따라 인덱스 성능이 달라진다. 같음, 정렬, 다중값, 카디널리티 순으로 생성해야 한다.

조인

  • 하나의 테이블이 아닌 두 개 이상의 테이블을 묶어서 하나의 결과물을 만드는 것을 말한다.
  • 내부 조인(inner join)
    • 왼쪽 테이블과 오른쪽 테이블의 두 행이 모두 일치하는 행이 있는 부분만 표기(교집합)
  • 왼쪽 조인(left outer join)
    • 왼쪽 테이블의 모든 행이 결과 테이블에 표기된다.
  • 오른쪽 조인(right outer join)
    • 오른쪽 테이블의 모든 행이 결과 테이블에 표기된다.
  • 합집합 조인(full outer join)
    • 두 테이블을 기반으로 조인 조건에 만족하지 않는 행까지 모두 표기한다.

내부 조인

  • 두 테이블 간의 교집합을 나타낸다.
  • SELECT * FROM tableA A INNER JOIN tableB B ON A.key = B.key

왼쪽 조인

  • 테이블 B의 일치하는 부분의 레코드와 함께 테이블 A를 기준으로 완전한 레코드 집합을 생성
  • 만약 B에 일치하는 항목이 없으면 해당 값은 null 값이 된다.
  • SELECT * FROM tableA A LEFT JOIN tableB B ON A.key = B.key

오른쪽 조인

  • 테이블 A에서 일치하는 부분의 레코드와 함께 테이블 B를 기준으로 완전한 레코드 집합을 생성
  • A에 일치하는 항목이 없으면 해당 값은 NULL이 된다.
  • SELECT * FROM tableA A RIGHT JOIN tableB B ON A.key = B.key

합집합 조인

  • 양쪽 테이블에서 일치하는 레코드와 함께 테이블 A와 테이블 B의 모든 레코드 집합을 생성
  • 일치하는 항목이 없으면 누락된 쪽에 NULL 포함
  • SELECT * FROM tableA A FULL OUTER JOIN tableB B ON A.key = B.key

조인의 원리

중첩 루프 조인

  • 중첩 for 문과 같은 원리로 조건에 맞는 조인을 하는 방법
  • 랜덤 접근에 대한 비용이 많아 대용량 테이블에서는 사용하지 않음
  • ex) 테이블 a에서 행 하나를 읽고 다음 반복문에서 조건에 맞는 레코드를 찾음

정렬 병합 조인

  • 각각의 테이블을 조인할 필드 기준으로 정렬하고 정렬이 끝난 이후에 조인 작업을 수행
  • 조인 시에 적절한 인덱스가 없고 대용량 테이블들을 조인 조건으로 범위 비교 연산자가 있을 때 사용

해시 조인

  • 해시 테이블을 기반으로 조인
  • 두 테이블을 조인 시에 하나의 테이블이 메모리에 온전히 들어간다면 중첩 루피 조인보다 더 효율적이다.
  • 동등(=) 조인 에서만 사용할 수 있다.

'Computer science > 데이터베이스' 카테고리의 다른 글

트랜잭션과 무결성  (2) 2023.09.06

트랜잭션

  • 데이터베이스에서 하나의 논리적 기능을 수행하기 위한 작업의 단위
  • ACID 특징을 가짐
    • 원자성
    • 일관성
    • 독립성
    • 지속성

원자성

  • 트랜잭션과 관련된 일이 모두 수행되었거나 되지 않았음을 보장하는 특징
  • 트랜잭션 단위로 여러 로직들을 묶을 때 외부 API를 호출하는 것이 있으면 안된다.
    • 만약 있다면 롤백이 일어났을 때 어떻게 해야 할 것인지에 대한 해결 방법이 있어야 하고 트랜잭션 전파를 신경써서 관리해야 한다. → 스프링의 @transactional이 이를 지원해줌
  • commit
    • 여러 쿼리가 성공적으로 처리되었다고 확정하는 명령
  • rollback
    • 트랜잭션으로 처리한 하나의 묶음 과정을 일어나기 전으로 돌리는 (취소)명령
  • 트랜잭션 전파
    • 트랜잭션을 수행할 때 커넥션 단위로 수행하기 때문에 커넥션 객체를 넘겨서 수행해야 한다.
      • 하지만 이를 매번 넘겨주기가 어렵고, 귀찮다.
    • 이를 넘겨서 수행하지 않고 여러 트랜잭션 관련 메서드의 호출을 하나의 트랜잭션에 묶이도록 하는 것을 트랜잭션 전파라고 한다.

일관성

  • 허용된 방식으로만 데이터를 변경해야 하는 것을 의미

격리성

  • 트랜잭션 수행 시 서로 끼어들지 못하는 것을 의미한다.
  • 복수의 병렬 트랜잭션은 서로 격리되어 마치 순차적으로 실행되는 것처럼 작동되어야 하고 데이터베이스는 여러 사용자가 같은 데이터에 접근할 수 있어야 한다.
  • 순차적으로 하면 쉽게 되겠지만 성능이 나빠진다.
  • 격리성은 여러 개의 수준으로 나뉘어 격리성을 보장한다.

 💡 격리성 높음, 동시성 낮음

  1. SERIALIZABLE
  2. REPEATABLE_READ
  3. READ_COMMITTED
  4. READ_UNCOMMITTED

 💡 격리성 낮음, 동시성 높음

  • 밑으로 갈수록 동시성이 강해지지만 격리성은 약해지고 위로 갈수록 동시성은 약해지고 격리성은 강해진다.

격리 수준에 따라 발생하는 현상

  • 팬텀 리드
    • 한 트랜잭션 내에서 동일한 쿼리를 보냈을 때 해당 조회 결과가 다른 경우
  • 반복 가능하지 않은 조회
    • 한 트랜잭션 내의 같은 행에 두 번 이상 조회가 발생했는데, 그 값이 다른 경우를 가리킨다.
    • 팬텀 리드와 다른 점은 행 값이 달라질 수 있지만 팬텀리드는 다른 행이 선택될 수도 있다는 점이다.
  • 더티 리드
    • 한 트랜잭션이 실행 중일 때 다른 트랜잭션에 의해 수정되었지만 아직 커밋되지 않은 행의 데이터를 읽을 수 있을 때 발생

격리 수준

  • SERIALIZABLE
    • 트랜잭션을 순차적으로 진행시키는 것
    • 동시에 같은 행에 접근 불가
    • 성능이 가장 떨어지는 격리 수준
  • REPEATABLE_READ
    • 하나의 트랜잭션이 수정한 행을 다른 트랜잭션이 수정할 수 없도록 막아준다.
    • 새로운 행을 추가하는 것은 막지 않는다.
  • READ_COMMITTED
    • 가장 많이 사용되는 격리 수준
    • 다른 트랜잭션이 커밋하지 않은 정보는 읽을 수 없다.
      • 커밋 완료된 데이터에 대해서만 조회를 허용한다.
    • 어떤 트랜잭션이 접근한 행을 다른 트랜잭션이 수정할 수 있다.
  • READ_UNCOMMITTED
    • 가장 낮은 격리 수준
    • 하나의 트랜잭션이 커밋되기 이전에 다른 트랜잭션에 노출되는 문제가 있다.
      • 하지만 가장 빠르다.
    • 되도록 사용하지 않는 것이 이상적이다.
      • 어림잡아 집계하는 데에 사용하면 좋다.

지속성

  • 성공적으로 수행한 트랜잭션은 영원히 반영되어야 하는 것을 의미한다.
    • 이를 위해 체크섬, 저널링, 롤백 기능을 제공

무결성

  • 데이터의 정확성, 일관성, 유효성을 유지하는 것을 말한다.

개체 무결성

  • 기본키로 선택된 필드는 빈 값을 허용하지 않는다.

참조 무결성

  • 서로 참조 관계에 있는 두 테이블의 데이터는 항상 일관된 값을 유지해야 한다.

고유 무결성

  • 특성 속성에 대해 고유한 값을 가지도록 조건이 주어진 경우 그 속성 값은 모두 고유한 값을 가진다.

NULL 무결성

  • 특정 속성 값에 NULL이 올 수 없다는 조건이 주어진 경우 그 속성 값은 NULL이 될 수 없다는 제약조건

'Computer science > 데이터베이스' 카테고리의 다른 글

인덱스 / 조인  (1) 2023.09.07

객체를 컨트롤러에서 바인딩 하는 경우는 크게 2가지

@ModelAttribute

  • body내부에 쿼리파라미터 형식으로 들어온 값

@RequestBody

  • body내부에 (주로Json) 형태로 들어온 값

문제 상황

기존에 필드 네이밍을 할 때 boolean 타입의 값은 isXXX 이라는 형태로 네이밍을 하는 습관이 있었고, 내부에 boolean 타입 필드에 isXXX 라는 변수명을 선언 하였고, 해당 객체를 리턴하자 접두어 is가 떨어진 변수와 isXXX변수가 존재하고 있었다.

문제 원인 파악 전 기존에 알고 있던 사실

  • 기존에 @RequestParam, @ModelAttribute는 프로퍼티(setXXX)를 통해 바인딩을 한다고 알고 있었다.
  • @RequestBody는 httpMessageConverter를 통해 바인딩을 하기 때문에 setter가 없어도 가능하다.

테스트

  • 단순히 받아온 값을 그대로 내려주는 API (boolean값을 is를 뗀 값으로 네이밍)
  1. 롬복의 @Data 어노테이션을 붙였을 경우
    1. ModelAttribute를 사용한 경우 - 성공
    2. RequestBody을 사용한 경우 - 성공
  2. 롬복의 @Data 어노테이션을 안붙인 경우
    1. ModelAttribute를 사용한 경우 - 실패
    2. RequestBody을 사용한 경우 - 성공

위의 테스트 결과로 도출한 결론은 기존에 알고 있었던 사실과 동일하게 RequestBody는 Property 없이도 객체 바인딩을 수행할 수 있다.(변수가 public이었기 때문에 동작할 수 있었다....)

그렇다면 boolean type 변수를 isFollowed를 사용하던 followed를 사용하던 상관없는 것이 아닌가?(...)

테스트

  • followed 변수를 isFollowed로 변경
  1. 롬복의 @Data 어노테이션을 붙였을 경우
    1. ModelAttribute 사용
    2. RequestBody 사용
    • 위의 두 가지 경우 모두 followed라는 필드가 하나 더 생겨서 응답으로 리턴되었다
  2. 롬복의 @Data 어노테이션을 안붙인 경우
    1. ModelAttribute 사용
      • 위에서 봤듯이 어짜피 실패하는 케이스이다.
    2. RequestBody 사용 - 원하는 대로 수행됨

followed라는 필드가 하나 더 생겨서 응답으로 리턴된 상황

 

테스트 결과로 @Data 어노테이션과 연관되어 있는 문제라고 의심!

  • Lombok이 만들어준 getter, setter이다.
  • boolean타입의 경우 변수 앞에 is를 붙이고 getter를 만든다.
  • 현재 선언해준 isFollowed가 followed라고 선언된 것 처럼 프로퍼티가 생성되어 있다.
  • RequestBody는 HttpMessageConverter 로 인해 바인딩이 되는데 이때MappingJackson2HttpMessageConverter는 ObjectMapper를 사용하는데, 프로퍼티를 이용하기 때문에 getter / setter 둘 중 하나만 있으면 된다고 한다.

테스트를 진행하며 필드의 접근제한자에도 뭔가 관련이 있는 것 같다.

  • private로 테스트
    • 필드가 is접두어를 뗀 값으로 나오고 항상 default값이 적용되어있음
  • public으로 테스트
    • 필드가 하나 더 생성되어 전달된다.
      • isXXX
      • XXX

ObjectMapper에 대해서 살펴보자

  • ObjectMapper는 리플렉션을 활용해서 객체로부터 Json 형태의 문자열을 만들어내는데, 이것을 직렬화(Serialize)라고 한다. 해당 부분은 @ResponseBody나 @RestController 또는 ResponseEntity 등을 사용하는 경우에 처리된다.
  • ObjectMapper의 기본 설정으로는 public 필드 또는 public 형태의 getter(getX로 시작하는 메소드)만 접근이 가능하다.
    • 이 기본 설정 때문에 public으로 두었을때 일반 필드에도 접근이 가능하여 두 개의 필드가 생성되었던 것이다.
  • 결국은 ObjectMapper도 프로퍼티를 활용하여 역/직렬화를 수행한다.

정리

  • 1차 테스트
    • 접근제한자를 public으로 설정
      • @RequestBody
        • 정상적으로 수행됨
        • Getter, Setter 둘다 없어도 필드를 통해 객체를 (역)직렬화 한다.
        • Getter, Setter가 있다면 프로퍼티, 필드 접근을 통해 (역)직렬화 한다.
          • 이 때문에 public인 isXXX필드와 Lombok이 만들어준 isXXX 둘 다 접근이 가능하여 필드가 하나 더 생성되었던 것
      • @ModelAttribute
        • setter없이는 정상적인 수행 자체가 불가능
        • 요청에 맞는 생성자가 있다면 setter없이도 정상적인 수행이 가능하다.
  • 2차 테스트
    • 접글 제한자를 private로 설정
      • @RequestBody
        • getter/setter 둘 다 없을 때 Could not find acceptable representation 에러 발생
        • 둘 중 하나라도 있다면 에러는 발생하지 않지만
        • isXXX로 나와야할 필드가 XXX로 나오는 현상 발생
          • 필드를 보고 객체를 json으로 역직렬화 하는 것이 아닌 프로퍼티를 보고 역직렬화 한다.

프로세스

  • 프로세스는 컴퓨터에서 실행되고 있는 프로그램을 말하며 CPU 스케줄링의 대상이 되는 작업이라는 용어와 같은 의미로 쓰인다.
  • 쓰레드는 프로세스 내 작업의 흐름을 지칭한다.

프로세스의 상태

생성

  • 생성 상태는 프로세스가 생성된 상태를 의미하며 fork(), exec() 함수를 통해 생성한다. 이때 PCB가 할당된다
  • fork()
    • 부모 프로세스의 주소 공간을 그대로 복사하며, 새로운 자식 프로세스를 생성하는 함수
    • 주소 공간만 복사할 뿐이지 부모 프로세스의 비동기 작업 등을 상속하지는 않는다.
  • exec()
    • 새롭게 프로세스를 생성하는 함수

대기 상태

  • ready(대기 상태)는 메모리 공간이 충분하면 메모리를 할당받고 아니면 아닌 상태로 대기하고 있으며 CPU 스케줄러로부터 CPU 소유권이 넘어오기를 기다리는 상태.

대기 중단 상태

  • 메모리 부족으로 일시 중단된 상태

실행 상태

  • CPU 소유권과 메모리를 할당받고 인스트럭션을 수행 중인 상태를 의미

중단 상태

  • 어떤 이벤트가 발생한 이후 기다리며 프로세스가 차단된 상태
  • I/O 디바이스에 의한 인터럽트로 이런 현상이 발생하기도 한다.

일시 중단 상태

  • 중단된 상태에서 프로세스가 실행되려고 했지만 메모리 부족으로 일시 중단된 상태이다.

종료 상태

  • 메모리와 CPU 소유권을 모두 놓고 가는 상태를 말한다.
  • 부모 프로세스가 자식 프로세스를 강제시키는 비자발 종료로 종료되는 것도 있다.
  • 사용자가 process, kill 등 여러 명령어로 프로세스를 종료할 때 발생

프로세스 메모리 구조

https://velog.io/@cchloe2311/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B5%AC%EC%A1%B0

  • 운영체제는 프로세스에 적절한 메모리를 할당하는데 다음 구조를 기반으로 할당

스택

  • 지역변수, 매개변수, 함수가 저장되고 컴파일 시에 크기가 결정되며 동적인 특징을 갖는다.
  • 스택 영역은 함수가 함수를 재귀적으로 호출하면서 동적으로 크기가 늘어날 수 있고, 이때 힙 과 스택의 메모리 영역이 겹치면 안되기 때문에 힙과 스택 사이의 공간을 비워 놓는다.

  • 동적 할당할 때 사용되며 런타임 시 크기가 결정된다.

데이터 영역

  • 전역변수, 정적변수가 저장, 정적인 특징을 갖는 프로그램이 종료되면 사라지는 변수가 들어있는 영역
  • BSS
    • 초기화 되지 않은 변수가 0으로 초기화되어 저장된다.
  • DATA
    • 0이 아닌 다른 값으로 할당된 변수들이 저장된다.

코드 영역

  • 프로그램에 내장되어 있는 소스 코드가 들어가는 영역

PCB

  • 프로세스에 대한 메타데이터를 저장한 데이터를 뜻한다.
    • 프로세스를 나타내기 위한 모든 정보들
  • 프로세스 제어 블록이라고도 한다.
  • 프로세스가 생성되면 운영체제는 해당 PCB를 생성
  • 커널 스택의 가장 앞부분에서 관리된다. (일반 사용자가 접근하지 못함)

컨텍스트 스위칭

https://www.crocus.co.kr/1364

  • PCB를 교환하는 과정
  • 한 프로세스에 할당된 시간이 끝나거나 인터럽트에 의해 발생

'Computer science > 운영체제' 카테고리의 다른 글

메모리  (0) 2023.08.10

CPU는 메모리에 올라와 있는 프로그램의 명령어들을 실행할 뿐이다.

메모리 계층

  • 레지스터
    • CPU 안에 있는 작은 메모리, 휘발성, 속도 가장 빠름, 용량 가장 적음
  • 캐시
    • L1,L2 캐시를 지칭 휘발성, 속도 빠름, 용량적음
  • 주기억장치
    • RAM을 뜻한다. 휘발성, 속도 보통, 용량 보통
    • 램은 하드디스크로 부터 일정량의 데이터를 복사 → 임시저장 → 필요시 cpu에 전달
  • 저장장치(HDD, SSD)/보조기억장치
    • 비휘발성, 속도 낮음, 용량 높음

캐시

  • 데이터를 미리 복사해 놓는 임시 저장소
  • 빠른 장치와 느린 장치에서 속도 차이에 따른 병목현상을 줄이기 위한 메모리

시간 지역성

  • 최근 사용한 데이터에 다시 접근하려는 특성

공간 지역성

  • 최근 접근한 데이터를 이루고 있는 공간이나 가까운 공간에 접근하는 특성

캐시 히트

  • 캐시에서 원하는 데이터를 찾는 행위
  • 해당 데이터를 제어장치를 거쳐 가져오게 된다.
  • cpu 내부 버스 기반으로 작동하기 때문에 빠르다

캐시 미스

  • 데이터가 캐시에 없다면 주 메모리로 가서 데이터를 찾아오는 것
  • 시스템 버스 기반으로 작동하기 때문에 느리다.

캐시 매핑

  • 캐시가 히트되기 위해 매핑하는 방법
  • CPU의 레지스터와 주 메모리 간에 데이터를 주고받을 때를 기반으로 설명
  • 메모리 용량 차이가 나기 때문
    • 직접매핑
      • 처리가 빠르지만 충돌이 잦음
    • 연관매핑
      • 순서를 일치시키지 않고 관련 있는 캐시와 메모리를 매핑
      • 충돌은 적지만 모든 블럭을 탐색해서 속도가 느리다.
    • 집합 연관 매핑
      • 위 두개를 합침 순서를 일치시키지만 집합을 둬서 저장하며 블록화되어 있기 때문에 검색은 좀 더 효율적이다.

웹 브라우저의 캐시

  • 웹 브라우저의 작은 저장소 쿠키
    • 만료기한이 있는 키-값 저장소
  • 로컬 스토리지
    • 만료기한이 없는 키-값 저장소
  • 세션 스토리지
    • 만료기한이 없는 키-값 저장소
    • 탭 단위로 스토리지를 생성하며 탭을 닫을 때 데이터가 삭제된다.

데이터 베이스의 캐싱 계층

  • ex) redis

메모리 관리

  • 운영체제의 역할 중 하나, 한정된 메모리를 극한으로 활용해야 한다.

가상 메모리

  • 메모리 관리 기법의 하나로 실제로 이용 가능한 메모리 자원을 추상화하여 큰 메모리로 보이게 만드는 것을 말한다.
  • 가상주소
    • 가상으로 주어진 주소
    • 메모리 관리 장치(MMU)에 의해 실제주소로 변환
  • 실제주소
    • 실제 메모리에 존재하는 주소
  • 가상 메모리는 가상 주소와 실제 주소가 매핑되어 있고 프로세스의 주소 정보가 들어있는 페이지 테이블로 관리

스와핑

  • 가상 메모리에는 존재하지만 실제 메모리인 RAM에는 현재 없는 데이터나 코드에 접근할 경우 페이지 폴트가 발생
  • 메모리에서 사용하지 않는 영역을 하드디스크로 옮기고 하드디스크의 일부분을 마치 메모리처럼 불러와서 사용하는것 → 페이지 폴트가 일어나지 않은 것처럼 만든다.
  • 페이지 폴트
    • 프로세스의 주소 공간에는 존재하지만 ram에 없는 데이터에 접근했을 경우 발생
  • 페이지
    • 가상 메모리를 사용하는 최소 크기 단위
  • 프레임
    • 실제 메모리를 사용하는 최소 크기 단위

스레싱

  • 메모리의 페이지 폴트율이 높은 것을 의미한다.
  • 심각한 성능 저하 초래
  • 메모리에 너무 많은 프로세스가 동시에 올라가게 되면 스와핑이 많이 일어나서 발생
  • cpu이용률이 낮아진다. 낮아지면 os는 가용성을 높이기 위해 더 많은 프로세스를 메모리에 올린다.
  • 메모리를 늘리거나 HDD를 사용한다면 SSD로 바꾸는 방법이 있다.
  • 운영체제에서 이를 해결할 수 있는 방법
    • 작업 세트
      • 프로세스의 과거 사용 이력인 지역성을 통해 결정된 페이지 집합을 만들어서 미리 메모리에 로드하는것.
      • 미리 메모리에 로드하면 탐색에 드는 비용을 줄이고 스와핑 또한 줄일 수 있다.
    • PFF
      • 페이지 폴트 빈도를 조절하는 방법 상한선과, 하한선을 만드는 방법
      • 상한선에 도달한다면 프레임을 즐리고 하한선에 도달한다면 프레임을 줄인다.

메모리 할당

  • 메모리에 프로그램을 할당할 때는 시작 메모리 위치, 메모리의 할당 크기를 기반으로 할당하는데, 연속 할당과 불연속 할당으로 나뉜다.
  • 연속할당
    • 메모리에 연속적으로 공간을 할당하는 것을 말한다.
      • 고정 분할 방식
        • 메모리를 미리 나누어 관리하는 방식
        • 내부 단편화 발생
          • 메모리를 나눈 크기보다 프로그램이 작아서 들어가지 못하는 공간이 발생하는 현상
      • 가변 분할 방식
        • 매 시점 프로그램의 크기에 맞게 동적으로 메모리를 나눠 사용
        • 외부 단편화 발생
          • 메모리를 나눈 크기보다 프로그램이 커서 들어가지 못하는 공간이 많이 발생하는 현상
        • 최초 적합
          • 시작 지점부터 홀을 찾으면 바로 할당
        • 최적 적합
          • 프로세스의 크기 이상인 공간 중 가장 작은 홀부터
        • 최악 적합
          • 프로세스의 크기와 가장 차이가 많이는 홀에 할당
  • 불연속 할당
    • 현대 운영체제가 쓰는 방법
    • 페이징
      • 동일한 크기의 페이지 단위로 나누어 메모리의 서로 다른 위치에 프로세스를 할당한다.
      • 주소 변환이 복잡해진다.
    • 세그멘테이션
      • 프로세스는 코드, 데이터, 스택, 힙 등으로 이뤄지는데, 코드와 데이터 등 이를 기반으로 나눌 수 있으며 함수 단위로 나눌 수 있음을 의미한다.
      • 공유, 보안 측면에서 좋고, 홀 크기가 균일하지 않은 문제가 발생
    • 페이지드 세그멘테이션
      • 공유나 보안을 의미 단위의 세그먼트로 나누고, 물리적 메모리는 페이지로 나누는 것

페이지 교체 알고리즘

  • 메모리는 한정되어 있기 때문에 스와핑이 많이 일어난다. 스와핑은 많이 일어나지 않도록 설계되어야 하며 이는 페이지 교체 알고리즘을 기반으로 스와핑이 일어난다.
  • FIFO
    • 가장 먼저 온 페이지를 교체 영역에 가장 먼저 놓는 방법을 의미한다.
  • LRU(least Recentle Used)
    • 참조가 가장 오래된 페이지를 바꾼다.
  • NUR(Not Used Recently)
    • 시계방향으로 탐색하며 최근 참조되지 않은 프로세스를 교체하고 체크하는 방법?
  • LFU(Least Frequently Used)
    • 가장 참조 횟수가 적은 페이지를 교체

'Computer science > 운영체제' 카테고리의 다른 글

프로세스  (0) 2023.08.10

Reactive streams 구현 라이브러리

  • Project reactor
  • RXJava
  • Mutiny

Project reactor

  • Pivotal 사에서 개발
  • Spring reactor에서 사용
  • Mono와 Flux publisher 제

Project reactor - Flux

  • 0..n개의 item을 전달
  • 에러가 발생하면 error signal 전달하고 종료
  • 모든 item을 전달했다면 complete signal 전달하고 종료
  • backPressure 지원

Project reactor - Mono

  • 0..1개의 item을 전달
  • 에러가 발생하면 error signal 전달하고 종료
  • 모든 item을 전달했다면 complete signal 전달하고 종료

Flux에서 하나의 값만 넘겨주면 되는데 Mono가 필요한가?

  • Mono는 1개의 item만 전달하기 때문에 next 하나만 실행하면 complete가 보장된다.
  • 혹은 전달하지 않고 complete를 하면 값이 없다는 것을 의미한다.
  • 하나의 값이 있거나 없다
    • Optinal
  • Mono<T> : Optinal<T>
    • 없거나 혹은 하나의 값
    • Mono<Void>로 특정 사건이 완료되는 시점을 가리킬 수도 있다.
  • Flux<T> : List<T>
    • 무한하거나 유한한 여러개의 값

RxJava

  • Netflix 에서 개발
  • 닷넷 프레임워크를 지원하는 Reactive Extensions를 포팅
  • Flowable, Observable, Single, Maybe, Completable, publisher 제공

RxJava - Flowable

  • 0..n개의 item을 전달
  • 에러가 발생하면 error signal을 전달하고 종료
  • 모든 item을 절달했다면 complete signal 전달하고 종료
  • backPressure 지원
  • Reactor의 Flux와 유사

RxJava - Observable

  • 0..n개의 item을 전달
  • 에러가 발생하면 error signal을 전달하고 종료
  • 모든 item을 절달했다면 complete signal 전달하고 종료
  • backPressure 지원X

RxJava - Single

  • 1개의 item을 전달 후 바로 onComplete signal 전달
  • 1개의 item이 없다면 onError signal 전달
  • 에러가 발생했다면 onError signal 전달

RxJava - Maybe

  • 1개의 item을 전달 후 바로 onComplete signal 전달
  • 1개의 item이 없어도 onComplete signal 전달 가능
  • 에러가 발생했다면 onError singal 전달
  • Reactor의 Mono와 유사

RxJava - Completable

  • onComplete 혹은 onError signal만 전달
  • 값이 아닌 사건을 전달

'웹프로그래밍 > WebFlux' 카테고리의 다른 글

Reactive Programming  (0) 2023.07.21
Reactive manifesto  (0) 2023.07.05
CompletionStage 인터페이스  (0) 2023.07.03
Future 인터페이스  (0) 2023.06.13
blocking과 non-blocking의 차이(I/O 관점)  (0) 2023.06.12

일반적인 서비스

  • 객체는 다른 객체를 직접 호출하고 데이터를 받는다. == 동기
  • 경계가 무너지고 구성요소의 독립적인 실행이 보장되지 않으며 복원력, 유연성 모두 위협을 받게 됨
  • Reactive manifesto를 적용한다면?

동기 stream

  • callee는 caller에게 응답이 아닌 stream을 제공한다.
  • callee는 각각의 값을 stream을 통해서 전달한다.
  • caller는 해당 stream을 collect하여 처리한다.

stream을 이용한 흐름

  • 구성 요소는 서로 비동기적으로 메시지를 주고 받으며, 독립적인 실행을 보장
    • caller는 collect를 통해서 값을 조회해야 한다.
      • caller와 callee를 동기적으로 동작
  • 메시지 큐를 생성하고 배압을 적용하여 부하를 관리하고 흐름을 제어한다.
    • stream이 메시지 큐의 역할을 하지만, 부하를 관리할 수 없다

비동기 future

  • callee는 caller에게 응답이 아닌 future를 제공
  • callee는 각각의 값을 future를 통해서 전달한다.
  • caller는 해당 future를 chaining 하여 이를 처리한다.

future를 이용한 흐름

  • 구성 요소는 서로 비동기적으로 메시지를 주고 받으며, 독립적인 실행을 보장
    • caller와 callee는 비동기적으로 동작한다.
  • 메시지 큐를 생성하고 배압을 적용하여 부하를 관리하고 흐름을 제어한다.
    • future는 메시지 큐의 역할을 할 수 없고, 부하를 관리할 수 없고, 배압도 적용할 수 없다.

Reactive streams

  • callee는 caller에게 응답이 아닌 publisher를 제공
  • callee는 각각의 값을 publisher를 통해서 전달한다.
  • caller는 해당 publisher를 subscribe하거나 다른 caller에게 전달한다.
  • caller는 subscriber를 등록하여 back-pressure를 조절하여 처리 가능한 만큼 전달 받는다.

Reactive streams을 이용한 흐름

  • 구성 요소는 서로 비동기적으로 메시지를 주고 받으며, 독립적인 실행을 보장
    • callee는 publisher를 반환하고 caller를 subscriber를 등록한다. 이 과정에서 caller와 callee는 비동기적으로 동작한다.
  • 메시지 큐를 생성하고 배압을 적용하여 부하를 관리하고 흐름을 제어한다.
    • publisher는 메시지 큐를 생성해서 부하를 관리하고 흐름을 제어한다. back-pressure를 조절할 수 있는 수단을 제공한다.

Reactive programming

  • 비동기 데이터 stream을 사용하는 패러다임
  • 모든 것이 이벤트로 구성되고 이벤트를 통해 전파되어야 한다.
    • event-driven 해야 한다.
    • 데이터의 전달, 에러, 완료 까지 모두 이벤트로 취급
  • Reactive manifesto의 Responsive,Resilient, Elastic, Message Driven 까지 모두 해당

'웹프로그래밍 > WebFlux' 카테고리의 다른 글

Reactive Streams 구현 라이브러리  (0) 2023.07.24
Reactive manifesto  (0) 2023.07.05
CompletionStage 인터페이스  (0) 2023.07.03
Future 인터페이스  (0) 2023.06.13
blocking과 non-blocking의 차이(I/O 관점)  (0) 2023.06.12

TCP/IP 4계층 모델

  • 인터넷 프로토콜 스위트는 인터넷에서 컴퓨터들이 서로 정로블 주고 받는데 쓰이는 프로토콜의 집합이며, 이를 TCP/IP 4계층 모델로 설명하거나 OSI 7계층 모델로 설명하기도 한다.
  • TCP/IP 4계층 모델은 네트워크에서 사용되는 통신 프로토콜의 집합으로 계층들은 프로토콜의 네트워킹 범위에 따라 네 개의 추상화 계층으로 구성된다.

계층 구조

  • OSI 7계층은 애플리케이션 계층을 세 개로 쪼개고 링크 계층을 데이터링크, 물리 계층으로 나눠서 표현하는 것이 다르며, 인터넷 계층을 네트워크 계층으로 부른다.
  • 이 계층들은 특정 계층이 변경되었을 떄 다른 계층이 영향을 받지 않도록 설계되었다. 예를들어 TCP를 UDP로 변경한다고 해서 웹 브라우저를 다시 설치해야 하는 것은 아니듯 유연하게 설계되었다.

애플리케이션 계층

  • FTP,HTTP,SSH,SMTP,SSH,DNS 등 응용 프로그램이 사용되는 프로토콜 계층이며 웹 서비스, 이메일 등 서비스를 실질적으로 사람들에게 제공하는 계층이다.
  • FTP
    • 장치와 장치 간의 파일을 전송하는 데 사용되는 표준 통신 프로토콜
  • SSH
    • 보안되지 않은 네트워크에서 네트워크 서비스를 안전하게 운연하기 위한 암호화 네트워크 프로토콜
  • HTTP
    • World Wide Web을 위한 데이터 통신의 기초이자 웹 사이트를 이용하는데 쓰는 프로토콜
  • SMTP
    • 전자 메일 전송을 위한 인터넷 표준 통신 프로토콜
  • DNS
    • 도메인 이름과 IP 주소를 매핑해주는 서버

전송 계층

  • 송신자와 수신자를 연결하는 통신 서비스를 제공하며 연결 지향 데이터 스트림 지원, 신뢰성, 흐름 제어를 제공할 수 있으며 애플리케이션과 인터넷 계층 사이의 데이터가 전달될 때 중계 역할을 한다. 대표적으로 TCP,UDP가 있다.
  • TCP
    • 패킷 사이의 순서를 보장하고 연결지향 프로토콜을 사용해서 연결을 하여 신뢰성을 구축해서 수신여부를 확인하며 ‘가상회선 패킷 교환 방식’을 사용한다.
      • 가상회선 패킷 교환 방식
        • 각 패킷에는 가상회선 식별자가 포함되며 모든 패킷을 전송하면 가상회선이 해제되고 패킷들은 전송된 순서대로 도착하는 방식을 말한다.
      • TCP연결 성립 과정
        • TCP는 신뢰성을 확보할 떄 3-way handshake라는 작업을 진행한다.
          1. SYN 단계
            • 클라이언트는 서버에 클라이언트의 ISN을 담아 SYN을 보낸다. ISN은 새로운 TCP 연결의 첫 번째 패킷에 할당된 임의의 시퀀스 번호를 말한다.
          2. SYN+ACK 단계
            • 서버는 클라이언트의 SYN을 수신하고 서버의 ISN을 보내며 승인번호로 클라이언트의 ISN+1을 보낸다.
          3. ACK 단계
            • 클라이언트는 서버의 ISN+1한 값인 승인번호를 담아 ACK를 서버에 보낸다.
      • TCP연결 해제 과정
        • TCP는 연결을 해제할 때는 4-way handshake 과정이 발생
          1. 클라이언트가 연결을 닫으려고 할 때 FIN으로 설정된 세그먼트를 보낸다. 그 후 FIN_WAIT_1상태로 들어가고 서버의 응답을 기다린다.
          2. 서버는 클라이언트로 ACK라는 승인 세그먼트를 보내고, CLOSE_WAIT 상태에 들어간다. 클라이언트가 세그먼트를 받으면 FIN_WAIT_2 상태에 들어간다.
          3. 서버는 ACK를 보내고 일정 시간 이후에 클라이언트에 FIN이라는 세그먼트를 보낸다.
          4. 클라이언트는 TIME_WAIT 상태가 되고 다시 서버로 ACK를 보내서 서버는 CLOSED 상태가 되고 클라이언트는 어느 정도의 시간을 대기한 후 연결이 닫히고 클라이언트와 서버의 모든 자원의 연결이 해제된다.
        • 이 과정 중 가장 눈 여겨 봐야할 것은 TIME_WAIT이다. 그냥 연결을 닫으면 되지 왜 굳이 일정 시간 뒤에 닫을까?
          1. 지연 패킷이 발생할 경우를 대비하기 위함
            • 패킷이 뒤늦게 도달하고 이를 처리하지 못한다면 데이터 무결성 문제가 발생
          2. 두 장치가 연결이 닫혔는지 확인하기 위함
            • LAST_ACK 상태에서 닫히게 되면 다시 새로운 연결을 하려고 할 때 장치는 줄곧 LAST_ACK로 되어 있기 떄문에 오류가 발생
  • UDP
    • 순서를 보장하지 않고, 수신 여부를 확인하지 않으며 단순히 데이터만 주는 ‘데이터그램 패킷 교환 방식’을 사용한다.
      • 데이터그램 패킷 교환 방식
        • 패킷이 독립적으로 이동하며 최적의 경로를 선택하여 가는데, 하나의 메시지에서 분할된 여러 패킷은 서로 다른 경로로 전송될 수 있으며 도착한 순서가 다를 수 있는 방식을 말한다.

인터넷 계층

  • 인터넷 계층은 장치로부터 받은 네트워크 패킷을 IP주소로 지정된 목적지에 전송하기 위해 사용되는 계층이다.
  • IP, ARP, ICMP 등이 있으며 패킷을 수신해야 할 상대의 주소를 지정하여 데이터를 전달한다. 상대방이 제대로 받았는지에 대해 보장하지 않는 비연결형적인 특징을 가지고 있다.

링크 계층

  • 전선, 광섬유, 무선 등으로 실질적으로 데이터를 전달하며 장치 간에 신호를 주고받는 규칙을 정하는 계층이다.
  • 물리 계층과 데이터 링크 계층으로 나누기도 하는데 물리 계층은 무선 LAN과 유선 LAN을 통해 0과 1로 이뤄진 데이터를 보내는 계층을 말하며, 데이터 링크 계층은 ‘이더넷 프레임’을 통해 에러 확인, 흐름 제어, 접근 제어를 담당하는 계층을 말한다.

Reactive란?

무언가를 바꾸거나 예방하기 위해 먼저 행동하기 보다는 사건이나 상황에 반응하는

Reactive manifesto

  • 소프트웨어 아키텍처에 대한 선언문
  • Reactive system의 특성을 강조하고 구축에 필요한 가이드라인 제공
  • 4가지의 핵심 가치를 제시

Responsive

  • 요구사항
    • 문제를 신속하게 탐지하고 효과적으로 대처
    • 신속하고 일관성 있는 응답 시간 제공
    • 신뢰할 수 있는 상한성을 설정하여 일관된 서비스 품질을 제공
  • 결과
    • 가능한 한 즉각적으로 응답
    • 사용자의 편의성과 유용성의 기초
    • 오류 처리를 단순화
    • 일반 사용자에게 신뢰를 조성하고, 새로운 상호작용을 촉진

Resilient

  • 요구사항
    • 복제,봉쇄,격리,위임에 의해 실현
    • 장애는 각각의 구성 요소에 포함(봉쇄)
    • 구성 요소들은 서로 분리(격리)
    • 복구 프로세스는 다른 구성요소에 위임(위임)
    • 필요한 경우 복제를 통해 고가용성이 보장(복제)
  • 결과
    • 장애에 직면하더라도 응답성을 유지
    • 시스템이 부분적으로 고장이 나더라도, 전체 시스템을 위험하게 하지 않고 복구 할 수 있도록 보장
    • 구성 요소의 클라이언트는 장애를 처리하는데에 압박을 받지 않습니다.

Elastic

  • 요구사항
    • 경쟁하는 지점이나 중앙 집중적인 병목 현상이 존재하지 않도록 설계
    • 구성 요소를 샤딩하거나 복제하여 입력을 분산
    • 실시간 성능을 측정하는 도구를 제공
    • 응답성 있고 예측 가능한 규모 확장 알고리즘을 지원
  • 결과
    • 작업량이 변화하더라도 응답성을 유지
    • 입력 속도의 변화에 따라 이러한 입력에 할당된 자원을 증가시키거나 감소
    • 상품 및 소프트웨어 플랫폼에 비용 효율이 높은 방식으로 유연성을 제

Message Driven

  • 요구사항
    • 비동기 메시지 전달에 의존
    • 명시적인 메시지 전달
    • 위치 투명 메시징을 통신 수단으로 사용
    • 논블로킹 통신
  • 결과
    • 구성 요소 사이에서 느슨한 결합, 격리, 위치 투명성을 보장하는 경계를 형성. 이 경계는 장애를 메시지로 지정하는 수단을 제공
    • 시스템에 메시지 큐를 생성하고, 모니터링하며 필요시 배압을 적용
    • 유연성을 부여하고, 부하 관리와 흐름제어를 가능하게
    • 단일 호스트든 클러스터를 가로지르든 동일한 구성과 의미를 갖고 장애를 관리
    • 수신자가 활성화가 되어 있을 때만 자원을 소비할 수 있기 때문에 시스템 부하를 억제
  • 정리
    1. 비동기 통신
      1. 구성 요소는 서로 비동기적으로 메시지를 주고 받으며, 독립적인 실행을 보장
    2. 메시지 큐
      1. 메시지 큐를 생성하고 배압을 적용하여 부하를 관리하고 흐름을 제어한다.
    3. 복원력
      1. 구성 요소 사이에 경계를 형성하여 직접적인 장애의 전파를 막고 장애를 메시지로 지정하여 위치와 상관없이 동일하게 장애를 관리한다.
    4. 탄력성
      1. 구성 요소 사이에 경계를 형성하여 각각의 구성 요소를 독립적으로 확장 가능하게 만들고, 자원을 더 쉽게 추가하거나 제거한다.

Reactive manifesto

가능한 한 즉각적으로 응답

장애에 직면하더라도 응답성을 유지

작업량이 변화하더라도 응답성을 유지

비동기 non-blocking 기반의 메시지 큐를 사용하여 통신

'웹프로그래밍 > WebFlux' 카테고리의 다른 글

Reactive Streams 구현 라이브러리  (0) 2023.07.24
Reactive Programming  (0) 2023.07.21
CompletionStage 인터페이스  (0) 2023.07.03
Future 인터페이스  (0) 2023.06.13
blocking과 non-blocking의 차이(I/O 관점)  (0) 2023.06.12

 

CompletionStage 인터페이스

ForkJoinPool - thread pool

  • CompletableFuture은 내부적으로 비동기 함수들을 실행하기 위해 ForkJoinPool을 사용
  • ForkJoinPool의 기본 size = 할당된 코어 -1
  • 데몬 쓰레드
    • main 스레드가 종료되면 즉각적으로 종료

ForkJoinPool - fork & join

  • Task를 fork를 통해서 subtask로 나누고
  • Thread pool에서 steal work 알고리즘을 이용해서 균등하게 처리
  • join을 통해서 결과를 생성

CompletionStage 연산자

CompletionStage 연산자 조합

  • 50개에 가까운 연산자들을 활용하여 비동기 task들을 실행하고 값을 변형하는 등 chaining을 이용한 조합 가능
  • 에러를 처리하기 위한 콜백 제공

then**[Async] 차이

  • stage에 상태에 따라 caller 쓰레드에서 action을 수행 하거나 callee 쓰레드에서 action을 실행 하는 등 파악하기 어렵다.
  • 하지만 then**Async에서는 thread pool에 있는 쓰레드에서 action을 실행(항상)
  • 모든 then**Async 연산자는 executor를 추가 인자로 받는다.
    • 이를 통해 다른 쓰레드풀로 task를 실행할 수 있다.

thenAccept[Async]

  • Consumer를 파라미터로 받는다.
  • 이전 task로부터 값은 받지만 넘기지 않는다.
  • 다음 task에게 null이 전달된다.
  • 값을 받아서 action만 수행하는 경우 유용

thenApply[Async]

  • Function을 파라미터로 받는다.
  • 이전 task로부터 T 타입의 값을 받아서 가공하고 U타입의 값을 반환한다.
  • 다음 task에게 반환했던 값이 전달된다.
  • 값을 변형해서 전달해야 하는 경우 유용

thenCompose[Async]

  • Function을 파라미터로 받는다.
  • 이전 task로 부터 T타입을 받아서 가공하고 U타입의 ComletionStage를 반환한다.
  • 반환한 CompletionStage가 done 상태가 되면 값을 다음 task에 전달한다.
  • 다른 future를 반환해야하는 경우 유용

thenRun[Async]

  • Runnable을 파라미터로 받는다.
  • 이전 task로부터 값을 받지 않고 값을 반환하지 않는다.
  • 다음 task에게 null이 전달된다.
  • future가 완료되었다는 이벤트를 기록할 때 유용

exceptionally

  • Function을 파라미터로 받는다.
  • 이전 task에서 발생한 exception을 받아서 처리하고 값을 반환한다.
  • 다음 task에게 반환된 값을 전달한다.
  • future 파이프에서 발생한 에러를 처리할 때 유용

 

+ Recent posts