소프트웨어: 가상화의 여행 (2) 스토리지(메모리, 하드디스크)
🤔 이 글의 출발점
모든 S/W 는 세단계로 정의할 수 있습니다. Input 값과 Output 값, 그리고 Input 값을 원하는 Output 값으로 만들기 위한 알고리즘으로요!
이런식으로 여러 IT 기술들의 철학, 구성이 하나의 청사진(Blue Print)으로 수렴하는 경우가 많은 것 같습니다. 소프트웨어 시리즈 글은 컴퓨터를 공부하는 분들과 이런 인사이트를 공유하며 함께 생각해보고 싶어 작성했습니다. 그럼 이번 글도 고고띵~
(수정이 필요한 부분은 꼭 알려주시면 감사하겠습니다! 😊)
목차
[H/W]
- 실제 구성
- 메모리 계층 구조
- 지역성 원리
- Register
- Cache Memory
- Main Memory
- Disk
- Network Cloud[프로그래머를 위한 가상화]
- Virtual Memory
- 메모리 관리[성능을 위한 가상화]
- Partitioning
- Sharding[서비스를 위한 가상화]
- CDN: 정적 리소스 캐싱
- Redis, Memcached: 응답과 데이터베이스 쿼리 결과 캐시
- 클라우드 블록 스토리지
H/W
실제 구성
메모리 계층 구조
- Trade-Off: 메모리 연산 속도 ← → 크기
- CPU 와 연산 속도를 맞추기 위해, 연산 속도가 높은 메모리 구조를 CPU 와 가까운 위치에 둠.
지역성 원리 (Locality)
- 시간 지역성: 최근 접근한 데이터에 다시 접근하는 경향
- 공간 지역성: 최근 접근한 데이터의 주변 공간에 다시 접근하는 경향
Register [CPU의 구성 요소]
- 고속 기억장치임
- 명령어 주소, 코드, 연산에 필요한 데이터, 연산 결과 등을 임시로 저장
- 용도에 따라 범용 레지스터와 특수목적 레지스터로 구분됨
- 중앙처리장치 종류에 따라 사용할 수 있는 레지스터 개수와 크기가 다름
[종류]
- 범용 레지스터 : 연산에 필요한 데이터나 연산 결과를 임시로 저장
- 특수목적 레지스터 : 특별한 용도로 사용하는 레지스터
→ MAR(메모리 주소 레지스터) : 읽기와 쓰기 연산을 수행할 주기억장치 주소 저장
→ MBR(메모리 버퍼 레지스터) : 주기억장치에서 읽어온 데이터 or 저장할 데이터 임시 저장
→ IR(명령어 레지스터) : 현재 실행 중인 명령어 저장
→ PC(프로그램 카운터) : 다음에 수행할 명령어 주소 저장
→ AC(누산기) : 연산 결과 임시 저장
Cache Memory
- CPU 코어와 메모리 사이의 병목 현상 완화
[ 캐시 Miss ]
- Cold miss: 해당 메모리 주소를 처음 불러서 나는 Miss
- Conflict miss: A와 B가 같은 캐시 메모리 주소에 할당되어 있어서 나는 Miss (driect mapped cache에서 많이 발생)
- Capacity miss: 캐시 메모리의 공간이 부족해서 나는 Miss
[ 블록 사상 방식: 메모리에서 읽는 블록이 저장될 캐시의 위치를 결정 ]
- Direct Mapped Cache: DRAM의 여러 주소가 캐시 메모리의 한 주소에 대응되는 다대일 방식. 캐시메모리는
인덱스 필드 + 태그 필드 + 데이터 필드
로 구성된다. - Fully Associative Cache: 비어있는 캐시 메모리가 있으면, 마음대로 주소를 저장하는 방식. 저장할 때는 매우 간단하지만, 찾을 때가 문제. Full Scan
- Set Associative Cache: Direct + Fully 방식. 특정 행을 지정하고, 그 행안의 어떤 열이든 비어있을 때 저장하는 방식이다.
→ Direct에 비해 검색 속도는 느리지만, 저장이 빠르고 Fully에 비해 저장이 느린 대신 검색이 빠른 중간형이다.
Main Memory
- 명령어 집합에 의해 정의된 메모리로서 실행될 프로그램과 데이터가 머무는 장소
- DRAM(Dynamic Random Access Memory): 집적도가 높다.
- SRAM: 접근 속도가 빨라 캐시 메모리로 사용된다.
Disk
- 보조기억장치
- 주기억 장치 보다 속도는 느리지만 저장 용량이 상대적으로 크다.
- 전원이 차단 돼도 내용이 그대로 유지된다(영구적으로 보관).
Cloud
최근에는 Network 기술의 발전으로 원격 스토리지를 사용할 수 있다.
프로그래머를 위한 가상화
프로그래머가 생각하는 메모리: Register, Virtual memory
(OS + 가상 메모리를 지원하는 CPU 가 제공하는 가상화)
Virtual Memory
[ TLB(MMU) ]
- 프로그램: 자신의 가상의 private memory 를 가지고 있다
- 각 프로세스마다 자신의 메모리를 가지고 있다
- 가상 메모리 명령어나 데이터: 프로그램의 주소(virtual address)[ 데이터의 주소 ]
- Virtual Address: The address of a program
- Physical Address: The address of a DRAM
[ 가상 메모리 기능 ]
- Large Address Space
- Protection
- Sharing
- Portability
- Increased CPU utilization
[요구 페이징]
- 가상 메모리는 요구 페이징 기법을 통해 필요한 페이지만 메모리에 적재하고 사용하지 않는 부분은 그대로 둔다.
- 특정 페이지에 대해 CPU의 요청이 들어온 후에야 해당 페이지를 메모리에 적재하며, 한번도 접근되지 않은 페이지는 물리적 메모리에 적재되지 않는다.
- 이를 통해 메모리 사용량이 감소하고 프로세스 전체를 메모리에 올리는데 들었던 입출력 오버헤드가 감소하며 응답시간이 단축된다.
- 유효, 무효 비트를 두어 각 페이지가 메모리에 존재하는지 표시한다.
- 유효 : 페이지가 메모리에 적재됨.
- 무효 : 페이지가 현재 메모리에 없는 경우이거나 그 페이지가 속한 주소 영역을 프로세스가 사용하지 않는 경우
- CPU가 참조하려는 페이지가 현재 메모리에 올라와 있지 않아 무효로 세팅되어 있는 경우를
'페이지 부재'
가 일어났다고 한다.
[페이지 교체]
- 페이지 부재가 발생하면 요청된 페이지를 디스크에서 메모리로 읽어와야 한다. 이때 물리적 메모리에 빈 프레임이 존재하지 않을 수 있다.
- 이 경우, 메모리에 올라와있는 페이지 중 하나를 디스크로 쫓아내고 메모리에 빈 공간을 확보하는 작업이 필요하다. 이를 페이지 교체라고 한다.
- 페이지 교체를 할 때, 어떤 프레임에 있는 페이지를 쫓아낼 것인지 결정하는 알고리즘을 페이지 교체 알고리즘이라 하며, 목표는 페이지 부재율을 최소화하는 것이다.
메모리 관리
운영체제 만이 운영체제 메모리 영역과 사용자 메모리 영역의 접근에 제약을 받지 않음
- Swapping: 주 기억장치(RAM)으로 불러오는 과정을 swap-in, 보조 기억장치로 내보내는 과정을 swap-out.
→ Swap 알고리즘: FIFO, LIFO, round-robin… - Fragmentation: 프로세스들이 차지하는 메모리 틈 사이에 사용 하지 못할 만큼의 작은 자유공간들이 늘어나게 되는 것
→ 외부 단편화: 메모리 공간 중 사용하지 못하게 되는 일부분, 압축으로 해결
→ 내부 단편화: 프로세스가 사용하는 메모리 공간 에 포함된 남는 부분
[ 단위 ]
- frame: a first-length block of main memory
- page: 메모리 Transfer의 단위
- segment: 논리적 내용의 단위
[ 가상 메모리 이전 메모리 관리 ]
- Fixed Partitioning: Overlay 이용, 메모리에 로드할 수 있는 프로세스 수 제한
- Dynamic Partitioning: Overlay 이용, 메모리에 여러 프로세스 수를 로드할 수 있으나, External Fragmentation이 생기고, 나중에 Compaction 해야 함.
[ 가상 메모리 이후 메모리 관리 ]
가상 메모리
는 메모리에 로드된 즉, 실행중인 프로세스가 가상의 공간을 참조하여 마치 커다란 물리 메모리를 갖고 있는 것처럼 사용할 수 있도록 하는 것이다.- 간단하게 말해 실제 메모리 주소가 아닌 가상의 메모리 주소를 주는 방식이다.
- 페이징과 세그멘테이션이 있다.
[ 페이징 ]
- 프로세스의 주소 공간을 동일한(고정된) 사이즈의 페이지 단위로 나누어 물리적 메모리에 불연속적으로 저장하는 방식
- 메모리는
Frame
이라는 고정 크기로 분할되고, 프로세스는Page
라 불리는 고정 크기로 분할된다. - 메모리상에서 여러 곳에 흩어진 프로세스를 수행하기 위해 MMU를 통해 논리 주소와 물리 주소를 나누어 사용함으로써 CPU를 속여야 한다.
- 프로세스를 정상적으로 사용하기 위해 MMU의 재배치 레지스터를 여러 개 사용해서 위의 그림과 같이 각 페이지의 실제 주소로 변경해준다. 이러한 여러 개의 재배치 레지스터를
페이지 테이블(Page Table)
이라 한다. - 실제 메모리는 전혀 연속적이지 않는데, CPU는 연속적으로 사용하고 있다는 것을 보장받으며 정상적으로 수행한다.
- 단점: 내부 단편화
[ 세그멘테이션 ]
- 프로세스를 서로 크기가 다른 논리적인 블록 단위인 ‘세그먼트(Segment)’로 분할하고 메모리에 배치하는 것을 말하며, 각 세그먼트의 크기는 일정하지 않다.
- 프로세스를 Code + Data + Stack 영역으로 나누는 것 역시 세그멘테이션의 모습이다. 물론, code, data, stack 각각 내부에서 더 작은 세그먼트로 나눌 수도 있다.
- 세그먼테이션을 위한 테이블은 세그먼트 테이블이라고 한다.
- 세그먼트 테이블은 세그먼트 번호와 시작 주소, 세그먼트 크기를 엔트리로 갖는다.
- 세그먼트에서 주소변환 역시, 페이징과 유사하다. 한 가지 주의할 점은 세그먼트의 크기는 일정하지 않기 때문에, 테이블에 limit 정보가 주어진다. 그리고 CPU에서 해당 세그먼트의 크기를 넘어서는 주소가 들어오면 인터럽트가 발생해서 해당 프로세스를 강제로 종료시킨다.
- 단점: 외부 단편화
성능을 위한 가상화
사용자에게 투명성을 제공해야 한다.
Partitioning
- 비용: Full Scan
- WHAT: 관리하기 쉬운 Partition 이라는 작은 단위로 물리적 분할하는 것
- 특정 DML 과 Query 의 성능 향상 [ I/O, Lock 으로 인한 경합을 줄인다 ]
- 각 분할 영역(partition 별)을 독립적으로 백업하고 복구
- 가용성 및 관리 용이성 증가
- ❗️ JOIN 비용
- Horizontal Partitioning
Schema 를 복제한 후 Shard Key 를 기준으로 데이터를 나누는 것
❗️서버 간의 연결 과정이 많아진다. 데이터를 찾는 과정에서 latency 증가
❗하나의 서버가 고장나게 되면, 데이터의 무결성이 깨질 수 있다. - Vertical Partitioning [ HotSpot 컬럼 ]
이미 정규화된 하나의 Entity 를 2개 이상으로 분리하는 작업
→ I/O 측면에서 봤을 때, 필요한 Column만 올리면 메모리 상 이점
Sharding
- 비용: Full Scan 및 Hot Spot
- WHAT: 같은 테이블 스키마를 가진 데이터를 다수의 DB 에 분산 저장
- ❗️프로그래밍, 운영적인 복잡도
→ Data 를 어떻게 Read ? 어떻게 분산 ? Trade Off: Locator와 Sync - ❗️속도 → Cross-Partition Query: 기존의 Query 보다 느릴 수 있다
→ 분산된 DB 에 접근하기 위한 논리적인 작업은 라우터가 담당
[ Modular Sharding ]
- PK를 연산한 결과로 DB를 특정하는 방식
- 장점: Range Sharding 에 비해 데이터가 균일하게 분산된다.
- 단점: DB를 추가 증설하는 과정에서 이미 적재된 데이터의 재정렬이 필요
- Hash Sharding, Dynamic Sharding
[ Range Sharding ]
- PK 의 범위를 기준으로 DB를 특정하는 방식
- 장점: Modular Sharding 비해 증설에 재정렬 비용이 들지 않는다.
- 단점: 일부 DB 에 데이터가 몰릴 수 있다.
서비스를 위한 가상화
사용자에게 투명성을 제공해야 한다.
CDN: 정적 리소스 캐싱
- 지리,물리적으로 떨어져 있는 사용자에게 컨텐츠를 더 빠르게 제공할 수 있는 기술
- HTTP 통신에 최적화되어 있고, 캐시 기능을 제공하고, 네트워크 라우팅 기능은 물론 보안 기능까지 두루 갖춤
→ 국제적으로 서비스하려는 시스템에 반드시 필요한 구성요소 - CDN의 디스트리뷰션 설정: 캐시의 수명을 제어하는 TTL
- HTTP 헤더: Cache-Control(캐시가 유효한 기간, 우선시), Expires(캐시가 무효화되는 시점)
- HTTP 헤더: Forward Cookies로 캐시 여부 확인
Redis, Memcached: 응답과 데이터베이스 쿼리 결과 캐시
- 일반적으로 마스터/슬레이브 모드에서 분간 배포
- 데이터가 너무 오래 보관되지 않도록 적절한 만료 시간을 설정
→ 가장 일반적으로 요청되는 콘텐츠를 로드하고 캐시할 때 사용 - 효율이 잘 설계된 캐시는 시스템 부하를 최소화하며 인위적으로 시스템의 부하는 증가시키고 성능을 감소시키는 다중적인 중복작업을 방지한다.
- Redis는 메모리(RAM)에 저장해서 디스크 스캐닝이 필요없어 매우 빠른 장점이 존재함
- RAM 의 휘발성을 막기 위한 백업 과정
→ snapshot : 특정 지점을 설정하고 디스크에 백업
→ AOF(Append Only File) : 명령(쿼리)들을 저장해두고, 서버가 셧다운되면 재실행해서 다시 만들어 놓는 것
클라우드 블록 스토리지(Azure)
- Azure Managed Disks
→ 스토리지 계정 관리를 처리하여 Azure VM을 위한 디스크 관리를 간소화하는 기능
→ 가용성 및 백업 지원
→ 서버쪽 암호와 및 데이터 디스크 암호화 - Azure Disk Storage: Azure VM와 함께 사용하도록 설계됨
→ 네 가지 클라우드용 디스크 스토리지 옵션(Ultra Disk Storage, 프리미엄 SSD, 표준 SSD, 표준 HDD) 중에서 선택
→ Cost-effective Standard Storage.
→ VM > 디스크 창에서 새 디스크 만들기 및 연결을 선택(저장소 유형, 크기, 암호화 및 호스트 캐싱을 엄데이트)
→ 기존 디스크 연결도 가능