Operating Systems : Three Easy Pieces를 보고 번역 및 정리한 내용들입니다.
이 장에서는 더 빠르고, 크고, 신뢰성 있는 디스크 시스템을 구성하기 위해 다수의 디스크들을 함께 사용하는 테크닉인 RAID를 소개한다.
디스크를 쓸 때에는 빠르고, 크고, 신뢰성 있게 동작하기를 원한다. 어떻게 이런 시스템을 만들 수 이쓸까? 핵심 테크닉은 무엇이고, 여러 접근법 사이의 트레이드 오프는 무엇일까?
외부적으로 RAID는 디스크처럼 보인다. 즉 읽고 쓸 수 있는 블록의 그룹으로 보인다. 내부적으로는 매우 복잡한데, 여러 개의 디스크, 메모리, 시스템을 관리하기 위한 하나 이상의 프로세서로 구성되어 있다. 하드웨어 RAID는 디스크 그룹 관리 작업에 특화된 컴퓨터 시스템과 같다.
RAID는 하나의 디스크를 쓰는 것에 비해 많은 이점을 제공한다. 그 중 하나는 성능이다. 여러 개의 디스크를 병렬적으로 사용하는 것은 I/O 시간을 훨씬 빠르게 할 수 있다. 다른 이점은 용량이다. 큰 데이터 집합은 큰 디스크를 필요로 한다. 마지막으로 RAID는 신뢰성도 높일 수 있다. RAID를 사용하지 않고 데이터를 여러 개의 디스크에 분산시키는 것은 한 디스크에만 문제가 발생해도 데이터를 잃어버리기 쉽게 만든다. 중복(redundancy)을 통해 RAID는 한 디스크에 문제가 발생해도 아무 일도 일어나지 않은 것처럼 동작할 수 있다.
놀랍게도 RAID는 이 모든 이점들을 이를 사용하는 시스템에 투명하게 제공한다. 즉, RAID는 호스트 시스템에게는 그저 하나의 큰 디스크로 보인다. 이 투명성은 소프트웨어는 한 줄도 바꾸지 않고도 RAID 디스크를 교체할 수 있도록 한다. 디스크가 바뀌어도 OS와 사용자 애플리케이션은 수정 없이 계속 동작할 수 있게 되는 것이다. 이러한 방법으로 투명성은 RAID의 확산성(deployability)을 크게 높인다. 소프트웨어 호환성에 대한 고려 없이 사용자와 관리자가 RAID를 사용할 수 있게 하기 때문이다.
이제는 RAID의 중요한 측면들에 대해 논의 해보자. 우선은 인터페이스와 폴트 모델로 시작하고나서, 어떻게 RAID 디자인을 용량, 신뢰성, 성능의 세 측면에서 평가할 수 있는지에 대해 논의한다. 마지막으로는 RAID 디자인과 구현에서 중요한 여러 이슈들에 대해 논의하게 될 것이다.
위의 파일 시스템에서 RAID는 크고 빠르고 신뢰성 있는 디스크처럼 보인다. 단일 디스크와 같이, 이는 스스로를 파일 시스템으로 읽고 쓸 수 있는 선형적인 블럭 배열로 나타낸다.
파일 시스템이 논리적 I/O 요청을 RAID에 보내면 RAID는 해당 요청을 완료하기 위해 어떤 디스크에 접근해야 하는지를 내부적으로 계산하고, 이를 위한 하나 이상의 물리 I/O 요청을 보낸다. 이 물리 I/O의 정확한 특성은 아래에서 자세하게 논의할 RAID 레벨에 의존한다. 간단한 예로, 서로 다른 디스크에 각 블록의 두 복사본을 가지는 RAID를 생각해보자. 이런 mirrored RAID 시스템에 쓸 때 RAID는 하나의 논리적 I/O마다 두 번의 물리 I/O를 수행해야 한다.
RAID 시스템은 종종 별도의 하드웨어 박스로 만들어져, 호스트와는 SCSI, SATA와 같은 표준 인터페이스로 연결되어있다. 하지만 내부적으로 RAID는 꽤 복잡하다. 여기에는 RAID의 작업을 지시하는 펌웨어를 실행하기 위한 마이크로컨트롤러, 읽고 쓰는 데이터 블럭 버퍼링을 위한 DRAM과 같은 휘발성 메모리, 그리고 어떤 경우에는 쓰기 작업을 안전하게 버퍼링하기 위한 비휘발성 메모리와 패리티 계산을 수행하기 위한 특화된 논리 회로 등이 포함된다. 높은 수준에서 RAID는 특화된 컴퓨터 시스템과도 같다. 프로세서, 메모리, 디스크를 가지기 때문이다. 하지만 이는 애플리케이션을 실행하기보다는 RAID를 동작시키기 위한 특화 소프트웨어를 실행한다.
RAID를 이해하고 서로 다른 방식들을 비교하기 위해서는 폴트 모델을 염두에 둬야 한다. RAID는 특정 종류의 디스크 폴트를 감지하고 그로부터 복구되도록 설계되어 있다. 따라서 정확히 어떤 폴트가 일어날 것인지를 아는 것이 동작하는 디자인을 만드는 데에 중요하다.
가정해 볼 첫 번째 폴트 모델은 간단하다. 이는 fail-stop 폴트 모델로 불린다. 이 모델에서 디스크는 동작( working)과 실패(failed), 둘 중 하나의 상태를 가진다. 동작하는 디스크에서 모든 블럭들은 읽거나 쓰일 수 있다. 반대로 실패 상태의 디스크는 영구적으로 사용 불가능한 것으로 생각된다.
fail-stop 모델의 핵심 측면들 중 하나는 이것이 가지고 있는 폴트 감지에 대한 가정이다. 구체적으로, 디스크가 고장나는 경우를 쉽게 감지할 수 있다고 가정한다. 예를 들어 RAID 배열에서, RAID 컨트롤러 하드웨어(또는 소프트웨어)는 디스크가 고장났을 때, 즉시 이를 알 수 있다고 가정한다.
따라서 지금부터는 디스크 오염과 같은, 더 복잡하고도 조용한 고장들에 대해서는 걱정하지 않는다. 동작 중인 디스크에서 한 블럭만 접근 불가능해지는 경우도 고려하지 않는다. 이런 복잡한 디스크 폴트들에 대해서는 나중에 다루게 될 것이다.
곧 보게 될 테지만, RAID를 만드는 데에는 여러 가지 다른 방식들이 있다. 이 방식들 각각은 평가해볼 만한 서로 다른 특성들을 가지고 있다.
구체적으로, 우리는 RAID를 다음의 세 축을 기준으로 평가하게 될 것이다. 첫 번째는 용량(capacity)이다. 각각 개의 블럭들을 가지는 개 디스크의 집합이 주어졌을 때, RAID 사용자에게 제공할 수 있는 용량은 얼마나 될까? 데이터 중복이 없는 경우에 답은 가 될 테지만, 만약 미러링을 하는 시스템을 사용한다면 가 될 것이다. 다른 기법들은 그 사이의 값을 가지게 된다.
평가의 두 번째 축은 신뢰성(reliability)이다. 해당 디자인에서 감내할 수 있는 디스크 폴트는 얼마나 될까? 위의 폴트 모델을 따라, 오직 하나의 전체 디스크만이 고장날 수 있다고 가정한다. 이후의 장에서는 더 복잡한 결함 모드들에 대해 다루게 될 것이다.
마지막은 성능(performance)이다. 성능은 디스크 배열에 제공되는 워크로드에 심하게 의존하기 때문에 평가하기 어렵다. 그렇기 때문에 성능을 평가할 때에는 우선 생각해 볼만한 전형적인 워크로드 집합이 무엇인지부터 볼 것이다.
이제는 세 중요 RAID 설계들에 대해 살펴보자. RAID 레벨 0, RAID 레벨 1, RAID 레벨 4와 5가 그것들이다.
첫 번째 RAID 레벨은 어떤 데이터 중복도 사용하지 않기 때문에, 사실 RAID 레벨이 아니다. 하지만 RAID 레벨 0, 또는 스트라이핑(striping)은 성능과 용량에 대한 상한선을 제공하기 때문에 중요하다.
가장 간단한 형태의 스트라이핑은 시스템의 디스크에 걸쳐 블럭들에 줄을 긋는다. 여기서는 네 개의 디스크 배열을 가정해보자.
여기에서 기본 아이디어를 볼 수 있다. 디스크 배열의 블럭들을 여러 디스크들에 걸쳐 라운드-로빈 방식으로 분산시키는 것이다. 이 방식은 디스크 배열의 연속된 청크들에 대한 요청이 있을 때 배열의 병렬성을 최대한 활용하기 위해 설계되었다. 같은 행에 있는 블럭을 스트라이프(stripe)라 부른다. 따라서 블럭 0, 1, 2, 3은 같은 스트라이프에 있다.
이 예에서는 각 4KB 크기의 한 블럭만이 다음 디스크로 넘어가기 전, 각 디스크에 위치한다고 가정한다. 하지만 꼭 이렇게만 배치해야하는 것은 아니다. 예를 들어 블럭들을 다음과 같이 배치할 수도 있다.
이 예에서는 두 개의 4KB의 블럭을 다음 디스크로 넘어가기 전에 배치한다. 그러므로 RAID 배열의 청크 사이즈는 8KB가 되고, 한 스트라이프는 4개의 청크, 또는 32KB의 데이터를 가지게 된다.
청크 사이즈는 배열의 성능에 가장 큰 영향을 준다. 예를 들어 작은 청크 사이즈는 많은 파일들을 많은 디스크를 가로질러 스트라이핑되게 하고, 따라서 한 파일에 대한 읽기와 쓰기의 병렬성을 증가시킨다. 하지만 이 경우, 여러 디스크들을 가로지르며 블럭에 접근하기 위해 걸리는 시간이 증가한다. 왜냐하면 전체 요청에 대한 접근 시간은 전체 드라이브에 걸친 요청들의 최대 접근 시간에 의해 결정되기 때문이다.
한편 큰 청크 사이즈의 경우, 한 파일에 접근 할 때의 병렬성은 줄어들고, 높은 처리량을 얻기 위해 다수의 병행적 요청에 의존하게 된다. 하지만 큰 청크 사이즈는 접근 시간은 줄인다. 예를 들어 만약 하나의 파일이 청크에 딱 들어 맞아 하나의 디스크에 위치된다면, 이에 접근하기 할 때 필요한 접근 시간은 단일 디스크에 접근하는 시간과 동일해질 것이다.
따라서 최선의 청크 사이즈를 결정하는 일은 어렵다. 디스크 시스템에 제공되는 워크로드에 대한 뛰어난 이해를 필요로 하기 때문이다. 이에 대한 나머지 논의를 위해서는 배열이 4KB의 청크 사이즈를 쓴다고 가정한다. 대부분의 디스크 배열은 좀 더 큰 청크 사이즈를 사용하지만, 아래에서 논의할 이슈들에서는 실제 청크 사이즈가 문제가 되지 않는다. 따라서 단순하게 하나의 블럭, 즉 4KB를 청크 사이즈로 가정한다.
이제는 스트라이핑의 용량, 신뢰성, 성능을 평가해보자. 용량의 측면에서는 완벽하다. 블럭 사이즈의 개 디스크가 주어졌을 때, 스트라이핑의 경우 의 용량을 사용할 수 있게 한다. 신뢰성의 측면에서는 나쁜 의미로 완벽하다. 어떤 디스크든 고장이 나면 데이터 손실로 이어진다. 성능의 경우에는 훌륭하다. 모든 디스크들이, 보통은 병렬적으로 사용자 I/O 요청을 서비스하기 위해 활용된다.
RAID 성능을 분석할 때에는 서로 다른 두 종류의 성능 척도를 사용할 수 있다. 첫 번째는 단일-요청 지연(single-request latency)이다. RAID에 보내지는 한 I/O 요청의 지연 시간은, 한 논리 I/O 작업에서 얼마나 많은 병렬성이 있을 수 있는지를 보일 수 있기에 유용하다. 두 번째는 RAID의 정상-상태 처리량(steady-state throughput)으로, 많은 병행 요청의 전체 대역폭을 가리킨다. RAID가 종종 고성능 환경에서 사용되기 때문에 정상 상태에서의 대역폭은 중요하고, 분석에서도 주된 초점이 된다.
처리량에 대해 좀 더 자세히 이해하기 위해서, 관심이 갈 만한 몇 가지 워크로드들을 상정해보자. 이를 위해서는 순차적 워크로드와 랜덤 워크로드, 두 종류를 생각해본다. 순차적 워크로드에서는 디스크 배열로의 요청이 큰 연속 청크로 들어온다고 가정한다. 예를 들어 블럭 에서 시작해 MB에서 끝나는, 1MB의 요청이라 하자. 순차적 워크로드는 많은 환경에서 흔하므로 중요하다고 생각된다
랜덤 워크로드로는, 각 요청이 좀 더 작고, 디스크의 서로 다른 랜덤 위치에 대한 것이라 가정한다. 예를 들어 논리 주소 10, 550,000, 20,100, ...에서의 4KB 요청 스트림이라 해보자. DBMS에서의 트랜잭션 워크로드와 같은 몇몇 중요한 워크로드들이 이러한 접근 패턴을 보이기에, 이 워크로드도 중요하다.
물론 실제 워크로드는 이렇게 간단하지 않고, 위의 둘이 혼합되어 있는 경우들도 많다. 하지만 여기서는 단순하게 위의 두 경우만을 생각해본다.
위 두 워크로드는 디스크에 서로 다른 성능적 특성을 보인다. 순차적 접근에서 디스크는 탐색과 회전 지연이 줄어들고, 대부분의 시간은 데이터 전송에 쓰인다. 랜덤 접근에서는 반대로 탐색과 회전 지연에 대부분의 시간이 걸리고 데이터 전송에는 적은 시간이 쓰인다. 분석에서 이러한 차이를 드러내기 위해, 순차적 워크로드에서는 데이터 전송이 , 랜덤 워크로드에서는 의 속도로 일어난다고 가정한다. 일반적으로 는 보다 훨씬 크다.
이러한 차이를 제대로 이해했는지 확실히 하기 위해, 주어진 디스크 특성을 바탕으로 와 을 직접 계산해보자. 순차적 워크로드에서는 평균 10MB, 랜덤 워크로드에서는 평균 10KB의 데이터를 전송한다고 가정한다. 디스크 특성은 다음과 같다
를 계산하려면 우선 10MB 전송을 위해 얼마나 많은 시간이 걸리는지를 알아야 한다. 우선은 7+3ms를 탐색 및 회전에 쓰고 전송을 시작한다. 전송 속도가 50MB/s이니 10MB 전송을 위해서는 0.2초, 200ms가 걸린다. 따라서 각 10MB 요청마다, 해당 요청에 대한 처리를 완료하기 위해서는 총 210ms가 걸린다. 는 다음과 같이 계산할 수 있다. 대부분의 시간이 데이터 전송에 쓰이기 때문에 는 거의 디스크 대역폭의 정점에 위치한다.
에 대해서도 마찬가지로 계산하면, 를 얻을 수 있다. 순차적 워크로드에서 랜덤 워크로드보다 거의 50배는 빠르다.
이제 스트라이핑의 성능을 계산해보자. 위에서 말했듯 일반적으로는 좋은 성능을 보인다. 지연 속도의 측면에서, 단일 블럭 요청의 지연 시간은 거의 단일 디스크의 지연 속도와 같다. RAID-0은 그냥 요청을 그 디스크들 중 하나로 전달할 뿐이기 때문이다.
순차 워크로드에 대한 정상-상태 처리량의 측면에서는 시스템의 최대 대역폭을 기대할 수 있다. 따라서 처리량은 가 된다. 다수의 랜덤 I/O에 대해서도, 모든 디스크들을 활용할 수 있기 때문에 를 얻을 수 있다. 이후 보게 되겠지만, 이 값들은 계산하기에도 가장 쉽고, 다른 RAID 레벨과의 비교에서 상한선을 제공하기도 한다.
열심히 하시네요 박영서 화이팅!