메뉴
HN
Hacker News • 4일 전

델타: 체인 복제 기반 고가용성·강한 일관성 스토리지

IMP
6/10
핵심 요약

메타(Meta)가 재해 복구 및 부트스트랩 전략을 위해 체인 복제(chain replication)를 활용해 구축한 신규 객체 스토리지 서비스 '델타(Delta)'를 소개하는 글입니다. 델타는 지연 시간과 저장 효율을 희생하는 대신 단순성과 신뢰성을 극대화한 저의존성 시스템으로, 인프라의 최하단에서 가용성과 복구 가능성의 기반을 제공합니다.

번역된 본문

Kumar Mrinal, Binbin Lu 작성

수년에 걸쳐 메타(Meta)는 다양한 사용 사례와 워크로드 특성에 대응하는 여러 스토리지 서비스에 투자해 왔습니다. 그 과정에서 스토리지 영역의 시스템들을 줄이고 통합하려고 노력해 왔습니다. 동시에, 중요한 패키지 워크로드를 위한 전용 솔루션을 갖추면 모두가 더 만족스러워합니다. 이러한 시스템은 재해 복구 및 부트스트랩 전략에 필수적입니다. 이러한 인식과 함께 메타의 빌드 및 배포 아티팩트를 위한 스토리지를 제공해야 한다는 비즈니스 요구가 맞물려 새로운 객체 스토리지 서비스인 '델타(Delta)'가 탄생했습니다.

메타 인프라 스택에서 델타의 위치를 생각해 보면(아래 그림 참고), 델타는 가장 아래쪽에 위치하며 나머지 인프라의 가용성과 복구 가능성에 필요한 기본 프리미티브를 제공합니다. 부트스트랩 시스템의 경우, 복잡성은 솔루션을 더 신뢰할 수 있게 만들 때만 도입해야 합니다. 솔루션의 성능과 효율성은 최소한으로만 고려합니다. 부트스트랩 시스템에 대한 또 다른 고려사항은 부트스트랩 그 자체입니다. 부트스트랩은 엔지니어가 소수의 머신에 접근해 나머지 인프라를 복원함으로써 서비스를 사용하는 사람들에게 다시 제품을 제공할 수 있게 하는 과정입니다. 마지막으로, 재해가 발생할 경우 복구를 위해 부트스트랩 데이터는 백업되어야 합니다.

이 글에서는 델타의 목표, 델타 아키텍처를 지배하는 핵심 개념, 델타의 프로덕션 사용 사례, 복구 제공자로서의 발전 과정, 그리고 향후 과제를 다룹니다.

델타란 무엇인가?

델타는 단순하고, 신뢰할 수 있으며, 확장 가능하고, 의존성이 낮은 객체 스토리지 시스템입니다. put, get, delete, list라는 단 네 가지의 고수준 연산만 제공합니다. 델타는 지연 시간과 저장 효율을 희생하는 대신 단순성과 신뢰성을 택했습니다. 수평적으로 확장 가능하며, 소프트 의존성에 대해 적절한 장애 조치(failover) 전략을 갖추어 의존성을 최소화합니다.

델타가 아닌 것:

  • 범용 스토리지 시스템: 델타의 핵심 원칙은 복원력과 데이터 보호입니다. 저의존성 시스템에서 사용되도록 특별히 설계되었습니다.
  • 파일시스템: 델타는 단순한 객체 스토리지 시스템으로 동작합니다. Posix 같은 파일시스템 의미론을 노출할 의도가 없습니다.
  • 최대 저장 효율에 최적화된 시스템: 복원력이 핵심 원칙이고 중요 시스템에 초점을 맞추고 있기 때문에, 델타는 저장 효율, 지연 시간, 처리량을 최적화할 의도가 없습니다.

델타의 아키텍처

델타는 페일스톱(fail-stop) 저장 서버 클러스터를 조율하는 접근 방식인 체인 복제(chain replication)를 프로덕션 수준으로 구현했습니다. 강한 일관성 보장을 희생하지 않으면서 높은 처리량과 가용성을 갖춘 대규모 스토리지 서비스를 지원하는 것을 목표로 합니다. 델타가 체인 복제를 어떻게 활용해 클라이언트 데이터를 복제하는지 자세히 살펴보기 전에, 먼저 체인 복제의 기본을 알아보겠습니다.

체인 복제

기본적으로 체인 복제는 서버들을 선형적인 체인 형태로 구성합니다. 연결 리스트와 마찬가지로, 각 체인은 객체의 복제본을 중복 저장하는 호스트 집합으로 이루어집니다. 각 체인은 서버의 순열로 구성되며, 첫 번째 서버를 헤드(head), 마지막 서버를 테일(tail)이라고 부릅니다. 아래 그림은 네 대의 서버로 구성된 체인의 예를 보여줍니다.

모든 쓰기 요청은 헤드 서버로 전달됩니다. 업데이트는 체인을 따라 헤드 서버에서 테일 서버로 파이프라인 방식으로 전파됩니다. 모든 서버가 업데이트를 영속화하면, 테일이 쓰기 요청에 응답합니다. 읽기 요청은 테일 서버로만 전달됩니다. 클라이언트가 체인의 테일에서 읽을 수 있는 내용은 체인에 속한 모든 서버에 걸쳐 복제되므로, 강한 일관성이 보장됩니다.

체인 복제 vs. 쿼럼 복제

체인 복제가 무엇을 수반하는지 개략적으로 살펴보았으니, 이제 체인 복제가 널리 사용되는 다른 복제 전략과 비교하여 어떤 성과를 보이는지 살펴보겠습니다.

저장 효율: 체인 복제는 분명히 가장 저장 효율이 좋은 복제 전략은 아닙니다. 전체 데이터셋의 중복 복사본을 모든 호스트에 저장하기 때문입니다.

원문 보기
원문 보기 (영어)
By Kumar Mrinal , Binbin Lu Over the years, Meta has invested in a number of storage service offerings that cater to different use cases and workload characteristics. Along the way, we've aimed to reduce and converge the systems in the storage space. At the same time, having a dedicated solution for critical package workload makes everyone happier. Having this in place is necessary for our disaster recovery and bootstrap strategy. This realization, coupled with a business need to provide storage for Meta’s build and distribution artifacts, led to the inception of a new object storage service — Delta. Consider Delta’s positioning in the Meta infrastructure stack (below). It belongs at the very bottom, providing the basic primitive required for the availability and recoverability of the rest of the infrastructure. For bootstrap systems, complexity should be introduced only if it makes the solution more reliable. We’re only minimally concerned with the performance and efficiency of the solution. Another consideration for bootstrap systems involves the bootstrap itself. This process, by which engineers can access a small set of machines and restore the rest of our infrastructure, helps us get the product back up and working for people using it. Lastly, the bootstrap data needs to be backed up for recovery in case disaster strikes. In this post, we will discuss the goals for Delta, the main concepts that govern Delta’s architecture, Delta’s production use cases, its evolution as a recovery provider, and future work items. What is Delta? Delta is a simple, reliable, scalable, low-dependency object storage system. It features only four high-level operations: put, get, delete, and list. Delta trades latency and storage efficiency in favor of simplicity and reliability. Since it’s horizontally scalable, Delta takes on minimal dependencies with appropriate failover strategies for soft dependencies in place. Delta is not a : General purpose storage system: Delta’s core tenets are resiliency and data protection. It’s designed specifically to be used by low-dependency systems. Filesystem: Delta acts as a simple object storage system. It doesn’t intend to expose filesystem semantics like Posix etc. System optimized for maximum storage efficiency: With resiliency as its primary tenet and focus on critical systems, Delta doesn’t intend to optimize for storage efficiency, latency, or throughput. Delta’s architecture Delta has productionized chain replication , an approach to coordinating clusters of fail-stop storage servers. It intends to support large-scale storage services that exhibit high throughput and availability, without sacrificing strong consistency guarantees. Before diving deeper into how Delta leverages chain replication to replicate client data, let’s first explore the basics of chain replication. Chain replication Fundamentally, chain replication organizes servers in a chain in a linear fashion. Much like a linked list, each chain involves a set of hosts that redundantly store replicas of objects. Each chain contains a sequence of servers. We call the first server the head and the last one the tail. The figure below shows an example of a chain with four servers. Each write request gets directed to the head server. The update pipelines from the head server to the tail server through the chain. Once all the servers have persisted the update, the tail responds to the write request. Read requests are directed only to tail servers. What a client can read from the tail of the chain replicates across all servers belonging to the chain, guaranteeing strong consistency. Chain replication vs. quorum replication Now that we have provided an overview of what chain replication entails, let’s explore how chain replication fares against other widely used replication strategies. Storage efficiency: Chain replication clearly does not offer the most storage-efficient replication strategy. We store redundant copies of the whole data set on all hosts in a chain. A comparatively efficient approach would involve intelligently replicating fragments of data using erasure coding techniques. Fault tolerance: In an optimal bucket layout, chain replication can provide similar or better fault tolerance than quorum-based replication mechanisms. Why? A chain with `n` nodes can tolerate failures up to `n - 2` nodes without compromising on availability. On the contrary, for quorum-based replication systems, at least `w` hosts must be available to serve writes. Additionally, `r` hosts must be available to serve reads. Here `w` and `r` represent the write quorum size and read quorum size, respectively. Performance: In replication strategies (like primary backup), all backup servers can serve reads. This increases read throughput. In the native idea of chain replication, only the chain tail can serve reads. (We optimized this bit and will share details in the apportioned queries section later in this post.) Much like quorum-based replication mechanisms, in chain replication all writes are directed to the primary (the head of the chain). But in chain replication, writes are only responded to after all hosts in the chain have acknowledged the update. Thus, chain replication has higher write latency on average in comparison with quorum-based replication mechanisms. Quorum consensus: Quorum-based systems need complex consensus and leader election mechanisms to maintain quorum in the system. In contrast, the scope of quorum consensus in a chain-replication based system gets narrowed down to the much simpler, chain-host mapping. For example, the chain head always serves as a leader for processing writes, without the need for an explicit leader election. Considering the above differences, chain replication clearly fails to offer the most storage-efficient way to replicate data across machines. Additionally, it yields higher average write latency in comparison to quorum-based systems, as we consider writes successful only when all links in a chain have persisted the update. However, it’s very simple while offering similar fault tolerance and consistency guarantees. The anatomy of a Delta bucket Now that we have a preliminary understanding of chain replication, let’s talk about how Delta leverages it to replicate data across multiple servers. Each Delta bucket above includes several chains. Each chain usually consists of four or more servers, which can vary based on the desired replication factor. Each chain itself acts as a replica set and serves a slice of data and traffic. It can be thought of as a logical shard of a client data set. Servers in a particular chain get spread across different failure domains (power, network, etc.). Doing so guarantees durability and availability of client data if servers in one or more failure domains remain unavailable. We maintain a bucket config, the authoritative chain-host mapping for the layout of the bucket. When we add or remove servers and chains from the bucket, the bucket config gets appropriately updated. When clients access an object within a Delta bucket, a consistent hash of the object name selects the appropriate chain. Writes are always directed to the head of the appropriate chain. It writes the data to the local storage and forwards the write to the next host in the chain. The write is acknowledged only after the last host in the chain has durably stored the data on local media. Reads are always directed to the tail of the appropriate chain. This guarantees that only fully replicated data is visible and readable, thereby guaranteeing strong consistency. Delta supports horizontal scalability by adding new servers into the bucket and smartly rebalancing chains to the newly added servers without affecting the service’s availability and throughput. As an example, one tactic is to have servers with the most chains transfer some chains to new servers as a way to rebalance the load. New bucket layouts would still follow the desirable failure-domai