DynamoDB์—์„œ Spanner๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Amazon DynamoDB์—์„œ Spanner๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ NoSQL ์‹œ์Šคํ…œ์—์„œ Spanner๋กœ ์ด์ „ํ•˜๊ณ ์ž ํ•˜๋Š” ์•ฑ ์†Œ์œ ์ž๋ฅผ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Spanner๋Š” ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋Š” ํ™•์žฅ์„ฑ์ด ๋›ฐ์–ด๋‚œ ์™„์ „ ๊ด€๊ณ„ํ˜• ๋‚ด๊ฒฐํ•จ์„ฑ SQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. ์œ ํ˜•๊ณผ ๋ ˆ์ด์•„์›ƒ ์ธก๋ฉด์—์„œ Amazon DynamoDB ํ…Œ์ด๋ธ”์„ ๊พธ์ค€ํžˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ Spanner์— ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Amazon DynamoDB ํ…Œ์ด๋ธ”์— ์ž„์˜ ๋ฐ์ดํ„ฐ ์œ ํ˜•๊ณผ ๊ฐ’์ด ํฌํ•จ๋œ ๊ฒฝ์šฐ์—๋Š” Datastore ๋˜๋Š” Firestore์™€ ๊ฐ™์€ ๋‹ค๋ฅธ NoSQL ์„œ๋น„์Šค๋กœ ์ด์ „ํ•˜๋Š” ๊ฒƒ์ด ๋” ๊ฐ„๋‹จํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ, ๋ฐ์ดํ„ฐ ์œ ํ˜•, NoSQL์˜ ๊ธฐ๋ณธ ์ •๋ณด, ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์— ์ต์ˆ™ํ•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์€ ์‚ฌ์ „ ์ •์˜๋œ ์ž‘์—…์„ ์‹คํ–‰ํ•˜์—ฌ ์ด์ „ ์ž‘์—… ์˜ˆ์‹œ๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํŠœํ† ๋ฆฌ์–ผ ์ง„ํ–‰ ํ›„์—๋Š” ์ œ๊ณต๋œ ์ฝ”๋“œ ๋ฐ ๋‹จ๊ณ„๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ์— ๋งž์ถœ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์˜ ์•„ํ‚คํ…์ฒ˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์‚ฌ์šฉ๋œ ๊ตฌ์„ฑ์š”์†Œ๋ฅผ ๊ฐ„๋žตํ•˜๊ฒŒ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ตฌ์„ฑ์š”์†Œ์˜ ์•„ํ‚คํ…์ฒ˜ ๋‹ค์ด์–ด๊ทธ๋žจ

๋ชฉํ‘œ

  • Amazon DynamoDB์—์„œ Spanner๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค.
  • Spanner ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
  • NoSQL ์Šคํ‚ค๋งˆ๋ฅผ ๊ด€๊ณ„ํ˜• ์Šคํ‚ค๋งˆ์— ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.
  • Amazon DynamoDB๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ๋‚ด๋ณด๋ƒ…๋‹ˆ๋‹ค.
  • Amazon S3 ๋ฐ Cloud Storage ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.
  • Dataflow๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ Spanner์— ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.

๋น„์šฉ

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋น„์šฉ์ด ์ฒญ๊ตฌ๋  ์ˆ˜ ์žˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ Google Cloud๊ตฌ์„ฑ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Spanner ๋น„์šฉ์€ ์ธ์Šคํ„ด์Šค์˜ ์ปดํ“จํŒ… ์šฉ๋Ÿ‰๊ณผ ์›”๋ณ„ ๊ฒฐ์ œ ์ฃผ๊ธฐ ์ค‘์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์–‘์„ ๊ธฐ์ค€์œผ๋กœ ์ฒญ๊ตฌ๋ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค์˜ ์ตœ์†Œ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉฐ ๋๋‚  ๋•Œ ์‚ญ์ œ๋ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ์‹œ๋‚˜๋ฆฌ์˜ค์˜ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ๋Ÿ‰๊ณผ ์Šคํ† ๋ฆฌ์ง€ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถ”์ •ํ•œ ํ›„ Spanner ์ธ์Šคํ„ด์Šค ๋ฌธ์„œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ์ปดํ“จํŒ… ์šฉ๋Ÿ‰์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Google Cloud ๋ฆฌ์†Œ์Šค ์™ธ์—๋„ ๋‹ค์Œ Amazon Web Services(AWS) ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • AWS Lambda
  • Amazon S3
  • Amazon DynamoDB

์ด๋Ÿฌํ•œ ์„œ๋น„์Šค๋Š” ์ด์ „ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๋™์•ˆ์—๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ํŠœํ† ๋ฆฌ์–ผ์„ ๋งˆ์น˜๋ฉด ์•ˆ๋‚ด์— ๋”ฐ๋ผ ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ๋น„์šฉ ์ฒญ๊ตฌ๋ฅผ ๋ฐฉ์ง€ํ•˜์„ธ์š”. AWS ๊ฐ€๊ฒฉ ๊ณ„์‚ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„์šฉ์„ ์ถ”์‚ฐํ•˜์„ธ์š”.

ํ”„๋กœ์ ํŠธ ์‚ฌ์šฉ๋Ÿ‰์„ ๊ธฐ์ค€์œผ๋กœ ์˜ˆ์ƒ ๋น„์šฉ์„ ์‚ฐ์ถœํ•˜๋ ค๋ฉด ๊ฐ€๊ฒฉ ๊ณ„์‚ฐ๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

์‹œ์ž‘ํ•˜๊ธฐ ์ „์—

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Spanner, Pub/Sub, Compute Engine, and Dataflow APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Spanner, Pub/Sub, Compute Engine, and Dataflow APIs.

    Enable the APIs

  8. ์ด ๋ฌธ์„œ์— ์„ค๋ช…๋œ ํƒœ์Šคํฌ๋ฅผ ์™„๋ฃŒํ–ˆ์œผ๋ฉด ๋งŒ๋“  ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜์—ฌ ์ฒญ๊ตฌ๊ฐ€ ๊ณ„์†๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์‚ญ์ œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

    ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์ค€๋น„

    ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Cloud Shell์—์„œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. Cloud Shell์€ Google Cloud์˜ ๋ช…๋ น์ค„์— ๋Œ€ํ•œ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์ œ๊ณตํ•˜๊ณ  Google Cloud CLI ๋ฐ Google Cloud ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๊ธฐํƒ€ ๋„๊ตฌ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. Cloud Shell์€ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐ ๋ช‡ ๋ถ„ ์ •๋„ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1. In the Google Cloud console, activate Cloud Shell.

      Activate Cloud Shell

      At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

    2. ๊ธฐ๋ณธ Compute Engine ์˜์—ญ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด us-central1-b์ž…๋‹ˆ๋‹ค. gcloud config set compute/zone us-central1-b
    3. ์ƒ˜ํ”Œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ GitHub ์ €์žฅ์†Œ๋ฅผ ํด๋ก ํ•ฉ๋‹ˆ๋‹ค. git clone https://github.com/GoogleCloudPlatform/dynamodb-spanner-migration.git
    4. ๋ณต์ œ๋œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. cd dynamodb-spanner-migration
    5. Python ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. pip3 install virtualenv virtualenv env
    6. ๊ฐ€์ƒ ํ™˜๊ฒฝ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. source env/bin/activate
    7. ํ•„์ˆ˜ Python ๋ชจ๋“ˆ์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. pip3 install -r requirements.txt

    AWS ์•ก์„ธ์Šค ๊ตฌ์„ฑ

    ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Amazon DynamoDB ํ…Œ์ด๋ธ”, Amazon S3 ๋ฒ„ํ‚ท ๋ฐ ๊ธฐํƒ€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฆฌ์†Œ์Šค์— ์•ก์„ธ์Šคํ•˜๋ ค๋ฉด ๋จผ์ € ํ•„์ˆ˜ AWS Identity and Access Management(IAM) ๊ถŒํ•œ์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ๋˜๋Š” ์ƒŒ๋“œ๋ฐ•์Šค AWS ๊ณ„์ •์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ™์€ ๊ณ„์ •์—์„œ ํ”„๋กœ๋•์…˜ ๋ฆฌ์†Œ์Šค์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    AWS Lambda๋ฅผ ์œ„ํ•œ AWS IAM ์—ญํ•  ๋งŒ๋“ค๊ธฐ

    ์ด ์„น์…˜์—์„œ๋Š” AWS Lambda๊ฐ€ ํŠœํ† ๋ฆฌ์–ผ์˜ ์ดํ›„ ๋‹จ๊ณ„์—์„œ ์‚ฌ์šฉํ•˜๋Š” AWS IAM ์—ญํ• ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    1. AWS ์ฝ˜์†”์—์„œ IAM ์„น์…˜์œผ๋กœ ์ด๋™ํ•˜์—ฌ Roles(์—ญํ• )๋ฅผ ํด๋ฆญํ•œ ๋‹ค์Œ Create role(์—ญํ•  ๋งŒ๋“ค๊ธฐ)์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    2. ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ํ•ญ๋ชฉ ์œ ํ˜•์—์„œ AWS ์„œ๋น„์Šค๊ฐ€ ์„ ํƒ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
    3. ์‚ฌ์šฉ ์‚ฌ๋ก€์—์„œ Lambda๋ฅผ ์„ ํƒํ•œ ํ›„ ๋‹ค์Œ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    4. ๊ถŒํ•œ ์ •์ฑ… ํ•„ํ„ฐ ์ƒ์ž์— AWSLambdaDynamoDBExecutionRole์„ ์ž…๋ ฅํ•˜๊ณ  Return์„ ๋ˆŒ๋Ÿฌ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.
    5. AWSLambdaDynamoDBExecutionRole ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•œ ํ›„ ๋‹ค์Œ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.
    6. Role name(์—ญํ•  ์ด๋ฆ„) ์ƒ์ž์— dynamodb-spanner-lambda-role์„ ์ž…๋ ฅํ•œ ๋‹ค์Œ Create role(์—ญํ•  ๋งŒ๋“ค๊ธฐ)์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    AWS IAM ์‚ฌ์šฉ์ž ๋งŒ๋“ค๊ธฐ

    ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ผ ์ด ํŠœํ† ๋ฆฌ์–ผ ์ „๋ฐ˜์—์„œ ์‚ฌ์šฉํ•  AWS ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ์•ก์„ธ์Šค ๊ถŒํ•œ์ด ์žˆ๋Š” AWS IAM ์‚ฌ์šฉ์ž๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    1. AWS ์ฝ˜์†”์˜ IAM ์„น์…˜์— ์žˆ๋Š” ์ƒํƒœ์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ํด๋ฆญํ•œ ํ›„ ์‚ฌ์šฉ์ž ์ถ”๊ฐ€๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.
    2. ์‚ฌ์šฉ์ž ์ด๋ฆ„ ์ƒ์ž์— dynamodb-spanner-migration์„ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
    3. ์•ก์„ธ์Šค ์œ ํ˜•์—์„œ ์•ก์„ธ์Šค ํ‚ค - ํ”„๋กœ๊ทธ๋ž˜๋งคํ‹ฑ ๋ฐฉ์‹์œผ๋กœ ์•ก์„ธ์Šค ์™ผ์ชฝ์— ์žˆ๋Š” ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

    4. ๋‹ค์Œ: ๊ถŒํ•œ์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    5. ๊ธฐ์กด ์ •์ฑ… ์ง์ ‘ ์—ฐ๊ฒฐ์„ ํด๋ฆญํ•˜๊ณ  ๊ฒ€์ƒ‰ ์ƒ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„ํ„ฐ๋งํ•œ ํ›„ ๋‹ค์Œ ์„ธ ๊ฐ€์ง€ ์ •์ฑ… ์˜†์— ์žˆ๋Š” ์ฒดํฌ๋ฐ•์Šค๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

      • AmazonDynamoDBFullAccess
      • AmazonS3FullAccess
      • AWSLambda_FullAccess
    6. ๋‹ค์Œ: ํƒœ๊ทธ ๋ฐ ๋‹ค์Œ: ๊ฒ€ํ† ๋ฅผ ํด๋ฆญํ•œ ํ›„ ์‚ฌ์šฉ์ž ๋งŒ๋“ค๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    7. ํ‘œ์‹œ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ๋ด…๋‹ˆ๋‹ค. ์ƒˆ๋กœ ์ƒ์„ฑ๋œ ์‚ฌ์šฉ์ž์˜ ์•ก์„ธ์Šค ํ‚ค ID ๋ฐ ๋น„๋ฐ€ ์•ก์„ธ์Šค ํ‚ค๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์„น์…˜์—์„œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ฐฝ์„ ์—ด์–ด๋†“์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•˜์„ธ์š”. ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด ๊ณ„์ •์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‚ฌ์šฉ ํ™˜๊ฒฝ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์ด ๋๋‚˜๋ฉด IAM ์‚ฌ์šฉ์ž๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    AWS ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ

    1. Cloud Shell์—์„œ AWS ๋ช…๋ น์ค„ ์ธํ„ฐํŽ˜์ด์Šค(CLI)๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.

      aws configure
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      AWS Access Key ID [None]: PASTE_YOUR_ACCESS_KEY_ID
      AWS Secret Access Key [None]: PASTE_YOUR_SECRET_ACCESS_KEY
      Default region name [None]: us-west-2
      Default output format [None]:
      
      • ๋งŒ๋“  AWS IAM ๊ณ„์ •์˜ ACCESS KEY ID๋ฐ SECRET ACCESS KEY๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.
      • ๊ธฐ๋ณธ ๋ฆฌ์ „ ์ด๋ฆ„ ํ•„๋“œ์— us-west-2๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํ•„๋“œ๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ๋‘ก๋‹ˆ๋‹ค.
    2. AWS IAM ์ฝ˜์†” ์ฐฝ์„ ๋‹ซ์Šต๋‹ˆ๋‹ค.

    ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์ดํ•ด

    ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” Amazon DynamoDB ๋ฐ Spanner์˜ ๋ฐ์ดํ„ฐ ์œ ํ˜•, ํ‚ค, ์ƒ‰์ธ ๊ฐ„ ์œ ์‚ฌ์ ๊ณผ ์ฐจ์ด์ ์„ ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

    ๋ฐ์ดํ„ฐ ์œ ํ˜•

    Spanner๋Š” GoogleSQL ๋ฐ์ดํ„ฐ ์œ ํ˜•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ํ‘œ์—์„œ๋Š” Amazon DynamoDB ๋ฐ์ดํ„ฐ ์œ ํ˜•์ด Spanner ๋ฐ์ดํ„ฐ ์œ ํ˜•์— ๋งคํ•‘๋˜๋Š” ๋ฐฉ์‹์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

    Amazon DynamoDB Spanner
    ์ˆซ์ž ์ •๋ฐ€๋„๋‚˜ ์‚ฌ์šฉ ์šฉ๋„์— ๋”ฐ๋ผ INT64, FLOAT64, TIMESTAMP, DATE์— ๋งคํ•‘๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ๋ฌธ์ž์—ด ๋ฌธ์ž์—ด
    Boolean BOOL
    Null ๋ช…์‹œ์ ์ธ ์œ ํ˜•์ด ์—†์Šต๋‹ˆ๋‹ค. ์—ด์— null ๊ฐ’์ด ํฌํ•จ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ”์ดํŠธ
    ์„ธํŠธ ๋ฐฐ์—ด
    ์ง€๋„ ๋ฐ ๋ชฉ๋ก ๊ตฌ์กฐ๊ฐ€ ์ผ๊ด€๋˜๊ณ  ํ…Œ์ด๋ธ” DDL ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ์˜ ๊ตฌ์กฐ์ฒด์ž…๋‹ˆ๋‹ค.

    ๊ธฐ๋ณธ ํ‚ค

    Amazon DynamoDB ๊ธฐ๋ณธ ํ‚ค๋Š” ๊ณ ์œ ์„ฑ์„ ์„ค์ •ํ•˜๋ฉฐ ํ•ด์‹œ ํ‚ค์ด๊ฑฐ๋‚˜ ํ•ด์‹œ ํ‚ค์™€ ๋ฒ”์œ„ ํ‚ค์˜ ์กฐํ•ฉ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๊ธฐ๋ณธ ํ‚ค๊ฐ€ ํ•ด์‹œ ํ‚ค์ธ Amazon DynamoDB ํ…Œ์ด๋ธ”์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ•ด์‹œ ํ‚ค๋Š” Spanner ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธ ํ‚ค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ํ…Œ์ด๋ธ”์— ๊ด€ํ•œ ์„น์…˜์—์„œ๋Š” Amazon DynamoDB ํ…Œ์ด๋ธ”์ด ํ•ด์‹œ ํ‚ค์™€ ๋ฒ”์œ„ ํ‚ค๋กœ ๊ตฌ์„ฑ๋œ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์„ ๋ชจ๋ธ๋งํ•ฉ๋‹ˆ๋‹ค.

    ๋ณด์กฐ ์ƒ‰์ธ

    Amazon DynamoDB์™€ Spanner ๋ชจ๋‘ ๊ธฐ๋ณธ ํ‚ค๊ฐ€ ์•„๋‹Œ ์†์„ฑ์—์„œ ์ƒ‰์ธ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ํ›„๋ฐ˜๋ถ€์—์„œ ๋‹ค๋ฃจ๋Š” Spanner ํ…Œ์ด๋ธ”์—์„œ ์ƒ‰์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก Amazon DynamoDB ํ…Œ์ด๋ธ”์˜ ๋ณด์กฐ ์ƒ‰์ธ์„ ๊ธฐ๋กํ•ด ๋‘์„ธ์š”.

    ์ƒ˜ํ”Œ ํ…Œ์ด๋ธ”

    ์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์‰ฝ๊ฒŒ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ์ƒ˜ํ”Œ ํ…Œ์ด๋ธ”์„ Amazon DynamoDB์—์„œ Spanner๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•ฉ๋‹ˆ๋‹ค.

    Amazon DynamoDB Spanner
    ํ‘œ ์ด๋ฆ„ Migration Migration
    ๊ธฐ๋ณธ ํ‚ค "Username" : String "Username" : STRING(1024)
    ํ‚ค ์œ ํ˜• ํ•ด์‹œ ํ•ด๋‹น ์—†์Œ
    ๊ธฐํƒ€ ํ•„๋“œ Zipcode: Number Subscribed: Boolean ReminderDate: String PointsEarned: Number Zipcode: INT64 Subscribed: BOOL ReminderDate: DATE PointsEarned: INT64

    Amazon DynamoDB ํ…Œ์ด๋ธ” ์ค€๋น„

    ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” Amazon DynamoDB ์†Œ์Šค ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค๊ณ  ๋ฐ์ดํ„ฐ๋กœ ์ฑ„์›๋‹ˆ๋‹ค.

    1. Cloud Shell์—์„œ ์ƒ˜ํ”Œ ํ…Œ์ด๋ธ” ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” Amazon DynamoDB ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      aws dynamodb create-table --table-name Migration \
          --attribute-definitions AttributeName=Username,AttributeType=S \
          --key-schema AttributeName=Username,KeyType=HASH \
          --provisioned-throughput ReadCapacityUnits=75,WriteCapacityUnits=75
      
    2. ํ…Œ์ด๋ธ” ์ƒํƒœ๊ฐ€ ACTIVE์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

      aws dynamodb describe-table --table-name Migration \
          --query 'Table.TableStatus'
      
    3. ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ๋กœ ํ…Œ์ด๋ธ”์„ ์ฑ„์›๋‹ˆ๋‹ค.

      python3 make-fake-data.py --table Migration --items 25000
      

    Spanner ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งŒ๋“ค๊ธฐ

    ๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ์ปดํ“จํŒ… ์šฉ๋Ÿ‰์ธ ์ฒ˜๋ฆฌ ๋‹จ์œ„ 100๊ฐœ๋กœ Spanner ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ์ปดํ“จํŒ… ์šฉ๋Ÿ‰์€ ์ด ํŠœํ† ๋ฆฌ์–ผ ๋ฒ”์œ„์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ์˜ ๊ฒฝ์šฐ Spanner ์ธ์Šคํ„ด์Šค ๋ฌธ์„œ๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถฉ์กฑํ•˜๋Š” ๋ฐ ์ ์ ˆํ•œ ์ปดํ“จํŒ… ์šฉ๋Ÿ‰์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

    ์ด ์˜ˆ์‹œ์—์„œ๋Š” ํ…Œ์ด๋ธ” ์Šคํ‚ค๋งˆ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋™์‹œ์— ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“  ํ›„์— ์Šคํ‚ค๋งˆ ์—…๋ฐ์ดํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1. ๊ธฐ๋ณธ Compute Engine ์˜์—ญ์„ ์„ค์ •ํ•œ ๋ฆฌ์ „๊ณผ ๋™์ผํ•œ ๋ฆฌ์ „์—์„œ Spanner ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด us-central1์ž…๋‹ˆ๋‹ค.

      gcloud beta spanner instances create spanner-migration \
          --config=regional-us-central1 --processing-units=100 \
          --description="Migration Demo"
      
    2. Spanner ์ธ์Šคํ„ด์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ƒ˜ํ”Œ ํ…Œ์ด๋ธ”๊ณผ ํ•จ๊ป˜ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      gcloud spanner databases create migrationdb \
          --instance=spanner-migration \
          --ddl "CREATE TABLE Migration ( \
                  Username STRING(1024) NOT NULL, \
                  PointsEarned INT64, \
                  ReminderDate DATE, \
                  Subscribed BOOL, \
                  Zipcode INT64, \
               ) PRIMARY KEY (Username)"
      

    ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ค€๋น„

    ๋‹ค์Œ ์„น์…˜์—์„œ๋Š” Amazon DynamoDB ์†Œ์Šค ํ…Œ์ด๋ธ”์„ ๋‚ด๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•๊ณผ ํ…Œ์ด๋ธ”์„ ๋‚ด๋ณด๋‚ด๋Š” ๋™์•ˆ ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์บก์ฒ˜ํ•˜๋„๋ก Pub/Sub ๋ณต์ œ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

    ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ Pub/Sub์— ์ŠคํŠธ๋ฆฌ๋ฐ

    AWS Lambda ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ Pub/Sub์— ์ŠคํŠธ๋ฆฌ๋ฐํ•ฉ๋‹ˆ๋‹ค.

    1. Cloud Shell์—์„œ ์†Œ์Šค ํ…Œ์ด๋ธ”์˜ Amazon DynamoDB ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

      aws dynamodb update-table --table-name Migration \
          --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
      
    2. ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ˆ˜์‹ ํ•˜๋„๋ก Pub/Sub ์ฃผ์ œ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

      gcloud pubsub topics create spanner-migration
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      Created topic [projects/your-project/topics/spanner-migration].
      
    3. IAM ์„œ๋น„์Šค ๊ณ„์ •์„ ๋งŒ๋“ค์–ด ํ…Œ์ด๋ธ” ์—…๋ฐ์ดํŠธ๋ฅผ Pub/Sub ์ฃผ์ œ๋กœ ํ‘ธ์‹œํ•ฉ๋‹ˆ๋‹ค.

      gcloud iam service-accounts create spanner-migration \
          --display-name="Spanner Migration"
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      Created service account [spanner-migration].
      
    4. ์„œ๋น„์Šค ๊ณ„์ •์ด Pub/Sub์— ๊ฒŒ์‹œํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์„ ๊ฐ–๋„๋ก IAM ์ •์ฑ… binding์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. GOOGLE_CLOUD_PROJECT๋ฅผ Google Cloud ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์œผ๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค.

      gcloud projects add-iam-policy-binding GOOGLE_CLOUD_PROJECT \
          --role roles/pubsub.publisher \
          --member serviceAccount:spanner-migration@GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      bindings:
      (...truncated...)
      - members:
        - serviceAccount:spanner-migration@solution-z.iam.gserviceaccount.com
        role: roles/pubsub.publisher
      
    5. ์„œ๋น„์Šค ๊ณ„์ •์˜ ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      gcloud iam service-accounts keys create credentials.json \
          --iam-account spanner-migration@GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      created key [5e559d9f6bd8293da31b472d85a233a3fd9b381c] of type [json] as [credentials.json] for [spanner-migration@your-project.iam.gserviceaccount.com]
      
    6. AWS Lambda ํ•จ์ˆ˜๋ฅผ ์ค€๋น„ํ•˜๊ณ  ํŒจํ‚ค์ง•ํ•˜์—ฌ Amazon DynamoDB ํ…Œ์ด๋ธ” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ Pub/Sub ์ฃผ์ œ๋กœ ํ‘ธ์‹œํ•ฉ๋‹ˆ๋‹ค.

      pip3 install --ignore-installed --target=lambda-deps google-cloud-pubsub
      cd lambda-deps; zip -r9 ../pubsub-lambda.zip *; cd -
      zip -g pubsub-lambda.zip ddbpubsub.py
    7. ์•ž์„œ ๋งŒ๋“  Lambda ์‹คํ–‰ ์—ญํ• ์˜ Amazon ๋ฆฌ์†Œ์Šค ์ด๋ฆ„(ARN)์„ ์บก์ฒ˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      LAMBDA_ROLE=$(aws iam list-roles \
          --query 'Roles[?RoleName==`dynamodb-spanner-lambda-role`].[Arn]' \
          --output text)
      
    8. pubsub-lambda.zip ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AWS Lambda ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      aws lambda create-function --function-name dynamodb-spanner-lambda \
          --runtime python3.9 --role ${LAMBDA_ROLE} \
          --handler ddbpubsub.lambda_handler --zip fileb://pubsub-lambda.zip \
          --environment Variables="{SVCACCT=$(base64 -w 0 credentials.json),PROJECT=GOOGLE_CLOUD_PROJECT,TOPIC=spanner-migration}"
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      {
          "FunctionName": "dynamodb-spanner-lambda",
          "LastModified": "2022-03-17T23:45:26.445+0000",
          "RevisionId": "e58e8408-cd3a-4155-a184-4efc0da80bfb",
          "MemorySize": 128,
      ... truncated output... "PackageType": "Zip", "Architectures": [ "x86_64" ] }

    9. Create a variable to capture the ARN of the Amazon DynamoDB stream for your table.

      STREAMARN=$(aws dynamodb describe-table \
          --table-name Migration \
          --query "Table.LatestStreamArn" \
          --output text)
      
    10. Lambda ํ•จ์ˆ˜๋ฅผ Amazon DynamoDB ํ…Œ์ด๋ธ”์— ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

      aws lambda create-event-source-mapping --event-source ${STREAMARN} \
          --function-name dynamodb-spanner-lambda --enabled \
          --starting-position TRIM_HORIZON
      
    11. ํ…Œ์ŠคํŠธ ์ค‘ ์‘๋‹ต์„ฑ์„ ์ตœ์ ํ™”ํ•˜๋ ค๋ฉด ํ•ญ๋ชฉ์„ ์ƒ์„ฑ, ์—…๋ฐ์ดํŠธ ๋˜๋Š” ์‚ญ์ œํ•  ๋•Œ๋งˆ๋‹ค ํ•จ์ˆ˜๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ์ด์ „ ๋ช…๋ น์–ด ๋์— --batch-size 1์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

      ๋‹ค์Œ๊ณผ ๋น„์Šทํ•œ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      {
          "UUID": "44e4c2bf-493a-4ba2-9859-cde0ae5c5e92",
          "StateTransitionReason": "User action",
          "LastModified": 1530662205.549,
          "BatchSize": 100,
          "EventSourceArn": "arn:aws:dynamodb:us-west-2:accountid:table/Migration/stream/2018-07-03T15:09:57.725",
          "FunctionArn": "arn:aws:lambda:us-west-2:accountid:function:dynamodb-spanner-lambda",
          "State": "Creating",
          "LastProcessingResult": "No records processed"
      ... truncated output...
      

    Amazon S3๋กœ Amazon DynamoDB ํ…Œ์ด๋ธ” ๋‚ด๋ณด๋‚ด๊ธฐ

    1. Cloud Shell์—์„œ ์—ฌ๋Ÿฌ ํ›„์† ์„น์…˜์— ์‚ฌ์šฉํ•  ๋ฒ„ํ‚ท ์ด๋ฆ„์˜ ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      BUCKET=${DEVSHELL_PROJECT_ID}-dynamodb-spanner-export
      
    2. DynamoDB๋ฅผ ๋‚ด๋ณด๋‚ผ Amazon S3 ๋ฒ„ํ‚ท์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      aws s3 mb s3://${BUCKET}
      
    3. AWS ๊ด€๋ฆฌ ์ฝ˜์†”์—์„œ DynamoDB๋กœ ์ด๋™ํ•˜์—ฌ ํ…Œ์ด๋ธ”์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    4. Migration ํ…Œ์ด๋ธ”์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    5. ๋‚ด๋ณด๋‚ด๊ธฐ ๋ฐ ์ŠคํŠธ๋ฆผ ํƒญ์—์„œ S3๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    6. ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด point-in-time-recovery(PITR)๋ฅผ ์‚ฌ์šฉ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    7. S3 ์ฐพ์•„๋ณด๊ธฐ๋ฅผ ํด๋ฆญํ•˜์—ฌ ์ด์ „์— ๋งŒ๋“  S3 ๋ฒ„ํ‚ท์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

    8. ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    9. ์ƒˆ๋กœ๊ณ ์นจ ์•„์ด์ฝ˜์„ ํด๋ฆญํ•˜์—ฌ ๋‚ด๋ณด๋‚ด๊ธฐ ์ž‘์—… ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์—์„œ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ๋ช‡ ๋ถ„ ์ •๋„ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค.

      ํ”„๋กœ์„ธ์Šค๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ถœ๋ ฅ ๋ฒ„ํ‚ท์„ ์‚ดํŽด๋ด…๋‹ˆ๋‹ค.

      aws s3 ls --recursive s3://${BUCKET}
      

      ์ด ๋‹จ๊ณ„๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๋ฐ ์•ฝ 5๋ถ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™„๋ฃŒ๋˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      2022-02-17 04:41:46          0 AWSDynamoDB/01645072900758-ee1232a3/_started
      2022-02-17 04:46:04     500441 AWSDynamoDB/01645072900758-ee1232a3/data/xygt7i2gje4w7jtdw5652s43pa.json.gz
      2022-02-17 04:46:17        199 AWSDynamoDB/01645072900758-ee1232a3/manifest-files.json
      2022-02-17 04:46:17         24 AWSDynamoDB/01645072900758-ee1232a3/manifest-files.md5
      2022-02-17 04:46:17        639 AWSDynamoDB/01645072900758-ee1232a3/manifest-summary.json
      2022-02-17 04:46:18         24 AWSDynamoDB/01645072900758-ee1232a3/manifest-summary.md5
      

    ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ˆ˜ํ–‰

    ์ด์ œ Pub/Sub๊ฐ€ ์ œ๊ณต๋˜๋ฏ€๋กœ ๋‚ด๋ณด๋‚ด๊ธฐ ์ดํ›„์— ๋ฐœ์ƒํ•œ ํ…Œ์ด๋ธ” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ํ‘ธ์‹œํ•ด ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋‚ด๋ณด๋‚ธ ํ…Œ์ด๋ธ”์„ Cloud Storage์— ๋ณต์‚ฌ

    1. Cloud Shell์—์„œ Cloud Storage ๋ฒ„ํ‚ท์„ ๋งŒ๋“ค์–ด Amazon S3์—์„œ ๋‚ด๋ณด๋‚ธ ํŒŒ์ผ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

      gcloud storage buckets create gs://${BUCKET}
      
    2. ํŒŒ์ผ์„ Amazon S3์—์„œ Cloud Storage๋กœ ๋™๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๋ณต์‚ฌ ์ž‘์—…์—์„œ๋Š” rsync ๋ช…๋ น์–ด๊ฐ€ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. ๋‚ด๋ณด๋‚ด๊ธฐ ํŒŒ์ผ์˜ ์šฉ๋Ÿ‰์ด ํฐ ๊ฒฝ์šฐ(์ˆ˜ GB ์ด์ƒ) Cloud Storage Transfer Service๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์ „์†ก์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

      gcloud storage rsync s3://${BUCKET} gs://${BUCKET} --recursive --delete-unmatched-destination-objects
      

    ๋ฐ์ดํ„ฐ ์ผ๊ด„ ๊ฐ€์ ธ์˜ค๊ธฐ

    1. ๋‚ด๋ณด๋‚ธ ํŒŒ์ผ์˜ ๋ฐ์ดํ„ฐ๋ฅผ Spanner ํ…Œ์ด๋ธ”์— ์“ฐ๋ ค๋ฉด Dataflow ์ž‘์—…์„ ์ƒ˜ํ”Œ Apache Beam ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

      cd dataflow
      mvn compile
      mvn exec:java \
      -Dexec.mainClass=com.example.spanner_migration.SpannerBulkWrite \
      -Pdataflow-runner \
      -Dexec.args="--project=GOOGLE_CLOUD_PROJECT \
                   --instanceId=spanner-migration \
                   --databaseId=migrationdb \
                   --table=Migration \
                   --importBucket=$BUCKET \
                   --runner=DataflowRunner \
                   --region=us-central1"
      
      1. ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—…์˜ ์ง„ํ–‰๋ฅ ์„ ๋ณด๋ ค๋ฉด Google Cloud ์ฝ˜์†”์—์„œ Dataflow๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

        Dataflow๋กœ ์ด๋™

      2. ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š” ๋™์•ˆ ์‹คํ–‰ ๊ทธ๋ž˜ํ”„๋ฅผ ์‚ดํŽด๋ณด๊ณ  ๋กœ๊ทธ๋ฅผ ๊ฒ€ํ† ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๊ฐ€ ์‹คํ–‰ ์ค‘์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ์ž‘์—…์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

        ์‹คํ–‰ ์ค‘์ธ ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—…

    2. ๊ฐ ๋‹จ๊ณ„๋ฅผ ํด๋ฆญํ•˜์—ฌ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์š”์†Œ๊ฐ€ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ๋ชจ๋“  ๋‹จ๊ณ„๊ฐ€ ์„ฑ๊ณต์ด๋ผ๊ณ  ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Amazon DynamoDB ํ…Œ์ด๋ธ”์—์„œ ๋งŒ๋“  ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ˆ˜์˜ ์š”์†Œ๊ฐ€ ๊ฐ ๋‹จ๊ณ„์—์„œ ์ฒ˜๋ฆฌ๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—…์˜ ์„ฑ๊ณต ๋‹จ๊ณ„

    3. ๋Œ€์ƒ Spanner ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ ์ˆ˜๊ฐ€ Amazon DynamoDB ํ…Œ์ด๋ธ”์˜ ํ•ญ๋ชฉ ์ˆ˜์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

      aws dynamodb describe-table --table-name Migration --query Table.ItemCount
      gcloud spanner databases execute-sql migrationdb \ --instance=spanner-migration --sql="select count(*) from Migration"

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      $ aws dynamodb describe-table --table-name Migration --query Table.ItemCount
      25000
      $ gcloud spanner databases execute-sql migrationdb --instance=spanner-migration --sql="select count(*) from Migration"
      25000
      
    4. ๊ฐ ํ…Œ์ด๋ธ”์—์„œ ์ž„์˜ ํ•ญ๋ชฉ์„ ์ƒ˜ํ”Œ๋งํ•˜์—ฌ ๋ฐ์ดํ„ฐ๊ฐ€ ์ผ๊ด€์ ์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

      gcloud spanner databases execute-sql migrationdb \
          --instance=spanner-migration \
          --sql="select * from Migration limit 1"
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

       Username: aadams4495
       PointsEarned: 5247
       ReminderDate: 2022-03-14
       Subscribed: True
       Zipcode: 58057
      
    5. ์ด์ „ ๋‹จ๊ณ„์—์„œ Spanner ์ฟผ๋ฆฌ์—์„œ ๋ฐ˜ํ™˜๋œ ๊ฒƒ๊ณผ ๋™์ผํ•œ Username๋กœ Amazon DynamoDB ํ…Œ์ด๋ธ”์„ ์ฟผ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด aallen2538์ž…๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ƒ˜ํ”Œ ๋ฐ์ดํ„ฐ์—๋งŒ ๊ด€๋ จ๋ฉ๋‹ˆ๋‹ค.

      aws dynamodb get-item --table-name Migration \
          --key '{"Username": {"S": "aadams4495"}}'
      

      ๋‹ค๋ฅธ ํ•„๋“œ์˜ ๊ฐ’์ด Spanner ์ถœ๋ ฅ์˜ ๊ฐ’๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      {
          "Item": {
              "Username": {
                  "S": "aadams4495"
              },
              "ReminderDate": {
                  "S": "2018-06-18"
              },
              "PointsEarned": {
                  "N": "1606"
              },
              "Zipcode": {
                  "N": "17303"
              },
              "Subscribed": {
                  "BOOL": false
              }
          }
      }
      

    ์ƒˆ ๋ณ€๊ฒฝ์‚ฌํ•ญ ๋ณต์ œ

    ์ผ๊ด„ ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์†Œ์Šค ํ…Œ์ด๋ธ”์—์„œ Spanner๋กœ ์ง„ํ–‰์ค‘์ธ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ธฐ๋กํ•˜๋„๋ก ์ŠคํŠธ๋ฆฌ๋ฐ ์ž‘์—…์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. Pub/Sub์˜ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ Spanner์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.

    ์‚ฌ์šฉ์ž๊ฐ€ ๋งŒ๋“  Lambda ํ•จ์ˆ˜๋Š” ์†Œ์Šค Amazon DynamoDB ํ…Œ์ด๋ธ”์˜ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์บก์ฒ˜ํ•˜์—ฌ Pub/Sub์— ๊ฒŒ์‹œํ•˜๋„๋ก ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

    1. AWS Lambda๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•˜๋Š” Pub/Sub ์ฃผ์ œ์— ๋Œ€ํ•œ ๊ตฌ๋…์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

      gcloud pubsub subscriptions create spanner-migration \
          --topic spanner-migration
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      Created subscription [projects/your-project/subscriptions/spanner-migration].
      
    2. Pub/Sub๋กœ ๋“ค์–ด์˜ค๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜์—ฌ Spanner ํ…Œ์ด๋ธ”์— ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์“ฐ๋ ค๋ฉด Cloud Shell์—์„œ Dataflow ์ž‘์—…์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

      mvn exec:java \
      -Dexec.mainClass=com.example.spanner_migration.SpannerStreamingWrite \
      -Pdataflow-runner \
      -Dexec.args="--project=GOOGLE_CLOUD_PROJECT \
                   --instanceId=spanner-migration \
                   --databaseId=migrationdb \
                   --table=Migration \
                   --experiments=allow_non_updatable_job \
      --subscription=projects/GOOGLE_CLOUD_PROJECT/subscriptions/spanner-migration \
      --runner=DataflowRunner \
      --region=us-central1"
      
      1. ์ผ๊ด„ ๋กœ๋“œ ๋‹จ๊ณ„์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ž‘์—… ์ง„ํ–‰๋ฅ ์„ ๋ณด๋ ค๋ฉด Google Cloud ์ฝ˜์†”์—์„œ Dataflow๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

        Dataflow๋กœ ์ด๋™

      2. ์ƒํƒœ๊ฐ€ ์‹คํ–‰ ์ค‘์ธ ์ž‘์—…์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

        ์‹คํ–‰ ์ค‘์ธ ์ž‘์—…

        ์ฒ˜๋ฆฌ ๊ทธ๋ž˜ํ”„๋Š” ์ด์ „๊ณผ ๋น„์Šทํ•œ ์ถœ๋ ฅ์„ ํ‘œ์‹œํ•˜์ง€๋งŒ, ์ฒ˜๋ฆฌ๋œ ํ•ญ๋ชฉ์€ ๊ฐ๊ฐ ์ƒํƒœ ์ฐฝ์—์„œ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ ์ง€์—ฐ ์‹œ๊ฐ„์€ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด Spanner ํ…Œ์ด๋ธ”์— ๋ฐ˜์˜๋˜๊ธฐ ์ „์— ์˜ˆ์ƒ๋˜๋Š” ์ง€์—ฐ ์‹œ๊ฐ„์„ ๋Œ€๋žต์ ์œผ๋กœ ์ถ”์ •ํ•œ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

        ์ง€์—ฐ ์‹œ๊ฐ„์œผ๋กœ ์ธํ•ด ์‹คํ–‰ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค

    ์ผ๊ด„ ๋กœ๋“œ ๋‹จ๊ณ„์—์„œ ์‹คํ–‰ํ•œ Dataflow ์ž‘์—…์€ ์œ ํ•œํ•œ ์ž…๋ ฅ๊ฐ’ ์ง‘ํ•ฉ์ด์—ˆ์œผ๋ฉฐ, ์ด๋ฅผ ์ œํ•œ๋œ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ผ๊ณ ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์ด Dataflow ์ž‘์—…์€ Pub/Sub๋ฅผ ์ŠคํŠธ๋ฆฌ๋ฐ ์†Œ์Šค๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ, ๋ฌด์ œํ•œ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค. ์ด 2๊ฐ€์ง€ ์œ ํ˜•์˜ ์†Œ์Šค์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ Apache Beam ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐ€์ด๋“œ์˜ PCollections ์„น์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”. ์ด ๋‹จ๊ณ„์˜ Dataflow ์ž‘์—…์€ ํ™œ์„ฑ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์™„๋ฃŒ ์‹œ ์ข…๋ฃŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Dataflow ์ŠคํŠธ๋ฆฌ๋ฐ ์ž‘์—…์€ ์„ฑ๊ณต ์ƒํƒœ๋กœ ๋ฐ”๋€Œ๋Š” ๋Œ€์‹  ์‹คํ–‰ ์ค‘ ์ƒํƒœ๋กœ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋ณต์ œ ํ™•์ธ

    ์†Œ์Šค ํ…Œ์ด๋ธ”์„ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด Spanner ํ…Œ์ด๋ธ”์— ๋ณต์ œ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

    1. Spanner์— ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํ–‰์„ ์ฟผ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

      gcloud spanner databases execute-sql migrationdb \
          --instance=spanner-migration \
          --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
      

      ์ด ์ž‘์—…์€ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    2. Spanner ์ฟผ๋ฆฌ์— ์‚ฌ์šฉํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Amazon DynamoDB์—์„œ ๋ ˆ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋ช…๋ น์–ด๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์‹คํ–‰๋  ๊ฒฝ์šฐ ์ถœ๋ ฅ๋˜๋Š” ๋‚ด์šฉ์€ ์—†์Šต๋‹ˆ๋‹ค.

      aws dynamodb put-item \
          --table-name Migration \
          --item '{"Username" : {"S" : "my-test-username"}, "Subscribed" : {"BOOL" : false}}'
      
    3. ๊ฐ™์€ ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜์—ฌ ์ด์ œ ํ•ด๋‹น ํ–‰์ด Spanner์— ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

      gcloud spanner databases execute-sql migrationdb \
          --instance=spanner-migration \
          --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
      

      ์‚ฝ์ž…๋œ ํ–‰์ด ์ถœ๋ ฅ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      Username: my-test-username
      PointsEarned: None
      ReminderDate: None
      Subscribed: False
      Zipcode:
      
    4. ์›๋ž˜ ํ•ญ๋ชฉ์—์„œ ์ผ๋ถ€ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ณ  Amazon DynamoDB ํ…Œ์ด๋ธ”์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

      aws dynamodb update-item \
          --table-name Migration \
          --key '{"Username": {"S":"my-test-username"}}' \
          --update-expression "SET PointsEarned = :pts, Subscribed = :sub" \
          --expression-attribute-values '{":pts": {"N":"4500"}, ":sub": {"BOOL":true}}'\
          --return-values ALL_NEW
      

      ๋‹ค์Œ๊ณผ ๋น„์Šทํ•œ ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      {
          "Attributes": {
              "Username": {
                  "S": "my-test-username"
              },
              "PointsEarned": {
                  "N": "4500"
              },
              "Subscribed": {
                  "BOOL": true
              }
          }
      }
      
    5. ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด Spanner ํ…Œ์ด๋ธ”์— ์ „ํŒŒ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

      gcloud spanner databases execute-sql migrationdb \
          --instance=spanner-migration \
          --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
      

      ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

      Username          PointsEarned  ReminderDate  Subscribed  Zipcode
      my-test-username  4500          None          True
      
    6. Amazon DynamoDB ์†Œ์Šค ํ…Œ์ด๋ธ”์—์„œ ํ…Œ์ŠคํŠธ ํ•ญ๋ชฉ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

      aws dynamodb delete-item \
          --table-name Migration \
          --key '{"Username": {"S":"my-test-username"}}'
      
    7. ํ•ด๋‹น ํ–‰์ด Spanner ํ…Œ์ด๋ธ”์—์„œ ์‚ญ์ œ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ „ํŒŒ๋˜๋ฉด ๋‹ค์Œ ๋ช…๋ น์–ด๊ฐ€ ํ–‰์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

      gcloud spanner databases execute-sql migrationdb \
          --instance=spanner-migration \
          --sql="SELECT * FROM Migration WHERE Username='my-test-username'"
      

    ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ํ…Œ์ด๋ธ” ์‚ฌ์šฉ

    Spanner๋Š” ํ…Œ์ด๋ธ” ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ ๊ฐœ๋…์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐœ๋…์€ ์ตœ์ƒ์œ„ ํ•ญ๋ชฉ์— ํ•ด๋‹น ์ตœ์ƒ์œ„ ํ•ญ๋ชฉ๊ณผ ๊ด€๋ จ๋œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ค‘์ฒฉ๋œ ํ•ญ๋ชฉ์ด ์žˆ๋Š” ์„ค๊ณ„ ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค(์˜ˆ: ๊ณ ๊ฐ๊ณผ ๊ณ ๊ฐ ์ฃผ๋ฌธ, ํ”Œ๋ ˆ์ด์–ด์™€ ํ”Œ๋ ˆ์ด์–ด ๊ฒŒ์ž„ ์ ์ˆ˜). Amazon DynamoDB ์†Œ์Šค ํ…Œ์ด๋ธ”์ด ํ•ด์‹œ ํ‚ค์™€ ๋ฒ”์œ„ ํ‚ค๋กœ ๊ตฌ์„ฑ๋œ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋‹ค์Œ ๋‹ค์ด์–ด๊ทธ๋žจ์˜ ๋‚ด์šฉ์ฒ˜๋Ÿผ ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ํ…Œ์ด๋ธ” ์Šคํ‚ค๋งˆ๋ฅผ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์œ„ ํ…Œ์ด๋ธ”์—์„œ ํ•„๋“œ๋ฅผ ๊ฒฐํ•ฉํ•  ๋•Œ ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ํ…Œ์ด๋ธ”์„ ํšจ์œจ์ ์œผ๋กœ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์‚ฌ์šฉ์ž ํ…Œ์ด๋ธ”๊ณผ ์ฃผ๋ฌธ ํ…Œ์ด๋ธ” ๋น„๊ต

    ๋ณด์กฐ ์ƒ‰์ธ ์ ์šฉ

    ๊ถŒ์žฅ์‚ฌํ•ญ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•œ ํ›„์— ๋ณด์กฐ ์ƒ‰์ธ์„ Spanner ํ…Œ์ด๋ธ”์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ ๋ณต์ œ๋ฅผ ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด์กฐ ์ƒ‰์ธ์„ ์„ค์ •ํ•˜์—ฌ ์ฟผ๋ฆฌ ์†๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Spanner ํ…Œ์ด๋ธ”๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Spanner ๋ณด์กฐ ์ƒ‰์ธ์€ ์ผ๊ด€์ ์ž…๋‹ˆ๋‹ค. ๋งŽ์€ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์ ์šฉ๋˜๋Š” eventual consistency๋ฅผ ๊ฐ€์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ์•ฑ ์„ค๊ณ„๊ฐ€ ๊ฐ„์†Œํ™”๋ฉ๋‹ˆ๋‹ค.

    ์ƒ‰์ธ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ํŠน์ • ์—ด ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์ƒ์œ„ N๊ฐœ์˜ ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ์„ ์ฐพ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํšจ์œจ์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด Amazon DynamoDB์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ์ฟผ๋ฆฌ์ž…๋‹ˆ๋‹ค.

    1. Spanner๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

      Spanner๋กœ ์ด๋™

    2. Spanner ์ŠคํŠœ๋””์˜ค๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

      ์ฟผ๋ฆฌ ๋ฒ„ํŠผ

    3. ์ฟผ๋ฆฌ ํ•„๋“œ์— ๋‹ค์Œ ์ฟผ๋ฆฌ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์ฟผ๋ฆฌ ์‹คํ–‰์„ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

      SELECT Username,PointsEarned
        FROM Migration
       WHERE Subscribed=true
         AND ReminderDate > DATE_SUB(DATE(current_timestamp()), INTERVAL 14 DAY)
       ORDER BY ReminderDate DESC
       LIMIT 10
      

      ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰๋˜๋ฉด ์„ค๋ช…์„ ํด๋ฆญํ•˜๊ณ  ์Šค์บ”๋œ ํ–‰๊ณผ ๋ฐ˜ํ™˜๋œ ํ–‰์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ƒ‰์ธ์ด ์—†์œผ๋ฉด Spanner๊ฐ€ ์ „์ฒด ํ…Œ์ด๋ธ”์„ ์Šค์บ”ํ•˜์—ฌ ์ฟผ๋ฆฌ์™€ ์ผ์น˜ํ•˜๋Š” ์†Œ๊ทœ๋ชจ ๋ฐ์ดํ„ฐ ํ•˜์œ„ ์ง‘ํ•ฉ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

      ์Šค์บ”๋œ ํ–‰๊ณผ ๋ฐ˜ํ™˜๋œ ํ–‰ ๋น„๊ต

    4. ์ด ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์ด ์ž์ฃผ ์ˆ˜ํ–‰๋˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒฝ์šฐ์—๋Š” Subscribed ๋ฐ ReminderDate ์—ด์—์„œ ๋ณตํ•ฉ ์ƒ‰์ธ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. Spanner ์ฝ˜์†”์—์„œ ์ƒ‰์ธ ์™ผ์ชฝ ํƒ์ƒ‰ ์ฐฝ์„ ์„ ํƒํ•œ ํ›„ ์ƒ‰์ธ ๋งŒ๋“ค๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

    5. ํ…์ŠคํŠธ ์ƒ์ž์— ์ƒ‰์ธ ์ •์˜๋ฅผ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

      CREATE INDEX SubscribedDateDesc
      ON Migration (
        Subscribed,
        ReminderDate DESC
      )
      
    6. ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ๋งŒ๋“ค๊ธฐ๋ฅผ ํด๋ฆญํ•ฉ๋‹ˆ๋‹ค.

      ์Šคํ‚ค๋งˆ ์—…๋ฐ์ดํŠธ ์ง„ํ–‰ ์ค‘

    7. ์ƒ‰์ธ์„ ๋งŒ๋“  ํ›„์—๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋‹ค์‹œ ์‹คํ–‰ํ•˜๊ณ  ์ƒ‰์ธ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

      SELECT Username,PointsEarned
        FROM Migration@{FORCE_INDEX=SubscribedDateDesc}
       WHERE Subscribed=true
         AND ReminderDate > DATE_SUB(DATE(current_timestamp()), INTERVAL 14 DAY)
       ORDER BY ReminderDate DESC
       LIMIT 10
      

      ์ฟผ๋ฆฌ ์„ค๋ช…์„ ๋‹ค์‹œ ๊ฒ€ํ† ํ•ฉ๋‹ˆ๋‹ค. ์Šค์บ”๋œ ํ–‰ ์ˆ˜๊ฐ€ ์ค„์–ด๋“  ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ๋‹จ๊ณ„์˜ ๋ฐ˜ํ™˜๋œ ํ–‰์€ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํšŸ์ˆ˜์™€ ์ผ์น˜ํ•ฉ๋‹ˆ๋‹ค.

      ์ฟผ๋ฆฌ ์„ค๋ช…

    ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ์ƒ‰์ธ

    Spanner์—์„œ ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ์ƒ‰์ธ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „ ์„น์…˜์—์„œ ์„ค๋ช…ํ•œ ๋ณด์กฐ ์ƒ‰์ธ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ณ„์ธต ๊ตฌ์กฐ์˜ ๋ฃจํŠธ์— ์žˆ์œผ๋ฉฐ, ๊ธฐ์กด์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋™์ผํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์ƒ‰์ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ์ƒ‰์ธ์€ ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ํ–‰์˜ ์ปจํ…์ŠคํŠธ ๋‚ด์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐ๋ฆฌ๋ธŒ ์ฒ˜๋ฆฌ๋œ ์ƒ‰์ธ์„ ์ ์šฉํ•  ์œ„์น˜์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ƒ‰์ธ ์˜ต์…˜์„ ์ฐธ์กฐํ•˜์„ธ์š”.

    ๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์กฐ์ •

    ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ์ด์ „ํ•˜๊ธฐ ๋ถ€๋ถ„์„ ์‚ฌ์šฉ์ž์˜ ์ƒํ™ฉ์— ๋งž์ถฐ ์กฐ์ •ํ•˜๋ ค๋ฉด Apache Beam ์†Œ์Šค ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜์„ธ์š”. ์‹ค์ œ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๊ธฐ๊ฐ„ ์ค‘์— ์†Œ์Šค ์Šคํ‚ค๋งˆ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ฐ์ดํ„ฐ๊ฐ€ ์†์‹ค๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    1. ์ˆ˜์‹ ํ•œ JSON์„ ํŒŒ์‹ฑํ•˜๊ณ  ๋ณ€ํ˜•์„ ๋นŒ๋“œํ•˜๋ ค๋ฉด GSON์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. JSON ์ •์˜๋ฅผ ๋ฐ์ดํ„ฐ์— ๋งž๊ฒŒ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

      public static class Record implements Serializable {
      
        private Item Item;
      
      }
      
      public static class Item implements Serializable {
      
        private Username Username;
        private PointsEarned PointsEarned;
        private Subscribed Subscribed;
        private ReminderDate ReminderDate;
        private Zipcode Zipcode;
      
      }
      
      public static class Username implements Serializable {
      
        private String S;
      
      }
      
      public static class PointsEarned implements Serializable {
      
        private String N;
      
      }
      
      public static class Subscribed implements Serializable {
      
        private String BOOL;
      
      }
      
      public static class ReminderDate implements Serializable {
      
        private String S;
      
      }
      
      public static class Zipcode implements Serializable {
      
        private String N;
      
      }
    2. ํ•ด๋‹น JSON ๋งคํ•‘์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

      mutation.set("Username").to(record.Item.Username.S);
      
      Optional.ofNullable(record.Item.Zipcode).ifPresent(x -> {
        mutation.set("Zipcode").to(Integer.parseInt(x.N));
      });
      
      Optional.ofNullable(record.Item.Subscribed).ifPresent(x -> {
        mutation.set("Subscribed").to(Boolean.parseBoolean(x.BOOL));
      });
      
      Optional.ofNullable(record.Item.ReminderDate).ifPresent(x -> {
        mutation.set("ReminderDate").to(Date.parseDate(x.S));
      });
      
      Optional.ofNullable(record.Item.PointsEarned).ifPresent(x -> {
        mutation.set("PointsEarned").to(Integer.parseInt(x.N));
      });

    ์ด์ „ ๋‹จ๊ณ„์—์„œ๋Š” Apache Beam ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด ์ผ๊ด„ ๊ฐ€์ ธ์˜ค๊ธฐ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ŠคํŠธ๋ฆฌ๋ฐ ๋ถ€๋ถ„์— ๋Œ€ํ•œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ์ˆ˜์ •ํ•˜์„ธ์š”. ๋งˆ์ง€๋ง‰์œผ๋กœ Spanner ๋Œ€์ƒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ํ…Œ์ด๋ธ” ์ƒ์„ฑ ์Šคํฌ๋ฆฝํŠธ, ์Šคํ‚ค๋งˆ, ์ƒ‰์ธ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

    ์‚ญ์ œ

    ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์‚ฌ์šฉ๋œ ๋ฆฌ์†Œ์Šค ๋น„์šฉ์ด Google Cloud ๊ณ„์ •์— ์ฒญ๊ตฌ๋˜์ง€ ์•Š๋„๋ก ํ•˜๋ ค๋ฉด ๋ฆฌ์†Œ์Šค๊ฐ€ ํฌํ•จ๋œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ํ”„๋กœ์ ํŠธ๋Š” ์œ ์ง€ํ•˜๋˜ ๊ฐœ๋ณ„ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•˜์„ธ์š”.

    ํ”„๋กœ์ ํŠธ ์‚ญ์ œ

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    AWS ๋ฆฌ์†Œ์Šค ์‚ญ์ œ

    ์ด ํŠœํ† ๋ฆฌ์–ผ ์™ธ์˜ ๋‹ค๋ฅธ ๊ณณ์—์„œ AWS ๊ณ„์ •์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ, ๋‹ค์Œ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ญ์ œํ•  ๋•Œ ์ฃผ์˜ํ•˜์„ธ์š”.

    1. Migration์ด๋ผ๋Š” DynamoDB ํ…Œ์ด๋ธ”์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.
    2. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋‹จ๊ณ„ ์ค‘์— ๋งŒ๋“  Amazon S3 ๋ฒ„ํ‚ท ๋ฐ Lambda ํ•จ์ˆ˜๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.
    3. ๋งˆ์ง€๋ง‰์œผ๋กœ ์ด ํŠœํ† ๋ฆฌ์–ผ์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ๋งŒ๋“  AWS IAM ์‚ฌ์šฉ์ž๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

    ๋‹ค์Œ ๋‹จ๊ณ„