SQL++/N1QL 쿼리

렌틱과 카우치베이스

알렉스 시르부 렌틱의 R&D 팀장으로, 안정적인 분산 시스템을 설계하고 구축하는 데 7년간의 경력을 보유하고 있습니다.

Lentiq 는 Kubernetes 기반의 멀티 클라우드 서비스형 데이터 레이크 스타트업으로, 다른 사람들의 데이터와 워크플로를 매일 관리하며 생계를 유지하고 있습니다. 이를 제대로 수행하기 위해서는 모든 내부 정보를 저장할 수 있는 빠르고 안정적이며 확장 가능한 데이터베이스가 필요하며, 마이크로서비스 지향 아키텍처를 구현할 수 있어야 합니다. 카우치베이스는 모든 요구 사항을 충족한다는 사실이 여러 차례 입증되었으며, 프로젝트가 시작된 이래로 우리가 선택한 데이터베이스였습니다. 따라서 다음은 Lentiq에서 유일한 영구 내부 스토리지 계층으로 Couchbase를 통합하고 사용해 온 역사를 소개합니다.

선택

애초에 왜 카우치베이스를 선택했을까요? 이에 대한 답은 이전 경험에서 찾을 수 있습니다. 우리 팀은 베어메탈 클라우드 프로젝트에서 다음과 같이 전환했습니다. Bigstep 의 모회사에서 새로운 Lentiq 프로젝트에 합류했습니다. 우리 동료들 중 일부는 Bigstep에서 사용하는 Couchbase 제품을 사용해 성능 테스트(얼마나 잘 작동하는지 보여주는)를 수행했을 뿐만 아니라 실제로 느린 관계형 데이터베이스 앞에서 캐시로 사용하기도 했습니다. Couchbase에 대한 이러한 이전 경험은 Lentiq의 내부 스토리지 계층을 선택해야 할 때 유용했습니다.

선택의 중요한 요소는 신제품의 아키텍처였습니다. 애플리케이션을 여러 개의 분리된 마이크로서비스로 분할함으로써 데이터베이스 계층에도 동일한 분리 원리를 적용해야 했습니다. 이렇게 하면 마이크로서비스가 다른 서비스에서 정보를 얻을 수 있는 유일한 방법은 노출된 인터페이스를 통해서만 가능하며 데이터베이스 우회가 허용되지 않는다는 사실과 함께 모듈 간의 우려를 더욱 강화할 수 있습니다. 또한 엄격한 스키마를 다루지 않고 빠르게 실험을 진행해야 했기 때문에 이 프로젝트에서는 NoSQL을 사용하기로 결정했습니다. 마지막으로, 프로젝트가 Java와 Spring으로 작성되어야 했기 때문에 데이터베이스와 쉽게 인터페이스할 수 있도록 지원하는 것도 필수적인 요소였습니다.

따라서 모든 요구 사항을 고려하고 오랜 친구인 CouchBase가 모든 상자를 어떻게 체크했는지 확인한 후 MVP로 CouchBase를 사용하기로 결정했으며 그 이후로 마음을 바꾸지 않았습니다!

 

아키텍처

후자의 두 가지 요구 사항은 매우 간단하지만, 첫 번째 요구 사항인 마이크로서비스 기반 아키텍처를 달성하기 위해 Couchbase를 어떻게 사용했을까요?

확실한 해결책은 마이크로서비스당 버킷을 할당하고, 시작 시 각 서비스에 클러스터 액세스 자격 증명을 부여하여 각 사용자에게 특정 버킷에만 액세스할 수 있는 별도의 사용자를 부여하는 것이었습니다. 간단하죠? 분리된 모듈을 사용함으로써, 우리는 (대부분) 각 마이크로서비스가 밀접하게 작동하는 객체 유형을 하나만 가질 수 있었습니다. 이 특정 객체에는 공개(외부 마이크로서비스에서 액세스할 수 있는 외부) 필드와 내부 필드가 모두 있습니다. 모든 필드는 버킷 내부에 저장되지만, 개체는 소유자의 외부 인터페이스를 통해 공개 필드만 정리되어 노출됩니다.

이러한 할당은 확장성과 안정성에도 도움이 되었습니다. 처음에는 마이크로서비스가 거의 없었기 때문에 모든 버킷을 동일한 Couchbase 클러스터 안에 배치했습니다. 점점 더 많은 버킷을 추가하면서 트래픽과 개체 크기에 따라 그룹화하고 여러 클러스터에 분할하여 더욱 격리하고 독립적으로 확장할 수 있도록 했습니다.

 

쿼리

다음을 사용하여 Spring 데이터 카우치베이스 라이브러리 , 데이터 읽기 및 쓰기를 위해 Couchbase에 연결하고 실제로 사용하는 것이 쉬워집니다.

일반적인 읽기 및 쓰기 작업은 CouchbaseRepositories와 CouchbaseTemplates(삽입, 업데이트, 삭제, findById)에서 제공합니다. 이러한 기본 작업을 확장할 수 있다는 점이 큰 도움이 됩니다. 예를 들어, 데이터 풀이라고 부르는 미니 데이터 레이크 내의 모든 프로젝트 환경에 대한 쿼리는 다음과 같은 리포지토리 클래스만 있으면 됩니다:

더 복잡한 쿼리(예: 배열 내부의 값 검색)의 경우, 배열 내부의 값을 검색하려면 N1Q1 쿼리 언어 는 주어진 함수에 대한 주석을 추가하는 것만큼이나 간단합니다. 다음 예는 주어진 상태의 모든 데이터 집합을 반환하고 해당 가시성 배열에서 필요한 가시성을 포함하는 데이터 집합을 식별합니다:

n1q1.filter 필드는 요청된 유형의 개체만 반환하도록 "_class=**SpecifiedClassForRepository**"로 자동 채워지므로 특별한 작업 없이도 여러 유형의 개체를 동일한 버킷에 저장할 수 있습니다.

잠금

저희는 데이터 저장 및 쿼리뿐만 아니라 서비스 잠금을 수행하는 데에도 Couchbase를 사용하고 있습니다.

잠금이 필요한 한 가지 예는 클라이언트가 일부 데이터를 분석하기 위해 새 애플리케이션을 만들고자 할 때 사용자가 애플리케이션을 부팅하기에 충분한 리소스를 가지고 있는지 확인해야 하는 경우입니다. 잠금이 꼭 필요한 상황은 아닌 것 같죠? 저희 환경은 협업 환경이고 여러 사람이 같은 프로젝트에서 작업할 수 있기 때문에 여러 클라이언트가 같은 환경 내에서 동시에 애플리케이션을 만들 수 있습니다. 따라서 특정 환경에 잠금을 사용하지 않으면 각 개인의 애플리케이션이 부팅되더라도 동시에 부팅하려고 하면 실제 물리적 리소스가 초과되어 한 애플리케이션 또는 애플리케이션에 여러 구성 요소가 있는 경우 둘 다 실패할 수 있습니다. 따라서 다른 생성 작업에서 새 애플리케이션을 고려할 수 있을 때까지 잠금을 유지하면서 검사를 수행해야 합니다.

그렇다면 잠금 솔루션은 무엇일까요? 비관적 잠금은 getAndLock 및 잠금 해제의 형태로, 잠금이 유지되는 동안 특정 문서에 대한 액세스를 차단합니다. 다음은 간단한 예시입니다:

 

이 접근 방식에서 직면하는 주요 문제는 getAndLock이 실제로 항상 작동하려면 잠그는 문서가 이전에 존재해야 하며, 원자적인 getOrCreateAndLock이 없다는 것입니다. 이 문제를 해결하기 위해 잠금은 액세스를 잠그는 환경과 연결되어 있으므로 실제로 잠금 문서 생성 및 삭제를 환경의 생성 및 삭제 흐름과 통합했습니다. 따라서 클라이언트가 애플리케이션을 생성할 때 이미 문서가 생성되어 있으므로(전체 환경 생성 프로세스가 미리 완료되어야 하므로) 잠금이 제대로 수행될 수 있습니다. 또한 특정 환경이 삭제되면 문서도 삭제되어 버킷에 아무 일도 하지 않고 남아 있지 않습니다.

 

결론

렌틱은 안정적이고 빠른 스토리지 계층이 고객과 내부 서비스 모두에 가장 중요하다는 것을 잘 알고 있습니다. 내부 마이크로 서비스를 위한 데이터베이스 레이어로 Couchbase를 선택한 것이 올바른 결정이었음을 입증했으며, 적절한 NoSQL 데이터베이스가 필요하다면 Couchbase를 진심으로 추천합니다!

이 게시물은 카우치베이스에서 제공한 것입니다. 커뮤니티 글쓰기 프로그램

이 문서 공유하기
받은 편지함에서 카우치베이스 블로그 업데이트 받기
이 필드는 필수 입력 사항입니다.

Author

Posted by Laura Czajkowski

로라 챠코브스키는 카우치베이스의 Snr. 개발자 커뮤니티 매니저로 카우치베이스의 커뮤니티를 총괄하고 있습니다. 그녀는 월간 개발자 뉴스레터를 담당하고 있습니다.

댓글 남기기

카우치베이스 카펠라를 시작할 준비가 되셨나요?

구축 시작

개발자 포털에서 NoSQL을 살펴보고, 리소스를 찾아보고, 튜토리얼을 시작하세요.

카펠라 무료 사용

클릭 몇 번으로 Couchbase를 직접 체험해 보세요. Capella DBaaS는 가장 쉽고 빠르게 시작할 수 있는 방법입니다.

연락하기

카우치베이스 제품에 대해 자세히 알고 싶으신가요? 저희가 도와드리겠습니다.