직렬/병렬

직렬/병렬

여러 개의 물건이 일직선으로 나열돼 있는 것을 직렬, 두 줄 이상으로 나열돼 있는 것을 병렬이라고 한다.

서버는 물론 PC에도 여러 개의 CPU가 탑재되어 있고, 대규모 웹 서비스에서는 방대한 수의 사용자 요청을 처리해야 하므로 수많은 서버를 배치해서 병렬로 처리하고 있다.

이처럼 주변에는 병렬 처리가 넘쳐나고 있지만, 무조건 병렬화한다고 해서 성능이 향상되는 것은 아니다. 병렬화한 자원을 놀리지 않고 어떻게 효율적으로 활용할지가 중요하다.

중요 사항

직렬 처리로 속도를 올리는 데 한계가 있다.

병렬화를 통해 속도는 빨라지지 않지만, 시간 단위당 처리량을 늘릴 수 있다.

병렬 처리에는 합류점, 직렬화 구간, 분기점이 병목 지점이 되기 쉽다.
병렬화할 때는 일을 분담해서 처리를 한 후 다시 집약할 때 오버헤드가 걸린다. 
그러므로 이 오버헤드를 감안하더라도 효과가 있을 경우에 병렬화를 한다.

어디에 사용되나?

웹 서버와 AP 서버에서의 병렬화

웹 서버에는 다수의 사용자가 접속하기 때문에 복수의 프로세스가 분담해서 병렬 처리하고 있다. AP 서버에서는 JVM 프로세스가 하나이지만 복수의 스레드가 병렬로 처리하고 있다.

하나의 CPU 코어 밖에 없는 서버에서는 프로세스 혹은 스레드를 아무리 늘려도 동시에 실행할 수 있는 것은 1개 뿐이다.

프로세스나 스레드 수를 조정할 때는 CPU 코어 수도 함께 고려해야 한다.

DB 서버에서의 병렬화

오라클 DB에서는 클라이언트 요청을 접수하는 서버 프로세스가 클라이언트 접속 수만큼 생성된다. (서버 프로세스에는 멀티 프로세스 모델 외에도 공유 서버형이라 불리는 하이브리드형이 있음)

데이터 파일 생성 시에 병목 현상이 발생하는 경우, 메모리에 캐시된 갱신 완료 데이터를 HDD에 기록하는 DBWR(DataBase WriteR) 프로세스를 늘려서 병렬화할 수도 있다.

DBWR 프로세스는 프로세스 수를 늘리는 방법 외에도 비동기 I/O를 사용해서 OS 측에서의 쓰기 처리를 병렬화하는 방법도 있다.

정리

직렬과 병렬의 장단점을 정리하면 다음과 같다.

직렬

구조가 간단해서 설계나 구현 난이도가 낮다

복수의 리소스를 유용하게 이용할 수 없다

병렬

복수의 리소스를 유용하게 이용할 수 있으며, 직렬에 비해 동일 시간당 처리를 하 수 있는 양이 증가한다.

또한, 일부가 고장 나더라도 처리를 게속할 수 있다.

처리 분기나 합류를 위한 오버헤드가 발생한다.

배타적 제어 등을 고려해야 하고 구조가 복잡해서 설계나 구현 난이도가 높다.

병렬화는 처리 능력 향상 외에도 이중화라는 관점에서도 장점이 있다. (하나가 고장나도 처리를 계속할 수 있음)

병렬화 시에 주의할 점은 다음과 같다.

병렬화에서는 직렬 처리 성능은 향상되지 않지만, 단위 시간당 처리량을 늘릴 수 있다.
병렬 처리에서는 합류점, 직렬화 구간, 분기점 병목 지점이 되기 쉽다.

병렬화가 유효한 부분을 파악해서 병렬화하지 않으면 효과가 없다. 
오버헤드나 구조 복잡화 등의 단점이 있다는 것을 고려한 후, 
이 단점 이상의 효과를 얻을 수 있는 경우에 병렬화한다.

동기/비동기

(이 절에서의 동기/비동기 설명은 블록/넌블록과 혼동이 오는 설명이라고 생각한다.)

동기, 비동기를 간단히 설명하면, 누군가에게 일을 부탁하고 그 일이 끝나기까지 잠자코 기다리는 것이 동기이고,

‘끝나면 말해'라고 말해 두고 다른 일을 하는 것이 비동기다. 즉, 비동기에서는 처리를 병행해서 진행할 수 있다.

특징

동기는 다른 사람에게 일을 부탁한 후 끝날 때까지 아무것도 하지 않고 기다리기 때문에 그 사이에 다른 것을 할 수 없다. 하지만 의뢰한 것이 끝났는지 여부를 확실하게 확인할 수 있다.

비동기는 끝날 때까지 기다리지 않기 때문에 병렬로 다른 일을 할 수 있다. 하지만 의뢰한 일이 끝났는지 여부를 확인하고 싶으면 별도의 방법을 이해한다.

어디에 사용되나?

Ajax

ajax 등장 이전에는 링크나 버튼을 클릭할 때마다 화면 전체가 바뀌는 것을 기다려야 했다.

하지만 Ajax를 사용한 웹 페이지에서는 비동기 통신이 가능해져서 화면을 보거나 입력하면서 필요한 부분만 갱신할 수 있게 되었다.

DBMS에서 사용되는 비동기 I/O

HDD 등의 저장소에 비동기로 쓰기 처리하는 것을 비동기 I/O라고 한다.

동기 I/O에서는 I/O가 끝날 때까지 프로세스가 다음 처리를 하지 않지만, 비동기 I/O에서는 I/O가 끝나지 않아도 다음 처리를 할 수 있다.

비동기 I/O는 대량의 I/O를 효율적으로 처리해야 하는 DBMS에 적합하다고 할 수 있다.

공유 메모리에 있는 다수의 데이터를 프로세스가 HDD에 기록하는 경우, 비동기 I/O 하나라면 I/O가 끝나기까지 기다리지 않고 다음 I/O를 발행할 수 있기 때문에 저장소 성능을 충분히 활용할 수 있다.

메시지 큐 등을 통한 미들웨어의 비동기 처리

트랜잭션의 범위 설계 -> 트랜잭션 범위 안은 동기, 밖은 비동기 처리

정리

동기/비동기의 장단점은 다음과 같다.

장점

단점

동기

의뢰한 처리가 끝났는지 여부를 쉽게 확인할 수 있어서 구조가 간단하고 구현 난이도도 낮다.

의뢰한 처리가 끝나기까지 기다려야 하기 때문에 대기 시간을 활용할 수 있다

비동기

의뢰한 처리가 진행되고 있는 동안 시간을 효율적으로 사용해서 병렬 처리를 할 수 있다

의뢰한 처리가 끝났는지 확인하지 않으면 모르기 때문에 불필요한 확인 처리가 늘어난다. 구조가 복잡해서 구현 난이도가 높다.

비동기 처리를 사용하는 경우의 주의할 점은 다음과 같다.

비동기로 요구한 처리가 끝나지 않은 상태에서 다음 처리를 진행해도 문제가 없는가
비동기로 요구한 처리가 끝났는지 확인할 필요가 있는가

큐(Queue)는 우리말로 대기 행렬이라 표현할 수 있다.

특징

큐에서는 줄을 설 때는 가장 마지막에 서고, 처리는 선두부터 순서대로 된다. 먼저 들어온 데이터가 먼저 나가는 큐 동작을 FIFO(First In First Out) 방식이라고 한다.

어디에 사용되나?

컴퓨터 세계에서 만들어지는 다양한 행렬

CPU 처리를 기다리고 있는 프로세스나 스레드 행렬
하드디스크 등의 저장소 읽기 처리를 기다리고 있는 I/O 요구 행렬
네트워크 접속 성립을 기다리고 있는 접속 요구 행렬

웹 서버의 CPU 처리를 기다리고 있는 아파치 프로세스

CPU를 기다리고 있는 프로세스 행렬을 런큐(run-queue)라고 한다.
OS 커널에는 프로세스 스케줄러라는 기능이 있어 런큐 등을 관리한다.

데이터베이스의 디스크 I/O

기본적인 개념은 CPU와 같지만, 프로세스나 스레드가 사용하는 대상이 CPU가 아닌 HDD인 점만 다르다.

HDD는 데이터가 기록돼 있는 특정 위치에 액세스해야 하기 때문에 CPU처럼 비어있다는 이유로 다른 것을 사용할 수 없다. → 속도가 느리기 때문에 고속 I/O가 요구되는 데이터에는 적합하지 않다.

캐시라 불리는 메모리를 이용해 성능 고속화 설계가 가능함

메시지 큐

메시지 큐를 사용하면 애플리케이션 간 상호 운용성을 향상시켜 시스템 전체 안정성을 향상시킬 수 있다.

대기 시간 절약이나 버퍼링용 리소스 절약 등에 의해 성능이 향상되는 경우도 있다.

발신자는 수신자의 상황에 개의치 않고 처리 후 메시지 큐에 데이터를 전송하고, 수신자는 본인의 상황에 따라 메시지 큐에서 데이터를 받아 처리 가능

정리

큐의 특징은 선두에서부터 순서대로 처리된다는 점

여러 처리가 동시에 진행되는 경우 자주 사용되며, 다양한 계층의 여러 부분에서 이용되고 있다.

큐 등을 확인하여 처리 지연의 발생 여부를 확인할 수 있다.

배타적 제어

배타적 제어는 문자 그대로 다른 것을 배제하는 제어다. 여러 사람이 공유하는 물건일 경우, 누군가 그 물건을 사용하고 있으면 다른 사람은 그것을 사용할 수 없다. 동시에 사용하게 되면 고장날 수도 있다.

컴퓨터 세계에서도 직렬 처리에서는 배타적 제어가 필요없지만, 병렬 처리에서는 필요하다. 배태적 제어를 하는 부분은 병목 현상이 발생하기 쉽다.

특징

복수의 처리가 공유 자원(CPU, 메모리, 디스크 등)에 동시에 액세스하면 불일치가 발생할 수 있기 때문에 배타적 제어로 보호해 줘야 한다.

배타적 제어에는 특정 처리가 공유 자원을 이용하고 있는 동안 다른 처리가 이용할 수 없게 해서 불일치가 발생하지 않도록 한다.

어디에 사용되나?

DBMS에 사용되는 배타적 제어

오라클 DB에서는 여러 프로세스가 동시에 병행으로 처리하고 있지만, 특정 프로세스가 공유 데이터를 변경하고 있는 도중에 다른 프로세스가 해당 공유 데이터를 읽거나 공유 데이터를 동시에 변경하지 못하도록 배타적 제어를 한다.

DBMS의 배타적 제어에는 매우 짧은 시간 동안만 락(lock)을 유지하는 래치(Latch)라는 것이 있어서 CPU에서 대기하는 방식이 있다. → Spin lock (컨텍스트 스위칭을 줄일 수 있지만, 하나의 CPU 혹은 하나의 코어 시스템에서는 유용하지 않다.)

비교적 장시간 락을 유지하도록 큐를 이용해서 관리하는 방식인 Sleep lock도 있다. (Mutex)

OS 커널에 사용되는 배타적 제어

리눅스 커널은 빅 커널락(Big Kernel Lock)이라 불리는, 하나의 스핀락으로 유지된다.

커널의 BKL이 이용되는 부분에서는 처리가 직렬화돼서 동시에 하나의 CPU만 커널 코드를 실행할 수 있다. 따라서 이 부분이 병목 지점이 되기 쉽다.

클러스터 데이터베이스의 배타적 제어

여러 대의 DB 서버를 조합해서 하나의 데이터베이스로 사용하는 액티브-액티브 클러스터 DB도 배타적 제어가 가능하다.

각 서버에서 병렬 처리를 하면 처리 속도가 올라가지만, 서버 간 배타적 제어에 의해 대기 처리가 늘어나면 아무리 서버가 많아도 병렬 처리를 할 수 없다.

클러스터 DB에서는 서버 간 데이터 교환을 얼마나 줄일 수 있는지, 배타적 제어에 의한 대기 상태를 얼마나 줄일 수 있는지가 중요하다.

정리

배타적 제어의 장단점은 다음과 같다.

장점

단점

배타적 제어 o

공유 데이터의 일관성을 유지할 수 있다.

병렬 처리가 안된다.

배타적 제어 x

병렬로 빠르게 처리할 수 있다.

데이터 불일치가 발생할 가능성이 있다.(동시에 공유 데이터를 변경하는 경우 등)

상태 저장/상태 비저장

어떤 작업을 하고 있을 때 현재 어디까지 작업이 진행됐는지와 같은 상태를 알아야 하는 경우가 있다. 시스템 처리를 하고 있을 때도 이 상태를 파악해야 하는 경우가 많다.

상태를 가진다는 것은 과거에 부여한 정보를 저장해서 계속 활용할 수 있다는 것을 의미한다. 한편, 상태를 가지고 있지 않으면 과거 정보를 알 수 없다.

구체적인 예로, ssh는 상태 저장 프로토콜이지만 http는 상태 비저장 프로토콜이다.

특징

상태 저장은 상태를 고려하기 때문에 복잡한 처리가 가능하지만, 시스템 복잡성이 커진다.

상태 비저장은 상태를 고려하지 않기 때문에 간단하며, 성능이나 안정성 측면에서 우수하다.

어디에 사용되나?

컴퓨터 내부 구조

컴퓨터 내에서 거의 모든 곳에 상태 저장이 사용됨

일반 CPU는 하나의 CPU에서 복수의 프로세스를 조금씩 처리한다. 특정 시점에 진짜로 처리하고 있는 프로세스는 1CPU(코어)당 하나다. 처리를 하지 않는 프로세스는 대기 상태로 있어야 한다. → 프로세스의 상태 전이

네트워크 통신 구조

브라우저가 HTTP 서버에 접속할 때는 HTTP라 불리는 프로토콜을 사용한다.

이 HTTP는 기본적으로 상태 비저장 프로토콜이지만, 로그인 기능 등 상태를 저장해야 하는 경우가 있기 때문에 세션(Session)이라는 개념을 사용해서 사용자의 인증 정보를 유지한다.

인증을 끝낸 사용자는 통신 시에 세션 정보를 건네기만 하면 이전 처리 상태를 유지하면서 접속 가능하다.

정리

상태 저장이란 상대가 상태 전이를 의식해서 처리하며 과거 경위를 이해한 상태에서 응답을 준다. 자신의 상태를 이해하기 때문에 요청 내용을 최소화할 수 있다.

상태 비저장은 매번 신규 요청이 생성되는 것을 의미한다. 이는 요청과 그에 대한 응답 구조가 간단하다는 것이다.

→ 상태를 관리함으로써 자유로운 처리가 가능해지지만, 서버 측 처리가 복잡해져서 리소스 부하가 높아지고 대량의 사용자 요청이 버거워질 수 있다. 적재적소에 이용할 수 있도록 검토가 필요하다.

가변 길이/고정 길이

미리 크기가 정해져 있는 경우를 고정 길이(Fixed-length), 정해져 있지 않은 경우를 가변 길이(Variable-length)라고 한다.

특징

가변 길이는 공간을 유용하게 활용할 수 있지만 성능 면에서 불안정하다.

고정 길이는 쓸데없는 공간이 생기지만 성능 면에서는 안정적이다.

어디에 사용되나?

파일 시스템

윈도우즈의 NTFS라 불리는 파일 시스템에서는 각종 파일을 고정 길이로 저장하고 있다. 하나의 고정 길이 틀이 4096바이트(KB)로, 4KB보다 작은 파일을 저장해도 1파일 저장에 4KB를 사용한다.

네트워크

일반적인 이더넷(Ethernet)의 MTU(IP 패킷 최대 크기)는 1500바이트로, TCP/IP 헤더 합계가 40바이트이기 때문에 MSS(TCP 세그먼트의 데이터 부분의 최대 크기)는 1460바이트가 된다.

TCP/IP로 데이터를 전송할 때 1460바이트 정도의 세그먼트로 분할하고, 마지막 남은 1~1460바이트 크기로 전송된다. → 총 데이터 크기가 n바이트일 때 1460바이트 크기의 세그먼트를 (n / 1460)개 보내고, (n % 1460)바이트 크기의 세그먼트를 하나 보냄.

이더넷은 가변 길이 프레임이지만 고정 길이를 사용하는 것도 있다. ATM(Asynchronous Transfer Mode)라는 데이터 링크 층의 프로토콜에서는 셀(cell)이라 불리는 53바이트 고정 길이 형식을 사용

데이터 구조(배열과 연결 리스트)

배열과 연결리스트는 모두 데이터를 순차적으로 처리하는 구조지만, 구조가 다르기 때문에 성능 측면의 특징도 많이 다르다.

특징

배열은 데이터를 빈틈없이 순서대로 나열한 데이터 구조

연결 리스트는 데이터르 선으로 연결한 데이터 구조

탐색이 빠른 것은 배열이고, 느린 것은 연결 리스트

데이터 추가, 삭제가 빠른 것은 연결 리스트이고, 느린 것은 배열

탐색 알고리즘(해시/트리 등)

해시나 트리는 탐색 알고리즘이 아닌 데이터 구조이지만, 효율적인 탐색을 위해 사용된다.

특징

필요한 때에 필요한 데이터를 빠르게 찾기 위해 데이터를 정리해 둘 필요가 있음

데이터를 찾을 때의 데이터 구조와 데이터 저장 방식 특성에 따라 적합한 데이터 정리 방법이 달라진다.

데이터 정리 방법을 ‘데이터 구조', 처리 순서를 ‘알고리즘'이라고 한다.

처리 순서에 맞추어 데이터 구조를 정리할 필요가 있기 때문에 ‘알고리즘과 데이터 구조'는 함께 다러진다.

어디에 사용되나

DBMS의 인덱스

인덱스가 없으면 디스크에서 테이블 데이터를 모두 읽어서 조사해야 한다. (Full Scand이라고 한다.)

인덱스가 있는 경우 최소한의 필요 블록만 읽으면 된다. 검색이 빨라지는 대신 데이터 추가, 갱신, 삭제 시에 테이블 뿐만 아니라 인덱스 데이터도 갱신해야 하기 때문에 오버헤드가 발생할 수 있음.

일반적으로 인덱스는 B 트리 구조이다. 트리 구조 계층이 깊어지지 않도록 디스크 I/O를 최소한으로 제어하기 때문.

해시 테이블

키와 값 조합으로 표를 구성한 데이터 구성이다.

키는 해시 함수를 통해 해시 값으로 변환된다. 해시 값은 고정 길이 데이터이기 때문에 조합 표의 데이터 구조가 간단해서 검색이 빠르다.

Last updated