쓰기
이 페이지에서는 Bigtable에 보낼 수 있는 쓰기 요청 유형을 나열하고 각 유형을 사용해야 하는 경우와 사용하지 말아야 하는 경우를 설명합니다. 쓰기 시 셀의 데이터 집계에 대한 자세한 내용은 쓰기 시간에 값 집계를 참조하세요.
Bigtable Data API 및 클라이언트 라이브러리를 사용하면 데이터를 프로그래매틱 방식으로 테이블에 쓸 수 있습니다. Bigtable은 각 쓰기마다 응답 또는 확인을 반환합니다.
각 클라이언트 라이브러리에서는 다음 유형의 쓰기 요청을 보낼 수 있습니다.
- 간단한 쓰기
- 증분 및 추가
- 조건부 쓰기
- 일괄 쓰기
Bigtable 클라이언트 라이브러리는 간단한 쓰기와 일괄 쓰기의 스마트 재시도 기능을 기본 제공합니다. 즉, 쓰기를 일시적으로 사용할 수 없는 경우라도 원활하게 처리합니다. 예를 들어 애플리케이션에서 데이터 쓰기를 시도하는 중에 일시적인 중단이나 네트워크 문제가 발생하면 쓰기가 커밋되거나 요청 기한에 도달할 때까지 자동으로 재시도됩니다. 이러한 탄력성은 단일 클러스터 라우팅 또는 멀티 클러스터 라우팅을 사용하는 단일 클러스터 인스턴스와 복제된 인스턴스 모두에서 작동합니다.
일괄 및 스트리밍 쓰기 작업에 Bigtable Beam 커넥터를 사용할 수 있습니다. 자세한 내용은 일괄 쓰기를 참조하세요.
쓰기 요청에 적용되는 한도는 할당량 및 한도를 참조하세요.
이 페이지에 설명된 쓰기 요청의 Cloud Bigtable 클라이언트 라이브러리 예시는 쓰기 예시를 참조하세요.
쓰기 유형 및 사용 시기
각 쓰기 요청에는 다음과 같은 기본 구성요소가 포함됩니다.
- 쓰려는 테이블의 이름
- Bigtable에 트래픽 라우팅 방법을 알려주는 앱 프로필 ID
- 변형 하나 이상. 변형은 다음 요소로 구성됩니다.
- column family 이름
- column qualifier
- 타임스탬프
- 테이블에 쓰는 값
변형 타임스탬프에는 현재 날짜와 시간의 기본값이 포함되며, 유닉스 시간(1970년 1월 1일 00:00:00 UTC) 이후 경과된 시간으로 측정됩니다.
Bigtable에 보내는 타임스탬프는 최대 밀리초 정밀도의 마이크로초 값이어야 합니다. 3023483279876543
과 같은 마이크로초 정밀도의 타임스탬프는 거부됩니다. 이 예시에서 허용되는 타임스탬프 값은 3023483279876000
입니다.
단일 쓰기 요청의 모든 변형은 재정의하지 않는 한 동일한 타임스탬프를 갖습니다. 쓰기 요청에서 모든 변형의 타임스탬프를 서로 같거나 다르게 설정할 수 있습니다.
간단한 쓰기
테이블 이름, 사용할 앱 프로필의 ID, row key, 행에 대한 변형(최대 100,000개)이 포함된 MutateRow
요청을 사용하여 단일 행을 Bigtable에 쓸 수 있습니다. 단일 행 쓰기는 원자적으로 수행됩니다. 단일 행에 여러 변형을 생성할 때 이 쓰기 유형을 사용합니다.
간단한 쓰기 요청을 보내는 방법을 보여주는 코드 샘플은 간단한 쓰기 수행을 참조하세요.
간단한 쓰기를 사용하지 말아야 하는 경우
다음 사용 사례에서는 간단한 쓰기가 효과적인 데이터 쓰기 방법이 아닙니다.
row key가 연속으로 있는 데이터를 일괄로 쓰는 경우. 이 경우 한 번의 백엔드 호출로 일괄 처리를 연속 수행할 수 있으므로 간단한 쓰기를 연속으로 사용하는 대신 일괄 쓰기를 사용해야 합니다.
높은 처리량(초당 행 수 또는 초당 바이트 수)이 필요하지만 낮은 지연 시간은 필요하지 않은 경우. 일괄 쓰기 속도가 더 빠릅니다.
증분 및 추가
값을 늘리거나 늘리려면 쓰기 시간에 값을 업데이트할 수 있는 집계를 사용하는 것이 가장 좋습니다. 집계는 추가 작업을 지원하지 않습니다. 자세한 내용은 쓰기 시간에 값 집계를 참조하세요.
기존 값에 데이터를 추가하거나 기존 숫자 값을 늘려야 하는데 집계를 사용할 수 없는 경우 ReadModifyWriteRow
요청을 보낼 수 있습니다. 이 요청에는 테이블 이름, 사용해야 하는 앱 프로필의 ID, row key, 데이터를 쓸 때 사용할 규칙 집합이 포함됩니다. 각 규칙에는 column family 이름, column qualifier, 추가 값 또는 증분 값이 포함됩니다.
규칙은 순서대로 적용됩니다. 예를 들어 요청에 열 값을 2만큼 증분하는 요청이 포함되어 있고 동일한 요청의 후반 규칙에서 같은 열을 1만큼 증분한다면 이 단일 원자 쓰기에서는 열이 3만큼 증분됩니다. 후반 규칙이 앞부분 규칙을 덮어쓰지 않습니다.
64비트 big-endian 부호 있는 정수로 인코딩된 경우에만 값을 증분할 수 있습니다. Bigtable에서는 비어 있거나 존재하지 않는 값의 증분을 값이 0인 것처럼 처리합니다. ReadModifyWriteRow
요청은 원자적인 특성을 갖습니다. 어떠한 이유로든 실패하면 재시도되지 않습니다.
셀에 값을 추가하는 방법을 보여주는 코드 샘플은 기존 값 증가를 참조하세요.
ReadModifyWriteRow
사용이 적합하지 않은 경우
다음 상황에서는 ReadModifyWriteRow
요청을 보내지 마세요.
사용 사례는 집계를 사용하여 처리할 수 있습니다.
멀티 클러스터 라우팅을 적용하는 앱 프로필을 사용하는 경우
단일 클러스터 앱 프로필을 여러 개 사용하고 있고 인스턴스의 다른 클러스터에서 같은 행과 열에 기록된 데이터와 충돌할 수 있는 쓰기를 보내는 경우. 단일 클러스터 라우팅 사용 시에는 쓰기 요청이 단일 클러스터로 전송된 후에 복제됩니다.
클라이언트 라이브러리에서 제공하는 스마트 재시도 기능을 사용하는 경우. 증분 및 추가는 다시 시도할 수 없습니다.
대용량 데이터 쓰기를 신속하게 완료해야 하는 경우. 행을 읽은 후 수정하는 요청은 간단한 쓰기 요청보다 느립니다. 따라서 이러한 쓰기 유형은 종종 대량 쓰기 작업에 적합하지 않습니다.
예를 들어 페이지 조회수와 같이 수백만 개를 계수하려면 집계를 사용하여 쓰기 시간에 개수를 업데이트해야 합니다. 또한 값을 증분하지 않고 각 뷰를 간단한 쓰기로 기록한 후 Dataflow 작업을 사용하여 데이터를 집계할 수 있습니다.
조건부 쓰기
행의 조건을 확인한 후 결과에 따라 해당 행에 데이터를 쓰려면 CheckAndMutateRow
요청을 제출합니다. 이 유형의 요청에는 row key와 행 필터가 포함됩니다. 행 필터는 기존 데이터 값을 확인하는 데 사용되는 규칙 집합입니다. 그런 다음 필터로 확인된 특정 조건이 충족될 때에만 행의 특정 열에 변형이 커밋됩니다. 이러한 확인 후 쓰기 프로세스는 단일 원자 작업으로 완료됩니다.
필터 요청에는 다음 유형의 변형 중 하나 또는 둘 모두가 포함되어야 합니다.
- 필터가 값을 반환하는 경우에 적용할 변형 또는 참 변형
- 필터가 아무것도 생성하지 않는 경우에 적용할 거짓 변형
한 번 쓰기로 각 유형의 변형(참과 거짓)을 최대 100,000개까지 제공할 수 있으며 최소한 한 개 이상을 보내야 합니다. 모든 변형이 완료되면 Bigtable에서 응답을 보냅니다.
조건부 쓰기를 보내는 방법을 보여주는 코드 샘플은 조건부 값 작성을 참조하세요.
조건부 쓰기를 사용하지 말아야 하는 경우
다음 사용 사례에서는 조건부 쓰기를 사용할 수 없습니다.
멀티 클러스터 라우팅을 적용하는 앱 프로필을 사용하는 경우
단일 클러스터 앱 프로필을 여러 개 사용하고 있고 인스턴스의 다른 클러스터에서 같은 행과 열에 기록된 데이터와 충돌할 수 있는 쓰기를 보내는 경우. 단일 클러스터 라우팅 사용 시에는 쓰기 요청이 단일 클러스터로 전송된 후에 복제됩니다.
대용량 데이터 쓰기를 신속하게 완료해야 하는 경우.
ReadModifyWriteRow
와 마찬가지로 조건부 쓰기 요청은 행을 수정하기 전에 행을 읽어야 하므로CheckAndModifyRow
요청은 간단한 쓰기 요청보다 느립니다. 따라서 이러한 쓰기 유형은 종종 대량 쓰기 작업에 적합하지 않습니다.
일괄 쓰기
MutateRows
요청을 사용하면 호출 한 번으로 행을 두 개 이상 쓸 수 있습니다. MutateRows
요청에는 각각 원자적으로 적용되는 항목이 최대 100,000개까지 포함됩니다. 각 항목은 row key와 행에 적용할 변형 한 개 이상으로 구성됩니다. 일괄 쓰기 요청에는 모든 항목에 걸쳐 변형이 최대 100,000개까지 포함될 수 있습니다. 예를 들어 일괄 쓰기에는 다음 순열 중 하나가 포함될 수 있습니다.
- 항목마다 변형이 1개 있는 항목 100,000개
- 변형이 100,000개 있는 항목 1개
- 변형이 각각 100개 있는 항목 1,000개
MutateRows
요청의 각 항목은 원자적 특성을 갖지만 전체 요청은 그렇지 않습니다. 필요한 경우 Bigtable은 모든 쓰기가 성공하거나 요청 기한에 도달할 때까지 일괄 처리에서 성공하지 못한 항목을 재시도합니다. 그런 다음 일괄 작업의 각 쓰기를 식별하는 응답과 쓰기 성공 여부를 반환합니다.
일괄 쓰기를 보내는 방법을 보여주는 코드 샘플은 일괄 쓰기 수행을 참조하세요.
일괄 쓰기를 사용하지 말아야 하는 경우
서로 가깝지 않은 행에 일괄 데이터를 쓰는 경우. Bigtable은 row key를 기준으로 데이터를 사전순으로 저장하며 바이너리는 알파벳순에 해당됩니다. 이로 인해 한 요청의 row key가 서로 비슷하지 않으면 Bigtable은 이들을 동시에 처리하지 않고 순차적으로 처리합니다. 따라서 처리량은 향상되지만 지연 시간이 길어집니다. 높은 지연 시간을 방지하려면 row key가 비슷하고 Bigtable이 서로 가까이 있는 행을 쓰게 될 때
MutateRows
를 사용합니다. 서로 가깝지 않은 행에는MutateRow
또는 간단한 쓰기를 사용합니다.같은 행에 변형을 여러 개 요청하는 경우. 간단한 쓰기 요청 한 번으로 모든 변형을 수행하면 성능이 향상됩니다. 간단한 쓰기에서는 모든 변경사항이 단일 원자 동작으로 커밋되지만 일괄 쓰기에서는 같은 행에 변형을 직렬화해야 하므로 지연 시간이 발생하기 때문입니다.
일괄 쓰기 흐름 제어
다음 중 하나를 사용하여 일괄 쓰기를 전송하는 경우 코드에서 일괄 쓰기 흐름 제어를 사용 설정할 수 있습니다.
- Bigtable Beam 커넥터(
BigtableIO
) - 자바용 Bigtable 클라이언트 라이브러리
- Bigtable HBase Beam 커넥터(
CloudBigtableIO
) - 자바용 Bigtable HBase 클라이언트
Dataflow 작업에 일괄 쓰기 흐름 제어가 사용 설정되어 있으면 Bigtable에서 자동으로 다음을 수행합니다.
- Bigtable 클러스터 과부하가 발생하지 않도록 트래픽 비율 제한
- 필요한 경우 더 많은 노드가 클러스터에 자동으로 추가되도록 Bigtable 자동 확장(사용 설정된 경우)을 트리거하기에 충분한 부하가 클러스터에 있는지 확인
이처럼 결합된 작업이 클러스터 과부하 및 작업 실패를 방지하므로 일괄 쓰기를 실행할 것으로 예상되는 경우 클러스터를 수동으로 확장할 필요가 없습니다. 흐름 제어가 사용 설정되면 클러스터 확장이 이전 작업이 아닌 Dataflow 작업 중에 이루어지므로 작업을 완료하는 데 클러스터를 수동으로 확장할 때보다 시간이 오래 걸릴 수 있습니다.
단일 클러스터 라우팅용으로 구성된 앱 프로필을 사용해야 합니다. 대상 클러스터의 Bigtable 자동 확장 사용 설정은 요구사항이 아니지만 자동 확장을 사용하면 일괄 쓰기 흐름 제어를 최대한 활용할 수 있습니다. Dataflow 자동 확장은 다른 작업과 마찬가지로 사용할 수 있습니다.
Bigtable 자동 확장에 대한 자세한 내용은 자동 확장을 참조하세요. 앱 프로필 라우팅 정책을 이해하려면 앱 프로필 개요를 참조하세요.
Bigtable HBase Beam 커넥터를 사용하여 일괄 쓰기 흐름 제어를 사용 설정하는 방법을 보여주는 코드 샘플은 Bigtable에 쓰기를 참조하세요.
승인된 뷰에 데이터 쓰기
승인된 뷰에 데이터를 쓰려면 다음 중 하나를 사용해야 합니다.
- gcloud CLI
- Java용 Bigtable 클라이언트
다른 Bigtable 클라이언트 라이브러리는 아직 승인된 뷰 액세스를 지원하지 않습니다.
승인된 뷰에 데이터를 쓸 때는 테이블 ID 외에 승인된 뷰 ID를 제공합니다.
승인된 뷰에 대한 모든 쓰기는 기본 테이블에 직접 적용됩니다.
승인된 뷰 정의 제한사항
승인된 뷰에서 데이터를 쓸 수 있는 행 또는 열은 승인된 뷰 정의에 의해 제한됩니다. 즉, 승인된 뷰에 지정된 기준과 동일한 기준을 충족하는 행과 열에만 쓸 수 있습니다.
예를 들어 승인된 뷰가 row key 프리픽스 examplepetstore1
로 정의된 경우 examplepetstore2
의 row key를 사용하여 데이터를 쓸 수 없습니다. row key 값의 시작에는 전체 문자열 examplepetstore1
이 포함되어야 합니다.
마찬가지로 승인된 뷰가 column qualifier 프리픽스 order-phone
으로 정의된 경우 column qualifier order-phone123
을 사용하여 데이터를 쓸 수 있지만 column qualifier order-tablet
은 사용할 수 없습니다.
또한 쓰기 요청은 조건부 쓰기 요청의 값을 확인할 때와 같이 승인된 뷰 외부에 있는 데이터를 참조할 수 없습니다.
승인된 뷰 외부에서 데이터를 쓰거나 참조하는 요청의 경우 PERMISSION_DENIED
오류 메시지가 반환됩니다.
복제
복제된 인스턴스의 클러스터 하나에서 쓰기 작업을 수신하면 해당 쓰기 작업이 인스턴스의 다른 클러스터로 즉시 복제됩니다.
원자성
복제된 인스턴스로 전송하는 각 MutateRows
요청은 요청이 라우팅되는 클러스터에서 단일 원자 작업으로 커밋됩니다. 쓰기 작업이 인스턴스의 다른 클러스터에 복제되면 해당 클러스터에도 쓰기 작업이 원자 작업으로 수신됩니다. 클러스터에는 부분 변형이 수신되지 않습니다. 변형은 수정하는 모든 셀에 대해 원자적으로 성공하거나 실패합니다.
일관성
쓴 데이터를 읽을 수 있을 때까지 걸리는 시간은 인스턴스의 클러스터 수 및 앱 프로필에서 사용하는 라우팅 유형을 비롯한 여러 가지 요소에 따라 달라집니다.
단일 클러스터 인스턴스에서는 데이터를 즉시 읽을 수 있지만, 인스턴스에 클러스터가 두 개 이상 있으면 복제를 사용해야 하므로 Bigtable은 eventual consistency를 가집니다. 요청을 같은 클러스터로 라우팅하면 읽기-쓰기 일관성을 얻을 수 있습니다.
쓰기 요청을 보낸 후 일관성 토큰을 만들어 사용하고 StandardReadRemoteWrites
모드에서 CheckConsistency
를 호출할 수 있습니다. 토큰은 복제 일관성을 확인합니다. 일반적으로 쓰기 일괄이 전송된 후 또는 특정 시간이 지난 후(예: 1시간)에 일관성 토큰을 만듭니다. 그런 다음 다른 프로세스에서 사용하도록 토큰을 전달할 수 있습니다. 예를 들면 읽기를 요청하는 모듈은 이러한 토큰을 사용하여 읽기 전에 모든 데이터가 복제되었는지 확인합니다.
토큰을 만든 후 바로 토큰을 사용할 경우 토큰을 처음 사용 시 일관성을 확인하는 데 몇 분 정도 걸릴 수 있습니다. 이러한 지연은 더 이상 수신 데이터가 없는지 확인하기 위해 각 클러스터가 다른 모든 클러스터를 검사하기 때문입니다. 최초 사용 후 또는 몇 분 정도 기다린 후 토큰을 처음으로 사용하면 토큰을 사용할 때마다 즉시 성공합니다.
충돌 해결 방법
Bigtable 테이블의 각 셀 값은 4-튜플(row key, column family, column qualifier, timestamp)로 고유하게 식별됩니다. 이러한 식별자에 대한 자세한 내용은 Bigtable 스토리지 모델을 참조하세요. 드물지만 정확히 4-튜플이 포함된 쓰기 2회가 서로 다른 두 클러스터로 전송되는 경우 Bigtable은 서버측 시간에 기반한 내부 마지막 쓰기 성공 알고리즘을 사용하여 충돌을 자동으로 해결합니다. Bigtable '마지막 쓰기 성공' 구현은 확정적이며 복제가 따라잡으면 모든 클러스터가 4-튜플에 대해 동일한 값을 갖습니다.