세션

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

세션 개요

이 페이지에서는 클라이언트 라이브러리를 만들거나, REST 또는 RPC API를 사용하거나, Google 클라이언트 라이브러리를 사용할 때의 세션 권장사항을 포함하여 Spanner의 고급 세션 개념을 설명합니다.

세션은 Spanner 데이터베이스 서비스와의 통신 채널을 나타냅니다. 세션은 Spanner 데이터베이스에서 데이터를 읽거나, 쓰거나, 수정하는 트랜잭션을 수행하는 데 사용됩니다. 각 세션은 단일 데이터베이스에 적용합니다.

세션은 한 번에 트랜잭션 한 개만 실행할 수 있습니다. 독립형 읽기, 쓰기, 쿼리는 트랜잭션을 내부적으로 사용하고 하나의 트랜잭션 제한을 위한 카운트를 수행합니다.

세션 캐시 성능 이점

세션을 만드는 데는 많은 리소스가 사용됩니다. 데이터베이스 작업이 수행될 때마다 성능 비용을 방지하기 위해 클라이언트는 사용 준비가 완료된 사용 가능한 세션 풀인 세션 캐시를 유지해야 합니다. 캐시는 기존 세션을 저장하고 요청 시 적합한 유형의 세션을 반환할 뿐만 아니라 미사용 세션을 정리해야 합니다. 세션 캐시를 구현하는 방법의 예시를 보려면 Go 클라이언트 라이브러리 또는 자바 클라이언트 라이브러리와 같은 Spanner 클라이언트 라이브러리 중 하나의 소스 코드를 참조하세요.

세션은 오래 지속되도록 계획되므로, 세션이 데이터베이스 작업에 사용된 후에는 클라이언트가 세션을 재사용할 수 있도록 캐시에 반환해야 합니다.

Google 클라이언트 라이브러리 사용 시 권장사항

다음은 Spanner에 Google 클라이언트 라이브러리를 사용할 때의 권장사항을 설명합니다.

세션 수 구성

일반적으로 클라이언트 라이브러리에 사용되는 기본 세션 수를 수정하지 않는 것이 좋습니다.

특별한 워크로드의 경우에는 예상되는 동시 트랜잭션 수에 하한 값을 설정하고 초기 테스트 숫자에 상한 값(예: 100)을 설정하는 것이 좋습니다. 상한이 적합하지 않으면 수를 올립니다. 활성 세션 수를 늘리면 Spanner 데이터베이스 서비스에 추가 리소스가 사용되므로, 사용되지 않는 세션을 삭제하지 못할 경우 성능이 저하될 수 있습니다. 또한 gRPC 채널별 세션 수는 100개를 초과하지 않는 것이 좋습니다.

쓰기 세션 비율 관리

대부분의 클라이언트 라이브러리의 경우, Spanner는 읽기-쓰기 트랜잭션을 위해 세션의 일부를 예약하는데, 이를 쓰기 세션 비율이라고 합니다. 앱이 쓰기 세션을 모두 사용하면 Spanner는 읽기 전용 트랜잭션에도 읽기-쓰기 세션을 사용합니다. 읽기-쓰기 세션에는 spanner.databases.beginOrRollbackReadWriteTransaction이 필요합니다. 사용자가 spanner.databaseReader IAM 역할에 포함되었으면 호출이 실패하고 Spanner는 다음 오류 메시지를 반환합니다.

generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction

쓰기 세션 비율을 유지하는 클라이언트 라이브러리의 경우, 쓰기 세션 비율을 설정할 수 있습니다.

C++

모든 C++ 세션은 동일합니다. 읽기 또는 읽기-쓰기 전용 세션이 없습니다.

C#

C#의 기본 쓰기 세션 비율은 0.2입니다. SessionPoolOptions의 WriteSessionsFraction 필드를 사용하여 이 비율을 변경할 수 있습니다.

Go

Go의 기본 쓰기 세션 비율은 0.2입니다. SessionPoolConfig의 WriteSessions 필드를 사용하여 이 비율을 변경할 수 있습니다.

자바

모든 자바 세션은 동일합니다. 읽기 또는 읽기-쓰기 전용 세션이 없습니다.

Node.js

Node.js의 기본 쓰기 세션 비율은 0입니다. 이 비율은 writes 필드를 사용하여 변경할 수 있습니다.

PHP

모든 PHP 세션은 동일합니다. 읽기 또는 읽기-쓰기 전용 세션이 없습니다.

Python

Python은 읽기 및 읽기-쓰기 세션 관리에 사용할 수 있는 네 가지 세션 풀 유형을 지원합니다.

Ruby

Ruby의 기본 쓰기 세션 비율은 0.3입니다. 이 비율은 client initialize 메서드를 사용하여 변경할 수 있습니다.

클라이언트 라이브러리를 만들거나 REST/RPC를 사용할 때의 권장사항

다음은 Spanner의 클라이언트 라이브러리에서 세션을 구현하거나 REST 또는 RPC API에서 세션을 사용할 때의 권장사항입니다.

이 권장사항은 클라이언트 라이브러리를 개발하거나 REST/RPC API를 사용하는 경우에만 적용됩니다. Cloud Spanner용 Google 클라이언트 라이브러리 중 하나를 사용하는 경우 Google 클라이언트 라이브러리 사용 시 권장사항을 참조하세요.

세션 캐시 생성 및 크기 조정

클라이언트 프로세스에 대한 세션 캐시의 최적 크기를 결정하려면 하한을 예상되는 동시 실행 트랜잭션 수로 설정하고 상한을 초기 테스트 숫자(예: 100)로 설정합니다. 상한이 적합하지 않으면 수를 올립니다. 활성 세션 수를 늘리면 Spanner 데이터베이스 서비스에 추가 리소스가 사용되므로, 사용되지 않는 세션을 삭제하지 못할 경우 성능이 저하될 수 있습니다. RPC API를 사용하는 사용자의 경우 gRPC 채널별 세션이 100개를 초과하지 않는 것이 좋습니다.

삭제된 세션 처리

세션을 삭제하는 방법에는 세 가지가 있습니다.

  • 클라이언트가 세션을 삭제할 수 있습니다.
  • Spanner 데이터베이스 서비스는 1시간 넘게 유휴 상태인 세션을 삭제할 수 있습니다.
  • 세션이 28일보다 오래된 경우 Spanner 데이터베이스 서비스가 세션을 삭제할 수 있습니다.

삭제된 세션을 사용하려고 하면 NOT_FOUND 오류가 발생합니다. 이 오류가 발생하면 새 세션을 만들어 사용하고, 새 세션을 캐시에 추가하고, 캐시에서 삭제된 세션을 제거합니다.

유휴 세션 유지

Spanner 데이터베이스 서비스는 미사용 세션을 중단할 권한을 갖습니다. 데이터베이스 사용이 단기간에 크게 늘어날 것으로 예상되는 경우와 같이 유휴 세션을 계속 유지해야 하는 이유가 분명한 경우에는 세션이 중단되지 않도록 할 수 있습니다. 세션을 유지하기 위해 SQL 쿼리 SELECT 1 실행과 같이 리소스를 많이 사용하지 않는 작업을 수행합니다. 단기적으로 필요하지 않은 유휴 세션이 있는 경우, Spanner가 이 세션을 중단하도록 한 후 다음에 세션이 필요할 때 세션을 새로 만듭니다.

세션을 계속 유지해야 하는 상황 중 하나로, 정기적으로 급증하는 데이터베이스 사용을 처리하는 경우가 있습니다. 매일 오전 9시부터 오후 6시까지 데이터베이스 사용량이 과중하게 발생하는 경우, 일부 유휴 세션이 최대 사용량 기간 동안에 필요할 수 있으므로 일부 유휴 세션을 이 기간 중에 유지해야 합니다. 오후 6시 이후에는 Spanner가 유휴 세션을 중단하도록 할 수 있습니다. 매일 오전 9시 이전에 예상되는 수요에 맞게 새 세션을 여러 개 만들 수 있습니다.

또 다른 상황은 Spanner를 사용하지만 그 과정에서 연결 오버헤드를 방지해야 하는 경우입니다. 연결 오버헤드를 방지하기 위해 일련의 세션을 유지할 수 있습니다.

클라이언트 라이브러리 사용자로부터 세션 세부정보 숨기기

클라이언트 라이브러리를 만드는 경우, 세션을 클라이언트 라이브러리 소비자에게 노출시키지 마세요. 복잡하지 않고 세션을 만들고 유지하는 클라이언트가 데이터베이스를 호출할 수 있도록 합니다. 클라이언트 라이브러리 소비자로부터 세션 세부정보를 숨기는 클라이언트 라이브러리의 예에 대해서는 자바용 Spanner 클라이언트 라이브러리를 참조하세요.

Idempotent가 아닌 쓰기 트랜잭션 오류 처리

재생 보호 기능이 없는 쓰기 트랜잭션은 두 번 이상 변형을 적용할 수 있습니다. 변형이 idempotent가 아닌 경우 변형이 두 번 이상 적용되면 오류가 발생할 수 있습니다. 예를 들어 쓰기 시도 전에 행이 존재하지 않았더라도 ALREADY_EXISTS 오류가 발생하면서 삽입이 실패할 수 있습니다. 백엔드 서버가 변형을 커밋했지만 이를 클라이언트에 알릴 수 없는 경우에 이러한 상황이 발생할 수 있습니다. 이런 경우 변형이 재시도되어 ALREADY_EXISTS 오류가 발생할 수 있습니다.

자체 클라이언트 라이브러리를 구현하거나 REST API를 사용하는 경우 이 상황을 해결할 수 있는 방법은 다음과 같습니다.

  • Idempotent가 되도록 쓰기를 구조화합니다.
  • 재생 보호 기능이 있는 쓰기를 사용합니다.
  • 'upsert' 논리를 수행하는 메서드를 구현합니다. 즉, 새 항목인 경우에는 insert이고 기존 항목인 경우에는 update입니다.
  • 클라이언트를 대신하여 오류를 처리합니다.

안정적 연결 유지

최상의 성능을 위해서는 세션을 호스팅하는 데 사용하는 연결이 안정적이어야 합니다. 세션을 호스팅하는 연결이 변경되면 Spanner는 세션의 활성 트랜잭션을 취소할 수 있으며 Spanner가 세션 메타데이터를 업데이트하는 동안 데이터베이스에 약간의 추가 부하가 발생합니다. 소수의 연결이 산발적으로 변경되는 것은 무방하지만 동시에 다수의 연결이 변경될 수 있는 상황은 피해야 합니다. 클라이언트와 Spanner 사이에서 프록시를 사용하는 경우, 각 세션의 연결 안정성을 유지해야 합니다.

활성 세션 모니터링

명령줄, REST API 또는 RPC API에서 ListSessions 명령어를 사용하여 데이터베이스의 활성 세션을 모니터링할 수 있습니다. ListSessions는 지정된 데이터베이스의 활성 세션을 표시합니다. 이 명령어는 세션 유출의 원인을 찾아야 하는 경우에 유용합니다. 세션 유출은 세션이 생성되지만 재사용을 위해 세션 캐시로 반환되지 않는 문제입니다.

ListSessions를 사용하면 세션이 생성된 시기와 세션이 마지막으로 사용된 시기를 포함하여 활성 세션에 대한 메타데이터를 확인할 수 있습니다. 이 데이터를 분석하면 세션 문제를 올바르게 해결할 수 있습니다. 대부분의 활성 세션에 최근 approximate_last_use_time이 없으면 애플리케이션에서 세션이 제대로 재사용되지 않는 것일 수 있습니다. approximate_last_use_time 필드에 대한 자세한 내용은 RPC API 참조를 확인하세요.

ListSessions 사용에 대한 자세한 내용은 REST API 참조, RPC API 참조 또는 gcloud 명령줄 도구 참조를 확인하세요.