분산 데이터베이스 시스템 101
또는 분산 데이터베이스-FK가 실제로 ' 웹 스케일 '이란 무엇을 의미합니까?
분산 데이터베이스 시스템은 복잡한 동물이며 여러 가지 맛이 있습니다. 내가 대학에서 이것에 대해 어둡게 기억 된 연구의 깊이를 파헤 치면 분산 데이터베이스 시스템을 구축하는 데 중요한 엔지니어링 문제 중 일부를 설명하려고 노력할 것입니다.
첫째, 일부 용어
ACID (원 자성, 일관성, 격리 및 내구성) 속성 : 바람직하지 않은 부작용을 일으키지 않고 트랜잭션을 안정적으로 구현하기 위해 시행해야하는 주요 불변량입니다.
Atomicity 는 트랜잭션을 완료하거나 롤백해야합니다. 부분적으로 완료된 트랜잭션은 절대로 보이지 않아야하며 시스템은이를 방지하는 방식으로 구축해야합니다.
일관성을 유지 하려면 트랜잭션이 데이터베이스 스키마에 의해 보장되는 변이 (예 : 선언적 참조 무결성)를 위반하지 않아야합니다. 예를 들어 외래 키가 존재하면 존재하지 않는 부모에게 경건한 자식 레코드를 삽입 할 수 없습니다.
격리를 위해서는 트랜잭션이 서로 간섭하지 않아야합니다. 트랜잭션이 병렬로 또는 순차적으로 실행될 경우 시스템은 동일한 결과를 보장해야합니다. 실제로 대부분의 RDBMS 제품은 성능과의 격리를 절충하는 모드를 허용합니다.
내구성을 위해서는 트랜잭션이 커밋되면 하드웨어 또는 소프트웨어 오류에 견딜 수있는 방식으로 영구 저장소에 남아 있어야합니다.
아래의 분산 시스템에 이러한 요구 사항이 존재하는 기술적 인 문제에 대해 설명하겠습니다.
공유 디스크 아키텍처 : 클러스터의 모든 처리 노드가 모든 스토리지에 액세스 할 수있는 아키텍처입니다. 이는 데이터 액세스에 대한 중앙 병목 현상을 일으킬 수 있습니다. 공유 디스크 시스템의 예는 Oracle RAC 또는 Exadata 입니다.
공유 없음 아키텍처 : 클러스터의 처리 노드에 다른 클러스터 노드가 볼 수없는 로컬 스토리지가있는 아키텍처입니다. 비공유 시스템의 예는 Teradata 및 Netezza 입니다.
공유 메모리 아키텍처 : 여러 CPU (또는 노드)가 공유 메모리 풀에 액세스 할 수있는 아키텍처입니다. 대부분의 최신 서버는 공유 메모리 유형입니다. 공유 메모리는 분산 시스템에서 수행하기 훨씬 어려운 캐시 또는 원자 동기화 기본 요소와 같은 특정 조작을 용이하게합니다.
동기화 : 여러 프로세스 또는 스레드가 공유 리소스에 일관되게 액세스 할 수 있도록 다양한 방법을 설명하는 일반적인 용어입니다. 일부 네트워크 아키텍처 (예 : Teradata의 BYNET)는 네트워크 프로토콜에 동기화 프리미티브가 있지만 공유 메모리 시스템보다 분산 시스템에서 수행하기가 훨씬 어렵습니다. 동기화에는 상당한 양의 오버 헤드가 발생할 수 있습니다.
Semi-Join : 분산 시스템의 서로 다른 두 노드에 보유 된 데이터를 결합하는 데 사용되는 프리미티브입니다. 본질적으로 조인을 해결하기 위해 조인 할 행에 대한 충분한 정보로 묶여서 한 노드에서 다른 노드로 전달됩니다. 대규모 쿼리에서는 상당한 네트워크 트래픽이 발생할 수 있습니다.
최종 일관성 : 쓰기시 성능 (따라서 트랜잭션 처리량 증가)을 위해 분산 시스템의 모든 노드에서 즉각적인 업데이트 (읽기 일관성)를 상쇄하는 트랜잭션 시맨틱을 설명하는 데 사용되는 용어입니다. 최종 일관성은 쿼럼 복제 를 성능 최적화로사용하여여러 데이터 복사본이 별도의 노드에 보관 된 분산 데이터베이스에서 트랜잭션 커밋 속도를 높이는부작용입니다.
Lamport 's Algorithm : 공유 메모리가없는 시스템에서 상호 배제 (동기화)를 구현하기위한 알고리즘. 일반적으로 시스템 내에서 상호 배제하려면 일반적으로 공유 메모리 시스템에서만 실용적인 유형의 원자 적 읽기 비교 쓰기 또는 유사한 명령이 필요합니다. 다른 분산 동기화 알고리즘이 존재하지만 Lamport는 첫 번째 알고리즘 중 하나이며 가장 잘 알려져 있습니다. 대부분의 분산 동기화 메커니즘과 마찬가지로 Lamport의 알고리즘은 클러스터 노드간에 정확한 타이밍 및 클럭 동기화에 크게 의존합니다.
2PC (Two Phase Commit) : 여러 물리적 시스템과 관련된 데이터베이스 업데이트가 일관되게 커밋 또는 롤백되도록하는 프로토콜 제품군. 트랜잭션 관리자를 통해 시스템 내에서 또는 여러 시스템에서 2PC를 사용하든간에 상당한 오버 헤드가 발생합니다.
2 단계 커밋 프로토콜에서 트랜잭션 관리자는 참여 노드에 커밋을 보장 할 수있는 방식으로 트랜잭션을 지속하도록 요청한 다음이 상태를 알립니다. 모든 노드가 '행복한'상태를 반환하면 노드는 커밋하도록 신호를 보냅니다. 모든 노드가 커밋이 완료되었음을 나타내는 응답을 보낼 때까지 트랜잭션은 여전히 열린 것으로 간주됩니다. 커밋이 완료되었음을 알리기 전에 노드가 중단되면 트랜잭션 관리자는 트랜잭션이 커밋되었음을 나타내는 긍정적 인 응답을받을 때까지 노드가 다시 시작될 때 노드를 다시 쿼리합니다.
MVCC (Multi-Version Concurrency Control) : 새 버전의 데이터를 다른 위치에 작성하고 새 버전이 커밋 될 때까지 다른 트랜잭션이 이전 버전의 데이터를 볼 수 있도록하여 경합을 관리합니다. 이렇게하면 새 쓰기 버전을 작성하고 이전 버전을 사용하지 않는 것으로 표시하기 위해 추가 쓰기 트래픽을 희생하여 데이터베이스 경합이 줄어 듭니다.
선거 알고리즘 : 여러 노드가 포함 된 분산 시스템은 장애 모드가 많을수록 단일 시스템보다 신뢰성이 떨어집니다. 대부분의 경우 클러스터형 시스템이 노드 장애를 처리하기 위해 일부 메커니즘이 필요합니다. 선거 알고리즘은 '리더'노드가 100 % 결정되거나 신뢰할 수없는 상황에서 분산 계산을 조정하기 위해 리더를 선택하는 데 사용되는 알고리즘 클래스입니다.
수평 분할 : 키를 사용하여 테이블을 여러 노드 또는 스토리지 볼륨으로 분할 할 수 있습니다. 이를 통해 큰 데이터 볼륨을 더 작은 청크로 분할하여 스토리지 노드에 분산시킬 수 있습니다.
샤딩 (Shading) : 비공유 아키텍처에서 데이터 세트가 여러 물리적 노드에 가로로 분할 될 수 있습니다. 이 분할이 투명하지 않은 경우 (즉, 클라이언트가 분할 체계를 알고 명시 적으로 쿼리 할 노드를 해결해야 함)이를 샤딩이라고합니다. 일부 시스템 (예 : Teradata)은 노드간에 데이터를 분할하지만 위치는 클라이언트에게 투명합니다. 이 용어는 일반적으로이 유형의 시스템과 함께 사용되지 않습니다.
일관된 해싱 : 키를 기반으로 파티션에 데이터를 할당하는 데 사용되는 알고리즘입니다. 해시 키의 균일 한 분배와 버킷 수를 효율적으로 확장 또는 축소 할 수있는 기능이 특징입니다. 이러한 속성을 사용하면 노드가 클러스터에 추가되거나 삭제 될 때 (실패로 인해) 크기가 동적으로 변경 될 수있는 노드 클러스터에서 데이터를 분할하거나로드하는 데 유용합니다.
다중 마스터 복제 : 클러스터의 여러 노드에 걸친 쓰기를 다른 노드로 복제 할 수있는 기술입니다. 이 기술은 일부 테이블을 서버에서 분할하거나 분할하고 다른 테이블을 클러스터에서 동기화 할 수 있도록하여 확장을 용이하게합니다. 쿼럼과 달리 모든 노드에 쓰기를 복제해야하므로 쿼럼 복제 시스템보다 다중 마스터 복제 아키텍처에서 트랜잭션 커밋이 더 비쌉니다.
비 차단 스위치 : 내부 하드웨어 병렬 처리를 사용하여 내부 병목 현상이없는 포트 수에 비례하는 처리량을 달성하는 네트워크 스위치. 순진한 구현은 크로스바 메커니즘을 사용할 수 있지만 N 포트에 대해 O (N ^ 2) 복잡성을 가지므로 더 작은 스위치로 제한합니다. 더 큰 스위치는 O (N ^ 2) 하드웨어없이 선형 처리량 확장을 달성하기 위해 비 차단 최소 스패닝 스위치라고하는 더 복잡한 내부 토폴로지를 사용할 수 있습니다.
분산 DBMS 만들기-얼마나 힘들 수 있습니까?
몇 가지 기술적 과제로 인해 실제로 수행하기가 매우 어렵습니다. 분산 시스템 구축의 복잡성 외에도 분산 DBMS 설계자는 까다로운 엔지니어링 문제를 극복해야합니다.
분산 시스템에 대한 원 자성 : 트랜잭션에 의해 업데이트 된 데이터가 여러 노드에 분산 된 경우 노드의 커밋 / 롤백이 조정되어야합니다. 이것은 무 공유 시스템에 상당한 오버 헤드를 추가합니다. 공유 디스크 시스템에서는 모든 노드에서 모든 스토리지를 볼 수 있으므로 단일 노드가 커밋을 조정할 수 있으므로 이는 문제가되지 않습니다.
분산 시스템의 일관성 : 위에 언급 된 외래 키 예제를 사용하려면 시스템이 일관된 상태를 평가할 수 있어야합니다. 예를 들어 외래 키 관계의 부모와 자식이 다른 노드에있을 수있는 경우 오래된 정보를 사용하여 트랜잭션을 확인하지 않도록 일종의 분산 잠금 메커니즘이 필요합니다. 이것이 적용되지 않으면 (예를 들어) 자식 삽입을 허용하기 전에 존재 여부를 확인한 후 부모가 삭제되는 경쟁 조건을 가질 수 있습니다.
제약 조건의 지연된 이행 (즉, DRI를 검증하기위한 커밋까지 대기)은 트랜잭션 기간 동안 잠금을 유지해야합니다. 이러한 종류의 분산 잠금에는 상당한 오버 헤드가 있습니다.
여러 개의 데이터 사본이 보유 된 경우 (이는 반조 인으로 인한 불필요한 네트워크 트래픽을 피하기 위해 공유 시스템이 필요할 수 있음) 모든 데이터 사본을 업데이트해야합니다.
분산 시스템에서의 격리 : 트랜잭션에 영향을받는 데이터가 여러 시스템 노드에 상주하는 경우 MVCC를 사용중인 경우 잠금 및 버전을 노드간에 동기화해야합니다. 중복 데이터 복사본이 저장 될 수있는 비공유 아키텍처에서 작업의 직렬화 가능성을 보장하려면 Lamport 's Algorithm과 같은 분산 동기화 메커니즘이 필요하며 네트워크 트래픽에 상당한 오버 헤드가 발생합니다.
분산 시스템 의 내구성 : 공유 디스크 시스템에서 내구성 문제는 노드 전체에 분산 동기화 프로토콜이 여전히 필요하다는 점을 제외하고는 공유 메모리 시스템과 본질적으로 동일합니다. DBMS는 로그에 쓰기를 저널하고 데이터를 일관되게 써야합니다. 비공유 시스템에는 다른 노드에 저장된 데이터의 여러 사본 또는 데이터의 일부가있을 수 있습니다. 커밋이 노드에서 올바르게 수행되도록하려면 2 단계 커밋 프로토콜이 필요합니다. 또한 상당한 오버 헤드가 발생합니다.
비공유 시스템에서 노드 손실은 시스템에서 데이터를 사용할 수 없음을 의미 할 수 있습니다. 이 데이터를 완화하기 위해 둘 이상의 노드에 복제 될 수 있습니다. 이 상황에서의 일관성은 데이터가 정상적으로 상주하는 모든 노드에 데이터를 복제해야 함을 의미합니다. 이로 인해 쓰기에 상당한 오버 헤드가 발생할 수 있습니다.
NoSQL 시스템에서 일반적으로 사용되는 최적화 중 하나는 쿼럼 복제 및 최종 일관성을 사용하여 트랜잭션을 커밋 된 것으로보고하기 전에 쿼럼에 기록하여 데이터의 일정 수준의 복원력을 보장하면서 데이터를 느리게 복제 할 수 있도록하는 것입니다. 그런 다음 데이터 사본이 상주하는 다른 노드로 지연 복제됩니다.
'최종 일관성'은 트랜잭션이 커밋 되 자마자 데이터를 일관되게보아야하는 경우 수용 할 수없는 일관성에 대한 주요 트레이드 오프입니다. 예를 들어, 재무 응용 프로그램에서 업데이트 된 잔액을 즉시 사용할 수 있어야합니다.
공유 디스크 시스템
공유 디스크 시스템은 모든 노드가 모든 스토리지에 액세스 할 수있는 시스템입니다. 따라서 계산은 위치와 무관합니다. 많은 DBMS 플랫폼도이 모드에서 작동 할 수 있습니다. Oracle RAC는 이러한 아키텍처의 예입니다.
공유 디스크 시스템은 스토리지 노드와 처리 노드 간의 M : M 관계를 지원할 수 있으므로 실질적으로 확장 할 수 있습니다. SAN에는 여러 개의 컨트롤러가있을 수 있으며 여러 서버가 데이터베이스를 실행할 수 있습니다. 이러한 아키텍처에는 스위치가 중앙 병목 현상이 있지만 크로스바 스위치를 사용하면이 스위치가 많은 대역폭을 가질 수 있습니다. 스토리지 대역폭의 트래픽을 줄일 수있는 일부 처리는 Oracle Exadata의 경우와 같이 스토리지 노드로 오프로드 될 수 있습니다.
스위치는 이론적으로 병목 현상이 있지만 사용 가능한 대역폭은 공유 디스크 아키텍처가 대규모 트랜잭션 볼륨으로 상당히 효과적으로 확장됨을 의미합니다. 대부분의 주류 DBMS 아키텍처는 '충분한'확장 성과 높은 안정성을 제공하기 때문에 이러한 접근 방식을 취합니다. 파이버 채널과 같은 중복 스토리지 아키텍처를 사용하면 처리 노드와 스토리지 노드 사이에 둘 이상의 경로가 있으므로 단일 장애 지점이 없습니다.
비공유 시스템
비공유 시스템은 데이터의 적어도 일부가 노드에 로컬로 유지되고 다른 노드에 직접 표시되지 않는 시스템입니다. 이는 중앙 스위치의 병목 현상을 제거하여 데이터베이스가 노드 수에 따라 (적어도 이론적으로는) 확장 될 수 있도록합니다. 수평 파티셔닝을 통해 데이터를 노드간에 분할 할 수 있습니다. 이것은 클라이언트에게 투명하거나 투명하지 않을 수 있습니다 (위의 샤딩 참조).
데이터는 본질적으로 분산되므로 쿼리에는 둘 이상의 노드의 데이터가 필요할 수 있습니다. 결합이 다른 노드의 데이터를 필요로하는 경우 한 노드에서 다른 노드로 결합을 지원하기에 충분한 데이터를 전송하기 위해 semi-join 조작이 사용됩니다. 이로 인해 많은 양의 네트워크 트래픽이 발생할 수 있으므로 데이터 분배를 최적화하면 쿼리 성능에 큰 차이가 생길 수 있습니다.
종종 데이터가 비공유 시스템의 노드에 복제되어 세미 조인의 필요성이 줄어 듭니다. 차원은 일반적으로 팩트 테이블보다 몇 배나 작으며 노드간에 쉽게 복제 할 수 있기 때문에 데이터웨어 하우스 어플라이언스에서 상당히 잘 작동합니다. 또한 일반적으로 일괄 처리로로드되므로 복제 오버 헤드는 트랜잭션 응용 프로그램보다 문제가 적습니다.
비공유 아키텍처의 고유 한 병렬 처리로 인해 데이터웨어 하우스의 특징 인 테이블 스캔 / 집계 쿼리에 적합합니다. 이러한 종류의 작업은 처리 노드 수에 따라 거의 선형으로 확장 될 수 있습니다. 세미 조인 작업이 많은 네트워크 트래픽을 생성 할 수 있으므로 노드 전체의 큰 조인은 더 많은 오버 헤드를 발생시키는 경향이 있습니다.
대용량 업데이트는 트랜잭션 업데이트 응용 프로그램에 유용하지 않습니다. 여러 업데이트로 인해이 유형의 아키텍처가 공유 디스크보다 덜 매력적입니다. 따라서 이러한 유형의 아키텍처는 데이터웨어 하우스 응용 프로그램에서 널리 사용되지 않는 경향이 있습니다.
샤딩, 쿼럼 복제 및 최종 일관성
쿼럼 복제는 DBMS가 고 가용성을 위해 데이터를 복제하는 기능입니다. 이는 SAN과 같은 고 가용성 기능이 내장되어 있지 않은 저렴한 상용 하드웨어에서 작동하도록 설계된 시스템에 유용합니다. 이 유형의 시스템에서 데이터는 여러 스토리지 노드에 복제되어 읽기 성능과 중복 스토리지를 통해 시스템이 노드의 하드웨어 장애에 대해 탄력성을 갖도록합니다.
그러나 모든 노드에 대한 쓰기 복제는 M 노드 및 N 쓰기에 대해 O (M x N)입니다. 트랜잭션이 커밋되기 전에 쓰기가 모든 노드에 복제되어야하는 경우 쓰기 비용이 많이 듭니다. 쿼럼 복제는 쓰기를 노드의 하위 집합에 즉시 복제 한 다음 백그라운드 작업을 통해 다른 노드에 느리게 기록 할 수있는 절충안입니다. 트랜잭션이 클라이언트에 커밋 된 것으로보고되기 전에 노드의 최소 하위 집합 (쿼럼)에 복제되도록함으로써 쓰기를보다 신속하게 커밋 할 수 있습니다.
이는 백그라운드 프로세스가 나머지 노드에 데이터 쓰기를 완료 할 때까지 쿼럼 외부의 노드를 읽을 때 더 이상 사용되지 않는 버전의 데이터를 볼 수 있음을 의미합니다. 시맨틱은 '최종 일관성'으로 알려져 있으며 응용 프로그램의 요구 사항에 따라 수용 가능하거나 수용 불가능할 수 있지만 트랜잭션 커밋은 리소스 사용에서 O (n)보다 O (1)에 더 가깝습니다.
샤딩은 클라이언트가 종종 '일관된 해싱'이라는 알고리즘 유형을 사용하여 데이터베이스 내에서 데이터의 파티셔닝을 인식해야합니다. 샤딩 된 데이터베이스에서 클라이언트는 키를 해시하여 쿼리를 실행할 클러스터의 서버를 결정합니다. 요청이 클러스터의 노드에 분산되어 있으므로 단일 쿼리 코디네이터 노드에 병목 현상이 없습니다.
이러한 기술을 사용하면 클러스터에 노드를 추가하여 데이터베이스를 거의 선형으로 확장 할 수 있습니다. 이론적으로 쿼럼 복제는 기본 저장 매체를 신뢰할 수없는 것으로 간주하는 경우에만 필요합니다. 이는 상품 서버를 사용하는 경우에 유용하지만 기본 스토리지 메커니즘에 고유 한 고 가용성 구성표 (예 : 미러링 된 컨트롤러가있는 SAN 및 호스트에 대한 다중 경로 연결)가있는 경우 가치가 떨어집니다.
예를 들어 Google의 BigTable은 쿼럼 복제를 사용하는 클러스터 파일 시스템 인 GFS에 있지만 쿼럼 복제를 자체적으로 구현하지는 않습니다. BigTable (또는 모든 비공유 시스템)은 여러 컨트롤러가있는 안정적인 스토리지 시스템을 사용하고 컨트롤러간에 데이터를 분할 할 수 있습니다. 그러면 데이터 파티셔닝을 통해 병렬 액세스가 가능합니다.
RDBMS 플랫폼으로 돌아 가기
이러한 기술을 RDBMS와 함께 사용할 수없는 고유 한 이유는 없습니다. 그러나 잠금 및 버전 관리는 이러한 시스템에서 상당히 복잡하며 해당 시스템의 시장은 매우 전문화 될 수 있습니다. 주류 RDBMS 플랫폼 중 어느 것도 쿼럼 복제를 사용하지 않으며 어떤 RDBMS 제품 (적어도 중요한 제품은 아님)을 구체적으로 알고 있지 않습니다.
공유 디스크 및 비공유 시스템은 매우 큰 워크로드로 확장 할 수 있습니다. 예를 들어, Oracle RAC는 63 개의 프로세싱 노드 (자체적으로 큰 SMP 머신 일 수 있음)와 SAN에서 임의의 수의 스토리지 컨트롤러를 지원할 수 있습니다. IBM Sysplex (zSeries 메인 프레임 클러스터)는 여러 메인 프레임 (각각 상당한 처리 능력과 I / O 대역폭을 갖는) 및 여러 SAN 컨트롤러를 지원할 수 있습니다. 이러한 아키텍처는 안정적인 스토리지를 가정하지만 ACID 시맨틱으로 매우 큰 트랜잭션 볼륨을 지원할 수 있습니다. Teradata, Netezza 및 기타 공급 업체는 매우 큰 데이터 볼륨으로 확장 할 수있는 무 공유 설계를 기반으로 고성능 분석 플랫폼을 만듭니다.
지금까지 저렴하지만 초 고용량 완전 ACID RDBMS 플랫폼 시장은 샤딩 및 다중 마스터 복제를 지원하는 MySQL이 지배하고 있습니다. MySQL은 쿼럼 복제를 사용하여 쓰기 처리량을 최적화하지 않으므로 트랜잭션 커밋은 NoSQL 시스템보다 비쌉니다. 샤딩은 매우 높은 읽기 처리량 (예 : Facebook에서 MySQL을 광범위하게 사용)을 허용하므로 이러한 유형의 아키텍처는 읽기가 많은 작업량에 맞게 확장됩니다.
흥미로운 토론
BigTable 은 아래 Michael Hausenblas가 지적한 공유 비 아키텍처 (기본적으로 분산 키-값 쌍) 입니다. 필자의 원래 평가에는 BigTable의 일부가 아니지만 일반적으로 가장 일반적인 구현 (예 : Hadoop / HBase 및 Google의 MapReduce 프레임 워크)과 함께 사용되는 MapReduce 엔진이 포함되었습니다.
스토리지와 처리 사이에 물리적 선호도가있는 Teradata와이 아키텍처를 비교하면 (즉, 노드는 공유 SAN이 아닌 로컬 스토리지가 있음) BigTable / MapReduce는 전 세계적으로 볼 수있는 병렬 스토리지 시스템을 통해 공유 디스크 아키텍처라고 주장 할 수 있습니다.
Hadoop과 같은 MapReduce 스타일 시스템의 처리 처리량은 비 차단 네트워크 스위치의 대역폭에 의해 제한됩니다. 1 비는 차단 스위치는, 그러나, 디자인에 내재 된 병렬 처리에 큰 대역폭 집계를 처리 할 수있는, 그래서 그들은 거의 성능에 상당한 실질적인 제약 없습니다. 이는 네트워크 스위치가 이론적으로 중앙 병목 현상이 발생하더라도 공유 디스크 아키텍처 (아마도 공유 스토리지 시스템이라고도 함)가 대규모 워크로드로 확장 될 수 있음을 의미합니다.
원래의 핵심 병목 현상은 공유 디스크 시스템에 존재하지만 여러 스토리지 노드 (예 : BigTable 태블릿 서버 또는 SAN 컨트롤러)가있는 파티션 된 스토리지 서브 시스템은 여전히 대규모 워크로드로 확장 될 수 있습니다. 비 차단 스위치 아키텍처는 이론적으로 포트가있는만큼의 현재 연결을 처리 할 수 있습니다.
1은 물론 처리 및 I / O 처리량이 가능합니다 또한 성능에 제한을 구성하지만, 네트워크 스위치는 모든 트래픽이 통과하는 중앙 지점입니다.