애플리케이션 디자인

카우치베이스에서 분산 다중 문서 ACID 트랜잭션을 구현한 방법

산 거래 는 애플리케이션에 엄격한 데이터 일관성 요구 사항이 있는 경우 필수입니다. 분산 시스템에서 트랜잭션을 실행하는 데 드는 비용으로 인해 대규모 병목 현상이 빠르게 발생할 수 있습니다. 이 글에서는 NoSQL 및 NewSQL 데이터베이스가 직면한 몇 가지 문제에 대한 개요를 제공합니다. 그런 다음 Couchbase가 중앙 조정과 단일 장애 지점 없이 확장 가능한 분산 트랜잭션 모델을 구현한 방법에 대해 자세히 살펴봅니다. 또한 Couchbase 7.0에서 N1QL의 트랜잭션 지원이 어떻게 이루어지는지에 대한 간략한 개요도 제공합니다.

간결함을 위해 일부 사소한 세부 사항은 생략했습니다.

 

관계형 트랜잭션 vs NewSQL 트랜잭션 vs NoSQL 트랜잭션

Couchbase가 트랜잭션 지원을 구현한 방법을 설명하기 전에 먼저 관계형 및 NoSQL 데이터베이스의 원자성 고유 특성(JSON과 같은 반정형 데이터 모델 사용)에 대해 설명해야 합니다:

 

RDBMS의 원자성

데이터베이스에 새 사용자를 저장해야 한다고 가정해 보겠습니다. 당연히 이 테이블에는 다른 많은 테이블이 연결되어 있으므로 사용자를 삽입하려면 다른 많은 테이블에도 삽입해야 합니다:

Transactions on Relational

관계형 모델에서는 모든 것을 '상자'에 저장하고 데이터를 작은 조각으로 분할해야 하므로 새 사용자를 추가할 때는 항상 트랜잭션 컨텍스트 내에서 실행해야 합니다. 그렇지 않으면 삽입 중 하나가 실패하면 사용자가 절반만 저장됩니다. 70년대에 관계형 모델이 처음 설계되었을 때보다 애플리케이션이 훨씬 더 복잡해졌기 때문에 RDBMS가 트랜잭션에 크게 의존하는 방식에 주목하세요.

다행히도 이러한 데이터베이스는 단일 노드에서 실행되도록 설계되었으므로 중앙 트랜잭션 코디네이터를 사용하여 성능에 영향을 주지 않고 한 번에 데이터를 커밋할 수 있습니다.

 

NewSQL의 원자성

NewSQL(분산 관계형)에서는 상황이 조금 더 복잡해집니다. 이러한 데이터베이스의 대부분은 관계형 모델을 재사용하므로 엔티티의 데이터(또는 집계 루트)는 여러 노드에 분산되는 경향이 있습니다.

atomicity in newsql

위 이미지에서 사용자를 메모리에 로드해야 하는 경우 먼저 서버 1에서 사용자를 가져온 다음 서버 2에서 사용자와 역할 간의 연결을 로드하고 마지막으로 서버 3에서 대상 역할을 로드해야 합니다. 이 간단한 작업은 데이터가 네트워크를 통해 최소 두 번 이상 이동해야 하므로 궁극적으로 읽기 성능이 제한됩니다. 실제 시나리오에서는 사용자에 연결된 테이블이 훨씬 더 많습니다. 그렇기 때문에 가능한 한 빨리 읽고 써야 할 때 분산 관계형은 아직 실용적이지 않습니다.

클러스터의 크기를 제한하거나, 인덱스에 크게 의존하여 모든 관계를 추적하거나, 샤딩 기술을 사용하여 모든 관련 데이터를 동일한 노드에 보관함으로써 위의 문제를 최소화할 수 있습니다(실제로 구현하기는 어렵지만). 마지막 두 가지 접근 방식은 제대로 구현되더라도 데이터베이스에서 상당한 리소스를 소모하여 제대로 관리해야 합니다.

엔티티와 관련된 데이터가 서로 다른 노드에 있을 수 있는 여러 테이블로 나뉘어져 있기 때문에 NewSQL 데이터베이스의 ACID 트랜잭션은 NoSQL보다 더 많은 조정이 필요합니다. 오늘날 우리가 사용하는 관계형 모델에서는 대부분의 쓰기, 업데이트, 계단식 삭제에 트랜잭션이 필요합니다. NewSQL 아키텍처에 필요한 추가적인 조정 작업은 지연 시간이 짧은 작업이 필요한 애플리케이션의 처리량 감소라는 대가를 치르게 됩니다.

 

문서 데이터베이스의 원자성

JSON과 같은 반정형 데이터를 사용하면 '교차 노드 조인'의 수를 대폭 줄일 수 있으므로 인덱싱에 지나치게 의존하지 않고도 읽기/쓰기 성능을 향상시킬 수 있습니다. 이 점이 바로 다이나모 종이 (약 13년 전에 처음 출판됨)은 촉매제를 사용하여 오늘날 우리가 알고 있는 NoSQL 데이터베이스를 만들었습니다.

반정형 데이터 모델의 또 다른 흥미로운 특징은 전체 사용자 데이터를 하나의 문서에 담을 수 있기 때문에 트랜잭션이 적다는 점입니다:

atomicity nosql

위 이미지에서 볼 수 있듯이 사용자 기본 설정과 역할은 "사용자 문서" 안에 쉽게 들어갈 수 있으므로, 작업이 원자적이므로 사용자를 삽입하거나 업데이트하기 위한 트랜잭션이 필요하지 않습니다. 문서를 삽입하지 않으면 전체 작업이 실패합니다. 쇼핑 카트, 제품, 트리 구조, 기타 여러 일반적인 사용 사례에도 동일하게 적용됩니다. 집계 루트 일반적으로

문서 데이터베이스를 사용하는 대부분의 애플리케이션에서 트랜잭션 작업 중 90%가 이 단일 문서 범주에 속합니다. 하지만... 나머지 10%는 어떨까요? 이러한 경우에는 버전 6.5부터 Couchbase에 추가된 다중 문서 트랜잭션 지원이 필요하며 이 글의 주요 초점입니다.

다음은 Couchbase Connect 2020에서 제공된 트랜잭션에 대한 프레젠테이션입니다. Matt Ingenthron이 다중 문서 ACID 트랜잭션이 필요한 경우와 그 이유에 대해 설명합니다:

다음에서 전체 버전을 시청하세요. https://www.youtube.com/watch?v=2fsZVe2cT3M&ab_channel=Couchbase

 

비디오 대본

전문을 읽으려면 클릭하세요.

가상이지만 어쩌면 현실적일 수 있는 카우치베이스 시스템의 문서 모델 예시를 통해 이를 어떻게 적용하는지 이야기해 보겠습니다. 우리는 돈을 모아서 플레이어와 몬스터가 등장하는 대규모 멀티플레이어 온라인 롤플레잉 게임(MMORPG)을 만들려고 합니다. 그래서 데이터 모델이 필요합니다. 

플레이어가 몬스터와 싸우고 그 싸움에 따라 승패가 갈리게 될 것입니다. 승리하면 무기를 얻고, 패배하면 체력이 떨어지므로 아무도 죽지 않습니다. 언제든 다시 살아날 수 있고 다른 날을 찾을 수 있습니다. 하지만 플레이어는 몬스터와 싸우고, 저희는 1.0 버전을 만들게 됩니다. 잘됐네요! 좋아요, 자금도 확보했고 1.0 버전도 만들었어요.

문제는 대규모 멀티플레이어 부분을 잊어버렸다는 점입니다. 협업 플레이가 없습니다. 여러 플레이어가 같은 몬스터와 싸우게 할 수 없죠. 그래서 이 문제를 해결해야 하죠? 그래서 새 버전을 출시하기로 했습니다. 플레이어는 계속해서 몬스터와 싸우고 무기를 획득할 수 있습니다.

그래서 2.0 버전을 출시했고, 2.0 버전에서는 플레이어가 함께 몬스터와 싸울 수 있습니다. 친구들과 협동하여 몬스터를 찾아서 죽일 수 있습니다. 

하지만 버그가 남아있었습니다. 여러 플레이어가 사망 일격을 가할 수 있는데, 이것이 문제가 되는 이유는 게임 플레이어가 이를 알아차리기 때문입니다. 이 대규모 멀티플레이어 월드에서 플레이어들은 몬스터와 함께 죽을 때까지 싸우는 대신, 죽을 때까지 싸우다가 여러 플레이어가 함께 모여서 모두 죽음의 일격을 가하거나 여러 명이 동시에 죽음의 일격을 가할 수 있습니다. 

문제는 아이템을 획득하고, 여러 아이템을 획득하고, 아이템에는 희귀도가 있기 때문에 아이템의 희귀도가 일정 수준 이상이면 게임 플레이가 그다지 흥미롭지 않다는 것입니다. 이 버그로 인해 세상에 너무 많은 아이템이 존재하게 되었고, 플레이어는 게임을 해킹하는 데만 시간을 보내다가 지루해져서 게임을 떠나게 됩니다. 게임플레이를 흥미롭게 유지해야 합니다.

그럼 이 문제에 대해 생각해 봅시다. 이 문제를 어떻게 해결할 수 있을까요? 아마도 수정책을 도입해야 할 것 같습니다. 플레이어와 몬스터, 여러 플레이어가 한 몬스터와 싸우는 것은 여전히 허용할 것입니다. 하지만 우리가 할 일은 우리가 가진 트릭 중 하나를 취하는 것입니다. 카우치베이스 CAS 운영.

와 함께 CAS 작동 이제 여러 플레이어가 해당 몬스터와 싸우면서 몬스터의 공격력이 0이 될 때까지 공격력을 낮추는 것입니다. 하지만 그 중 단 한 명의 플레이어만이 그 몬스터에게 치명타를 가하고 아이템을 획득할 수 있습니다.

따라서 두 명의 플레이어가 죽음의 일격을 가하려고 하면 요청을 처리하는 서버가 문서를 수정하려고 시도합니다. 이 서버는 불투명한 정보 중 일부를 가져와야 하는데, 이를 CAS(확인 및 설정의 약자)따라서 불투명도가 일치하지 않으면 문서가 이미 수정된 것이므로 해당 작업을 다시 시도해야 합니다. 시스템 내의 두 행위자가 동시에 해당 문서를 가져가려고 하는 시나리오에서 우리가 원하는 것은 하나는 성공하고 하나는 실패하는 것인데, CAS는 매우 효율적인 방법으로 이를 제공합니다.

그 트릭을 꺼내서 CAS 작업을 도입하고 버그가 수정되었으며 게임플레이가 훨씬 더 흥미로워졌고 2.1은 정말 잘 작동하므로 매우 훌륭합니다.

이제 좀 더 흥미롭게 만들어 보겠습니다. 이제 다른 기능을 소개한다고 상상해 보세요: "플레이어들은 여전히 몬스터와 함께 싸울 수 있지만, 도시 밖에서 해야 합니다. 따라서 플레이어가 있는 도시 성벽 밖에 있어야 하고, 도시 안으로 들어가면 기괴한 거래를 하게 됩니다."

처음에는 정말 잘 작동하지만 플레이어가 무언가를 알아챕니다.

플레이어1에 대한 문서를 검색해야 한다고 가정해 보겠습니다. 그런 다음 플레이어2에 대한 문서를 검색해야 합니다. 그런 다음 플레이어1에서 플레이어2로 검을 이동해야 하는데, 이는 애플리케이션 로직에서 매우 쉽게 수행할 수 있으며, CAS 작업을 통해 해당 변경 사항을 시스템에 다시 저장한 다음 다른 변경 사항을 다시 저장하면 되겠죠? 멋질 것 같네요. 버그가 있다는 것만 빼면요.

여기서 버그는 플레이어가 거래를 시작했다가 연결을 끊으면 희귀 아이템으로 만들고 싶었던 아이템이 희귀 아이템이 되지 않는다는 것입니다. 시스템 내에서 복제할 수 있습니다.

대규모 멀티플레이어 온라인 롤플레잉 게임에서는 이를 듀프 버그라고 합니다. Google에 가서 "중복 버그"를 검색하면 많은 시나리오를 찾을 수 있습니다.

다음은 불과 몇 주 전 스위치 버전의 파이널 판타지 크리스탈 크로니클이 듀프 버그로 인해 패치를 해야 했던 사례입니다. 그리고 그 며칠 전에는 한 게임 블로거가 이 중복 버그를 사용하여 게임 내에서 추가 아이템을 획득하는 방법을 보여주는 블로그에 올라온 영상이 있었습니다.

따라서 이 버그를 수정해야 합니다. 어떻게 할까요? Couchbase의 트릭 가방에 손을 뻗어 보겠습니다.

이제 카우치베이스 트랜잭션을 소개하겠습니다. 게임 플레이는 거의 똑같습니다. 하지만 카우치베이스 트랜잭션으로 무엇을 할까요? 그래서 이 슬라이드에서 코드에 대해 조금 이야기하겠습니다.

 

카우치베이스의 다중 문서 분산 ACID 트랜잭션

 

이제 다양한 데이터 모델에서 트랜잭션이 어떻게 작동하는지 이해하셨으니, 이제 Couchbase에서 이를 구현한 방법과 설계 선택의 배경에 대해 자세히 알아볼 차례입니다. 먼저 구문을 살펴보겠습니다:

위의 Java 예제는 두 클라이언트 간에 송금하는 방법을 보여주는 전형적인 예시입니다. 여기서는 람다 함수 를 사용하여 트랜잭션을 표현할 수 있습니다. 이 시나리오에서는 적절한 오류 처리가 어려울 수 있으며, 트랜잭션을 익명 함수로 래핑하면 Couchbase Java SDK가 해당 작업을 대신 수행할 수 있습니다(예: 실패 시 재시도).

트랜잭션 지원을 처음 시작했을 때 저희는 장황함을 피하려고 노력했습니다. 한 경쟁사의 트랜잭션 구문이 바로 이런 식이었죠:

최근에는 람다 함수 내에서 트랜잭션을 처리하는 것이 NoSQL 데이터베이스의 표준이 되고 있는 것 같습니다.

트랜잭션의 관계형 구문(예: BEGIN/COMMIT/ROLLBACK SQL 명령)과 비슷할 것이라고 예상하신 분들은 계속 읽으세요. N1QL을 통해서도 트랜잭션을 실행할 수 있습니다! 이제 내부에서 어떤 일이 벌어지고 있는지 알아보겠습니다.

 

카우치베이스 아키텍처 검토

Couchbase의 아키텍처에 익숙하지 않은 분들을 위해 더 진행하기 전에 4가지 중요한 개념을 빠르게 설명하겠습니다:

  • Couchbase는 확장성이 뛰어나 단일 클러스터에서 1개에서 100개 노드까지 쉽게 확장할 수 있습니다. 최소한의 노력으로 
  • JSON 문서에는 다음과 같은 "메타" 공간이 있습니다. xAttr 문서에 대한 메타데이터를 저장할 수 있습니다..
  • 각 버킷 내부(RDBMS의 스키마와 유사)에서 Couchbase는 데이터를 1024개의 샤드로 자동 분산시켰습니다. vBuckets. 샤딩은 개발자에게 완전히 투명하게 공개되며, 샤딩 전략도 저희가 관리합니다. 당사의 샤딩 알고리즘(CRC32)은 기본적으로 문서가 이러한 vBuckets 간에 고르게 분산되도록 보장하며 리샤딩이 전혀 필요하지 않습니다. 클러스터의 노드 간에 균등하게 분산됩니다(예: 4개의 노드로 구성된 클러스터의 경우, 각 노드에 256개의 vBucket이 있음).

  • 클라이언트의 SDK는 클러스터 맵의 사본을 저장하는데, 이는 vBuckets 및 해당 클러스터를 담당하는 노드의 해시맵입니다. 문서의 키를 해시함으로써 SDK는 문서가 어느 vBucket에 있어야 하는지 찾을 수 있습니다. 또한 클러스터 맵 덕분에 저장/삭제/업데이트 작업 중에 문서를 담당하는 노드와 직접 대화할 수 있습니다. 

bucket to server mapping

위의 설계 선택으로 Couchbase는 다른 NoSQL 데이터베이스에서 사용되는 전통적인 마스터/슬레이브 대신 마스터리스 아키텍처(마스터/마스터라고도 함)를 가질 수 있습니다. 이러한 아키텍처의 장점은 여러 가지가 있지만, 현재 우리에게 관련된 것은 다음과 같습니다:

  • SDK는 특정 문서의 위치를 알고 있으므로 삽입/업데이트/삭제 작업 중에 "한 번의 네트워크 홉"을 절약합니다(마스터/슬레이브 아키텍처에서는 문서의 위치를 마스터에게 물어봐야 합니다).
  • 데이터베이스 자체에는 중앙 코디네이터가 없으므로 단일 장애 지점이 없습니다. 실제로 클라이언트는 클러스터에서 어느 노드와 통신할지 정확히 알고 있기 때문에 간접적으로 경량 코디네이터 역할을 합니다.

 

중앙 코디네이터가 없는 분산 트랜잭션

 

카우치베이스의 아키텍처에서는 각 클라이언트가 자체 트랜잭션을 조정할 책임이 있습니다. 당연히 모든 작업은 SDK 수준에서 내부적으로 이루어집니다. 간단히 말해, 트랜잭션을 실행하는 애플리케이션의 인스턴스가 100개라면 잠재적으로 최대 100개의 코디네이터가 있다는 뜻입니다. 이러한 코디네이터는 애플리케이션에 거의 오버헤드를 추가하지 않으며, 그 이유를 곧 알게 될 것입니다.

코드 예제에 표시된 송금 예시를 다시 사용하고 이 거래에 관련된 문서 2개가 서로 다른 두 노드에 있다고 가정하면 1,000피트 뷰에서 거래는 다음과 같은 단계를 따릅니다:

distribute transaction flow

  1. 각 vBucket에는 다음과 같은 트랜잭션 로그를 담당하는 단일 문서가 있습니다. 활성 거래 기록 (ATR). ATR은 다음과 같이 쉽게 식별할 수 있습니다.  TXN:ATR- ID 접두사를 추가합니다. 첫 번째 문서 변경 전( ctx.대체(userA, 사용자 콘텐츠) 이 경우)에 새 항목이 추가됩니다. ATR 를 트랜잭션 ID와 "보류 중" 상태의 동일한 vBucket에 추가합니다. 하나만 ATR 는 트랜잭션당 사용됩니다.
  2. 트랜잭션 ID와 첫 번째 변이의 내용입니다, ctx.대체(userA, 사용자 콘텐츠)에서 진행되며 xAttrs 의 첫 번째 문서("userA")를 사용합니다.
  3. 트랜잭션 ID와 두 번째 변이의 내용입니다, ctx.대체(userB, userBContent)에서 진행되며 xAttrs 두 번째 문서 "userB"의
  4. 트랜잭션은 거래가 "커밋됨"으로 표시됩니다. ATR. 또한 이 호출을 활용하여 트랜잭션에 관련된 문서 ID 목록을 업데이트합니다.
  5. 문서 "userA"가 스테이징되지 않은 상태입니다( xAttrs 문서 본문을 대체합니다)
  6. 문서 "userB"가 스테이징되지 않은 상태입니다( xAttrs 문서 본문을 대체합니다)
  7. 트랜잭션은 "완료됨"으로 표시되고 ATR

이 구현은 다음에 의해 제한되지 않습니다. 범위, 컬렉션, 또는 샤드(vBuckets). 실제로 여러 버킷에서 트랜잭션을 실행할 수도 있습니다. 충분한 권한만 있으면 클러스터 내의 모든 문서가 트랜잭션의 일부가 될 수 있습니다.

이 시점에서 모든 잠재적 장애 시나리오에 대해 궁금한 점이 많으실 것으로 생각합니다. 여기서 가장 중요한 주제를 다루도록 하겠습니다. 의견을 남겨 주시면 그에 따라 글을 업데이트하도록 노력하겠습니다.

격리 처리 - 단조로운 원자 보기

Jepsen 에는 데이터베이스의 가장 중요한 일관성 모델을 설명하는 멋진 그래프가 있습니다:

Consistency Models

카우치베이스는 다음을 지원합니다. 커밋된 읽기/단조로운 원자 보기" 일관성 모델. 하지만 얼마나 좋은가요? 글쎄요, 커밋된 읽기 는 Postgres, MySQL, MariaDB 및 기타 여러 데이터베이스의 기본 옵션이며, 해당 옵션을 변경하지 않았다면 현재 사용 중인 옵션입니다.

커밋된 읽기 는 애플리케이션이 커밋되지 않은 데이터를 읽을 수 없도록 보장하지만, 여기서 흥미로운 부분은 커밋 프로세스가 실제로 어떻게 진행되는지입니다. 관계형 데이터베이스에서는 트랜잭션에서 변경된 행의 새 버전이 이전 버전을 모두 동시에 승계하도록 조정하는 경우가 많습니다. 이를 일반적으로 쓰기-포인트 커밋. 그러기 위해서는 멀티버젼 동시성 제어(MVCC) 가 필요합니다. 이는 빠른 읽기/쓰기가 핵심인 ACID 분산 데이터베이스에서 구현하는 데 드는 비용(성능 측면)은 말할 것도 없고, 그에 수반되는 모든 짐 때문에 문제가 될 수 있습니다.

쓰기 지점 커밋의 또 다른 단점은 커밋을 동기화하는 데 귀중한 시간을 소비할 수 있지만 다른 스레드가 커밋을 바로 읽지 않아 동기화에 소요되는 모든 노력이 낭비된다는 점입니다. 이런 경우 모노토닉 원자 뷰(MAV) 가 등장합니다. 이 기능은 처음 고가용성 트랜잭션: 장점과 한계 디자인에 큰 영향을 미쳤습니다.

MAV를 사용하면 읽기 지점에서 원자 커밋을 대신 제공할 수 있으므로 성능이 크게 향상됩니다. 실제로 어떻게 작동하는지 살펴봅시다:

 

반복 가능한 읽기 및 단조로운 원자 뷰

트랜잭션 예제에서는 다음과 같은 경우 4단계 에서 트랜잭션을 "커밋됨"으로 설정했지만 트랜잭션과 관련된 문서의 데이터를 아직 스테이징 해제하지 않은 경우입니다. 그렇다면 이 간격 동안 다른 클라이언트가 데이터를 읽으려고 하면 어떻게 될까요?

transaction failure scenario

내부적으로 SDK는 혹시라도 스테이징된 콘텐츠가 있는 문서를 발견하면 ATR을 읽어 트랜잭션 상태를 가져옵니다. 상태가 "커밋됨"이면 대신 스테이징된 버전을 반환합니다. 끝! 읽기 시간에 발생했을 때 간단히 해결할 수 있다면 쓰기를 동기화할 필요가 없습니다. 

 

분산 데이터베이스의 내구성

데이터베이스의 가장 중요한 역할 중 하나는 기록된 내용이 기록된 상태로 유지되도록 하는 것입니다. 노드에 장애가 발생하더라도 데이터가 손실되지 않아야 합니다. Couchbase에서는 두 가지 기능을 통해 이를 달성합니다: 버킷 복제본과 SDK의 내구성입니다.

버킷을 만드는 동안 원하는 각 문서의 복제본(백업) 개수를 구성할 수 있습니다. (2개가 가장 일반적인 선택입니다). 이 옵션을 사용하면 잠재적인 데이터 손실 없이 N개의 노드를 잃을 수 있습니다.

Atomicity-new SQL

카우치베이스는 기본적으로 항상 가장 빠른 방법을 사용하도록 설정되어 있으므로 데이터가 서버에 도착하자마자 클라이언트에 쓰기가 성공했다는 확인 메시지가 전송되고 모든 데이터 복제가 내부적으로 처리됩니다. 그러나 서버가 데이터를 복제하기 전에 서버에 장애가 발생하면(메모리 간 복제가 이루어지기 때문에 마이크로초에서 몇 밀리초 정도 걸립니다) 자연스럽게 변경 내용이 손실될 수 있습니다. 가치가 낮은 일부 데이터에는 괜찮을 수 있지만... 이봐요! 이것은 ACID의 "내구성"을 완전히 위반하는 것입니다. 그렇기 때문에 저희는 사용자가 직접 내구성 요구 사항:

durabilty options

그리고 대다수 (트랜잭션 라이브러리의 기본 옵션)을 선택했다는 것은 변이가 대부분의 데이터 서비스 노드에 복제(즉, 버킷에 할당된 메모리에 보관)되어야 한다는 의미입니다. 다른 옵션은 다음과 같습니다: majorityAndPersistActive, 그리고 persistToMajority. 참조하세요 내구성 요구 사항에 대한 공식 문서를 참조하세요. 를 클릭해 작동 방식을 더 잘 이해하세요. 이 기능은 문서가 저장되었는지 비관적으로 확인해야 하는 경우 트랜잭션 외부에서도 사용할 수 있습니다.

 

거래 중에 문제가 발생하면 어떻게 되나요?

트랜잭션이 롤백되기 전에 얼마나 오래 지속될지 구성할 수 있습니다. 기본값은 15초입니다. 이 시간 내에 동시성 또는 노드 문제가 있는 경우 트랜잭션이 이 시간에 도달할 때까지 대기 및 재시도를 조합하여 사용합니다.

트랜잭션을 관리하는 클라이언트가 갑자기 연결을 끊으면 문서의 메타데이터에 일부 스테이징된 콘텐츠가 남을 수 있습니다. 그러나 동일한 문서를 수정하려는 다른 클라이언트는 이미 만료된 트랜잭션의 일부이므로 스테이징된 콘텐츠를 덮어쓸 수 있음을 인식할 수 있습니다.

또한 트랜잭션 라이브러리는 주기적으로 정리를 실행하여 ATR에서 비활성 트랜잭션을 제거하여 가능한 한 작게 유지합니다.

 

N1QL을 사용한 분산 SQL 트랜잭션

N1QL 은 SQL++ 사양을 구현하는 쿼리 언어로, SQL92와 호환되지만 구조화되고 유연한 JSON 문서용으로 설계되었습니다. 자세히 알아보기 이 대화형 N1QL 튜토리얼에서.

지금까지 설명한 분산 트랜잭션 솔루션은 애플리케이션 수준의 트랜잭션에 적합합니다. 하지만 때로는 임시 데이터 변경을 실행해야 할 때가 있습니다. 또는 작업에 관련된 문서의 수로 인해 애플리케이션 메모리에서 문서를 조작하는 것이 비용이 많이 드는 작업(예: 모든 사용자의 계정에 10크레딧 추가)이 될 수 있습니다. Couchbase Server 7.0에서는 대부분의 관계형 데이터베이스와 거의 동일한 SQL 구문을 사용하여 N1QL을 통해 트랜잭션을 실행할 수 있습니다:

NoSQL Transactions Vs Relational Transactions

N1QL 트랜잭션은 이미 다음에서 제대로 도입되었습니다. N1QL을 사용한 카우치베이스 트랜잭션 그리고 "N1QL을 통한 분산 트랜잭션의 사용 사례 및 모범 사례"이 주제에 대해서는 자세히 설명하지 않겠습니다. 천 피트 높이에서 보면 트랜잭션은 쿼리 서비스. 카우치베이스는 모듈식이기 때문에 쿼리 서비스를 실행하는 노드를 확장하거나 축소하여 트랜잭션 처리량을 늘릴 수 있습니다.

N1QL과 람다 트랜잭션을 함께 사용할 수 있지만 가능하면 트랜잭션 라이브러리만 사용하는 것이 좋습니다.

 

결론: 트랜잭션을 위한 최고의 NoSQL

카우치베이스는 이미 원자 단일 문서 작업과 낙관적 잠금 및 비관적 잠금 를 오랫동안 사용해 왔습니다. 작년에 버킷, 컬렉션, 범위 또는 샤드에 관계없이 빠른 트랜잭션 지원을 도입했습니다. Couchbase 7.0에서는 기존의 관계형 트랜잭션 구문을 그대로 사용할 수도 있습니다. 이러한 모든 기능의 조합으로 대규모 트랜잭션을 위한 최고의 NoSQL인 Couchbase.

저렴한 비용 - 사용한 만큼만 지불

총 트랜잭션 오버헤드는 단순히 문서 변경 수 + 3(보류 중, 커밋됨, 완료됨으로 표시된 ATR)입니다. 예를 들어 트랜잭션 컨텍스트에서 송금 예제를 실행하면 데이터베이스에 대한 추가 호출이 최대 5회 발생합니다. 

트랜잭션 라이브러리는 SDK 위에 있는 계층으로, 성능에 영향을 미치지 않는 트랜잭션에 대한 지원을 추가했습니다(다른 플레이어는 쉽게 주장할 수 없는 기능입니다). 이는 탄탄한 아키텍처 덕분에 가능했습니다.

 

중앙 거래 관리자 또는 중앙 코디네이터 없음 

카우치베이스의 마스터리스 아키텍처와 고객이 직접 트랜잭션을 관리한다는 사실을 고려할 때, 중앙 조정이나 단일 장애 지점이 없는 구현이 가능합니다. 노드 장애 중에도 장애가 발생한 서버의 문서를 건드리지 않는 트랜잭션은 성공적으로 완료될 수 있습니다. 실제로 최대 트랜잭션 시간을 적절히 조절하면 장애가 발생한 노드에서 문서를 건드리더라도 트랜잭션이 완료됩니다, Couchbase의 노드 장애 조치  는 트랜잭션이 만료되기 전에 결함이 있는 서버를 격리하고 새 노드를 승격시킬 수 있을 만큼 빠릅니다.

 

내부 글로벌 클럭 및 MVCC 없음

일부 트랜잭션 구현에는 글로벌 클럭이라는 개념이 필요한데, 이는 분산 환경에서 전용 하드웨어 없이 유지보수하는 데 많은 비용이 들 수 있습니다. 경우에 따라 클럭 스큐가 최대 250밀리초보다 높으면 데이터베이스가 다운될 수도 있습니다. 

MVCC(다중 버전 동시성 제어)와 글로벌 클럭을 사용하면 기술적으로 더 높은 수준의 일관성을 달성할 수 있습니다. 반면에 데이터베이스의 전반적인 성능에 영향을 미칠 가능성이 높습니다. Couchbase는 관계형 데이터베이스가 기본적으로 지원하는 것과 동일한 읽기 커밋 일관성 모델을 지원합니다.

 

유연성

다음을 사용할 수 있습니다. 내구성 옵션 트랜잭션 컨텍스트 내부와 외부에서 낙관적 및 비관적 잠금 를 사용하여 잠재적인 동시성 문제를 방지하고 SDK 및/또는 N1QL을 통해 트랜잭션을 사용합니다. Couchbase를 기반으로 모든 종류의 애플리케이션을 구축하고 비즈니스 요구사항에 따라 성능을 미세 조정할 수 있는 유연성이 매우 뛰어납니다.

 

다음 단계는 무엇인가요?

다음은 방금 논의한 내용에 대해 자세히 알아보고 Couchbase를 시작하는 데 도움이 되는 몇 가지 링크입니다:

거래에 대해 자세히 알아보기 https://www.couchbase.com/transactions
Java SDK 트랜잭션 https://docs.couchbase.com/java-sdk/current/howtos/distributed-acid-transactions-from-the-sdk.html
NET SDK 트랜잭션 https://docs.couchbase.com/dotnet-sdk/current/howtos/distributed-acid-transactions-from-the-sdk.html
C++ SDK 트랜잭션 https://docs.couchbase.com/cxx-txns/current/distributed-acid-transactions-from-the-sdk.html
N1QL 트랜잭션 https://www.couchbase.com/blog/couchbase-transactions-with-n1ql/
Couchbase 다운로드 https://www.couchbase.com/downloads
Couchbase 7.0의 새로운 기능은 무엇인가요? https://docs.couchbase.com/server/7.0/introduction/whats-new.html

 

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

Author

Posted by 데니스 로사, 개발자 옹호자, 카우치베이스

데니스 로사는 독일 뮌헨에 거주하고 있는 카우치베이스의 개발자 옹호자입니다. 그는 소프트웨어 엔지니어로서 탄탄한 경력을 쌓았으며 Java, Python, Scala, Javascript를 유창하게 구사합니다. Denis는 검색, 빅 데이터, AI, 마이크로서비스 및 개발자가 아름답고 빠르고 안정적이며 확장 가능한 앱을 만드는 데 도움이 되는 모든 것에 대해 글을 쓰는 것을 좋아합니다.

댓글 하나

댓글 남기기

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

구축 시작

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

카펠라 무료 사용

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

연락하기

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