ในโมดูลนี้ คุณจะได้เตรียมฐานข้อมูล Amazon DynamoDB และเรียนรู้วิธีการใช้ DynamoDB เพื่อจัดเก็บข้อมูลเกี่ยวกับเกมเทิร์นเบสของคุณ

ระยะเวลาที่ใช้ในการศึกษาโมดูล: 30 นาที


Amazon DynamoDB คือฐานข้อมูล NoSQL ที่มีการจัดการเต็มรูปแบบ ซึ่งให้บริการโดย AWS และยังตอบสนองได้ภายในมิลลิวินาทีหลักเดียวและมีการปรับขนาดได้ไม่จำกัด DynamoDB ถูกนำไปใช้ในแอปพลิเคชันและอุตสาหกรรมอย่างกว้างขวาง ตั้งแต่รถเข็นซื้อของ Amazon.com ไปจนถึงบริการบอกตำแหน่งที่ตั้งทางภูมิศาสตร์ของ Lyft’s และเกมออนไลน์อีกมากมาย

การโต้ตอบกับ DynamoDB ทั้งหมดจะดำเนินการผ่าน HTTPS โดยใช้ AWS Identity and Access Management (IAM) สำหรับการรับรองความถูกต้องและการอนุญาต บ่อยครั้ง คุณจะได้ใช้ AWS SDK สำหรับภาษาที่ต้องการเพื่อโต้ตอบกับ DynamoDB หากคุณกำลังใช้ตัวเลือกการประมวลผลของ AWS สำหรับแอปพลิเคชันของคุณ เช่น Amazon Elastic Compute Cloud (Amazon EC2) หรือ AWS Lambda แอปพลิเคชันของคุณจะสามารถใช้ข้อมูลประจำตัวของ AWS ในสภาพแวดล้อมการประมวลผลเพื่อส่งคำร้องขอไปยัง DynamoDB ได้

ในขั้นตอนต่อไปนี้ คุณจะได้เตรียมฐานข้อมูล DynamoDB เป็นอันดับแรก จากนั้น คุณจะได้เรียนรู้วิธีการโต้ตอบกับฐานข้อมูล DynamoDB โดยใช้ AWS SDK for JavaScript ใน Node.js


  • ขั้นตอนที่ 1 เตรียมฐานข้อมูล Amazon DynamoDB

    ก่อนอื่น มาเตรียมฐานข้อมูล DynamoDB กันเลย ฐานข้อมูลใน DynamoDB จะเรียกอีกอย่างหนึ่งว่า ตาราง

    เมื่อสร้างตาราง DynamoDB คุณต้องระบุแอตทริบิวต์ที่จะใช้เป็น คีย์หลัก ของตาราง แต่ละระเบียนที่คุณเขียนลงในตาราง DynamoDB จะเรียกว่า รายการ และแต่ละรายการต้องมีคีย์หลักของตารางของคุณ

    การทำโมเดลข้อมูล DynamoDB และการออกแบบคีย์หลักคือหัวข้อสำคัญ อย่างไรก็ตาม เกมของคุณมีรูปแบบการเข้าถึงง่ายๆ ที่ไม่จำเป็นต้องใช้การทำโมเดลข้อมูลขั้นสูง ดังนั้น บทช่วยสอนนี้จะไม่ครอบคลุมหัวข้อขั้นสูงในการทำโมเดลข้อมูล DynamoDB สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการทำโมเดลข้อมูล DynamoDB คุณสามารถอ่านบทช่วยสอนเกี่ยวกับ การออกแบบฐานข้อมูลสำหรับแอปบนอุปกรณ์เคลื่อนที่ด้วย Amazon DynamoDB หรือ การทำโมเดลข้อมูลแอปพลิเคชันการเล่นเกมด้วย Amazon DynamoDB

    ในแอปพลิเคชันของคุณ คุณจะใช้ DynamoDB เป็นที่จัดเก็บ key-value ง่ายๆ แต่ละเกมมีแอตทริบิวต์ gameId ที่ระบุว่าแต่ละเกมไม่เหมือนกัน แอตทริบิวต์ gameId จะถูกนำไปใช้เป็นคีย์หลักสำหรับตารางของคุณ

    ในไดเรกทอรี scripts/ จะมีไฟล์ที่ชื่อว่า create-table.sh ที่สร้างตาราง DynamoDB ของคุณโดยใช้ AWS Command Line Interface (AWS CLI) เนื้อหาในไฟล์มีดังต่อไปนี้:
     

    aws dynamodb create-table \
      --table-name turn-based-game \
      --attribute-definitions '[
        {
          "AttributeName": "gameId",
          "AttributeType": "S"
        }
      ]' \
      --key-schema '[
        {
          "AttributeName": "gameId",
          "KeyType": "HASH"
        }
      ]' \
      --provisioned-throughput '{
        "ReadCapacityUnits": 5,
        "WriteCapacityUnits": 5
      }'

    อันดับแรก จะตั้งชื่อตารางว่า เกมเทิร์นเบส จากนั้น จะประกาศแอตทริบิวต์ที่ใช้ในคีย์หลักของตาราง คุณกำลังใช้คีย์หลักง่ายๆ ในตัวอย่างนี้ ดังนั้น คุณต้องประกาศแอตทริบิวต์ gameId เพียงแอตทริบิวต์เดียว ซึ่งเป็นประเภทข้อมูลสตริง ถัดไป คุณต้องระบุ Schema ของคีย์หลักโดยการระบุว่าให้ใช้แอตทริบิวต์ gameId เป็นคีย์แฮชของตารางของคุณ

    สุดท้าย คุณต้องระบุจำนวนหน่วยความจุการอ่านและการเขียนที่คุณต้องการสำหรับตารางของคุณ DynamoDB มีโหมดราคาตามความต้องการ ซึ่งคุณจะต้องชำระค่าบริการตามคำขออ่านและเขียนในตารางแต่ละคำขอ อย่างไรก็ตาม โหมดปริมาณการประมวลผลที่เตรียมไว้จะอยู่ภายใน AWS Free Tier คุณจึงใช้โหมดดังกล่าวที่นี่ได้

    สร้างตารางของคุณโดยการใช้คำสั่งต่อไปนี้ในเทอร์มินัลของคุณ:

    bash scripts/create-table.sh

    คุณควรจะเห็นผลลัพธ์ต่อไปนี้ในเทอร์มินัลของคุณ:

    {
        "TableDescription": {
            "AttributeDefinitions": [
                {
                    "AttributeName": "gameId",
                    "AttributeType": "S"
                }
            ],
            "TableName": "turn-based-game",
            "KeySchema": [
                {
                    "AttributeName": "gameId",
                    "KeyType": "HASH"
                }
            ],
            "TableStatus": "CREATING",
            "CreationDateTime": 1574086642.07,
            "ProvisionedThroughput": {
                "NumberOfDecreasesToday": 0,
                "ReadCapacityUnits": 5,
                "WriteCapacityUnits": 5
            },
            "TableSizeBytes": 0,
            "ItemCount": 0,
            "TableArn": "arn:aws:dynamodb:us-east-1:955617200811:table/turn-based-game",
            "TableId": "c62cb86a-211e-4a50-a160-4a616c8f3445"
        }
    }
  • ขั้นตอนที่ 2 บันทึกตัวอย่างรายการเกมในตาราง

    ตอนนี้เมื่อได้สร้างตารางแล้ว คุณก็เพิ่มรายการลงในตารางของคุณได้ แต่ละเกมจะแสดงเป็นหนึ่งรายการในตาราง

    โครงสร้างของเกมแต่ละรายการมีดังต่อไปนี้:

    แต่ละเกมจะมี GameId ซึ่งเป็นตัวระบุที่ไม่ซ้ำกันของเกม แอตทริบิวต์ User1 และ User2 จัดเก็บชื่อผู้ใช้ของผู้ใช้สองรายที่กำลังเล่นเกม แอตทริบิวต์ Heap1, Heap2 และ Heap3 จัดเก็บจำนวนอ็อบเจ็กต์ในแต่ละฮีปทั้งสามฮีป สุดท้าย แอตทริบิวต์ LastMoveBy ระบุผู้เล่นที่มีการเคลื่อนไหวล่าสุด

    ในไดเรกทอรี scripts/ จะมีไฟล์ที่ชื่อว่า createGame.js ที่เพิ่มตัวอย่างเกมลงในตารางของคุณ เนื้อหาในไฟล์มีดังต่อไปนี้:

    const AWS = require('aws-sdk')
    const documentClient = new AWS.DynamoDB.DocumentClient()
    
    const params = {
      TableName: 'turn-based-game',
      Item: {
        gameId: '5b5ee7d8',
        user1: 'myfirstuser',
        user2: 'theseconduser',
        heap1: 5,
        heap2: 4,
        heap3: 5,
        lastMoveBy: 'myfirstuser'
      }
    }
    
    documentClient.put(params).promise()
      .then(() => console.log('Game added successfully!'))
      .catch((error) => console.log('Error adding game', error))

    คุณนำเข้า AWS SDK แล้วสร้างอินสแตนซ์ของ DynamoDB Document Client Document Client คือการกำหนดสาระสำคัญที่มีระดับสูงกว่า DynamoDB API ระดับต่ำ และทำให้การทำงานกับรายการ DynamoDB ง่ายขึ้น หลังจากสร้างไคลเอ็นต์ สคริปต์จะรวบรวมพารามิเตอร์สำหรับการเรียกใช้ PutItem API รวมถึงชื่อตารางและแอตทริบิวต์ของรายการ จากนั้น จะเรียกใช้วิธี put() บน Document Client และบันทึกข้อมูลว่าสำเร็จหรือล้มเหลว

    คุณเรียกใช้สคริปต์ได้เพื่อแทรกเกมลงในตารางโดยการใช้คำสั่งต่อไปนี้ในเทอร์มินัลของคุณ:

    node scripts/createGame.js

    คุณควรจะเห็นผลลัพธ์ต่อไปนี้ในเทอร์มินัลของคุณ:

    Game added successfully!

    หมายเหตุ: หากคุณใช้คำสั่งเร็วเกินไป คุณอาจพบข้อผิดพลาดที่ระบุว่าตารางยังไม่พร้อมใช้งาน รอหนึ่งนาที แล้วลองใช้คำสั่งอีกครั้ง

    เยี่ยม! คุณเพิ่มหนึ่งเกมลงในตารางแล้ว ในขั้นตอนถัดไป คุณจะได้เรียนรู้วิธีการอัปเดตรายการเกมเพื่อจำลองผู้ใช้ที่กำลังเคลื่อนไหว

  • ขั้นตอนที่ 3 อัปเดตรายการเกมในตาราง

    ตอนนี้ คุณมีรายการเกมในตารางของคุณแล้ว ก็สามารถเรียนรู้วิธีการจำลองผู้ใช้ที่กำลังเคลื่อนไหวในเกมที่ดำเนินการอยู่ได้

    วิธีจัดการการดำเนินการนี้มีอยู่สองวิธี ในวิธีแรก คุณจะดึงข้อมูลรายการโดยใช้ GetItem API จากนั้น คุณจะอัปเดตรายการเกมในแอปพลิเคชันของคุณตามการเคลื่อนไหวของผู้เล่น สุดท้าย คุณจะแทนที่รายการที่อยู่ใน DynamoDB โดยใช้ PutItem API แม้ว่าตัวเลือกนี้จะใช้งานได้ แต่ก็ต้องส่งคำขอหลายรายการไปยังตาราง DynamoDB ของคุณและเสี่ยงต่อการเขียนทับการเปลี่ยแปลงที่เกิดขึ้นระหว่างการดึงข้อมูลและการเขียนรายการเกมใหม่

    วิธีที่สองในการจัดการการดำเนินการนี้คือการเรียกใช้ UpdateItem API ใน DynamoDB เมื่อใช้ UpdateItem API คุณจะอัปเดตรายการ DynamoDB ด้วยคำขอเดียวได้ คุณระบุรายการที่คุณต้องการเปลี่ยนแปลง แอตทริบิวต์ที่จะเปลี่ยนแปลง และเงื่อนไขที่ต้องการยืนยันกับรายการ เราขอแนะนำให้ใช้วิธีนี้ในการเปลี่ยนแปลงรายการ เนื่องจากไม่จำเป็นต้องเรียกใช้ฐานข้อมูลหลายครั้ง

    ในไดเรกทอรี scripts/ จะมีไฟล์ที่ชื่อว่า performMove.js ซึ่งมีเนื้อหาต่อไปนี้:

    const AWS = require('aws-sdk')
    const documentClient = new AWS.DynamoDB.DocumentClient()
    
    const performMove = async ({ gameId, user, changedHeap, changedHeapValue }) => {
      if (changedHeapValue < 0 ) {
        throw new Error('Cannot set heap value below 0')
      }
      const params = {
        TableName: 'turn-based-game',
        Key: { 
          gameId: gameId
        },
        UpdateExpression: `SET lastMoveBy = :user, ${changedHeap} = :changedHeapValue`,
        ConditionExpression: `(user1 = :user OR user2 = :user) AND lastMoveBy <> :user AND ${changedHeap} > :changedHeapValue`,
        ExpressionAttributeValues: {
          ':user': user,
          ':changedHeapValue': changedHeapValue,
        },
        ReturnValues: 'ALL_NEW'
      }
      try {
        const resp = await documentClient.update(params).promise()
        console.log('Updated game: ', resp.Attributes)
      } catch (error) {
        console.log('Error updating item: ', error.message)
      }
    }
    
    performMove({ gameId: '5b5ee7d8', user: 'theseconduser', changedHeap: 'heap1', changedHeapValue: 3 })

    สคริปต์นี้ซับซ้อนเล็กน้อย ดังนั้น เราจะอธิบายทีละขั้นตอน

    เหมือนกับสคริปต์ก่อนหน้านี้ คือคุณนำเข้า AWS SDK และสร้างอินสแตนซ์ DynamoDB Document Client

    จากนั้น คุณกำหนดวิธีการที่เรียกว่า performMove วิธีนี้จะคล้ายกับวิธีการภายในที่ใช้ในแอปพลิเคชันของคุณ เมื่อผู้ใช้ร้องขอการเคลื่อนไหว สคริปต์จะรวบรวมพารามิเตอร์สำหรับการเรียกใช้ UpdateItem API อันดับแรก จะเปลี่ยนสองแอตทริบิวต์ของเกมคือ ผู้ใช้ล่าสุดที่เคลื่อนไหวและจำนวนขององค์ประกอบในฮีปที่เปลี่ยนแปลง

    จากนั้น พารามิเตอร์ UpdateItem API จะยืนยันเกี่ยวกับสถานะปัจจุบันของเกม ConditionExpression จะได้รับการประเมินก่อนที่จะอัปเดตรายการเพื่อยืนยันว่ารายการมีสถานะตามที่คุณต้องการ คุณกำลังยืนยันสามรายการต่อไปนี้ในการแสดงเงื่อนไขของคุณ:

    1. ผู้ใช้ที่ร้องขอการเคลื่อนไหวคือหนึ่งในผู้ใช้สองรายในเกม
    2. รอบปัจจุบันเป็นของผู้ใช้ที่ร้องขอการเคลื่อนไหว
    3. ฮีปที่กำลังเปลี่ยนแปลงมีค่าปัจจุบันสูงกว่าค่าที่จะเปลี่ยน

    สุดท้าย พารามิเตอร์ระบุ ReturnValue ของ ALL_NEW ซึ่งหมายความว่า DynamoDB ส่งกลับรายการทั้งหมดหลังจากอัปเดตค่าแล้ว เมื่อคุณมาถึงขั้นตอนนี้ แอปพลิเคชันของคุณจะประเมินเกมได้เพื่อดูว่ามีผู้ชนะหรือไม่

    ทางด้านล่างของไฟล์จะมีตัวอย่างการเรียกใช้วิธีนี้ในแอปพลิเคชันของคุณ คุณปฏิบัติการสคริปต์ได้ด้วยคำสั่งต่อไปนี้:

    node scripts/performMove.js

    คุณควรจะเห็นผลลัพธ์ต่อไปนี้ในเทอร์มินัลของคุณ:

    Updated game:  { heap2: 4,
      heap1: 3,
      heap3: 5,
      gameId: '5b5ee7d8',
      user2: 'theseconduser',
      user1: 'myfirstuser',
      lastMoveBy: 'theseconduser' }

    คุณจะเห็นว่าการเขียนสำเร็จแล้วและเกมได้รับการอัปเดตแล้ว

    ลองเรียกใช้สคริปต์อีกครั้งในเทอร์มินัลของคุณ คุณจะเห็นผลลัพธ์ต่อไปนี้:

    Error updating item:  The conditional request failed

    คำขอแบบมีเงื่อนไขของคุณล้มเหลวในครั้งนี้ ผู้ใช้ที่ร้องขอ – theseconduser – คือผู้ใช้ที่มีการเคลื่อนไหวล่าสุด นอกจากนี้ ฮีปที่เปลี่ยนแปลง – heap1 – มีค่า 3 อยู่แล้ว แสดงว่าผู้ใช้ไม่ได้เปลี่ยนแปลงอะไร ดังนั้น คำขอจึงถูกปฏิเสธ


ในโมดูลนี้ คุณได้เตรียมฐานข้อมูล Amazon DynamoDB เพื่อจัดเก็บข้อมูลเกมของคุณ คุณได้เรียนรู้เกี่ยวกับคีย์หลักใน DynamoDB ในการทำโมเดลข้อมูลของคุณ หลังจากสร้างตาราง คุณได้เรียนรู้วิธีการแทรกรายการลงในตารางเพื่อจัดเก็บสถานะเกมเบื้องต้น สุดท้าย คุณได้เห็นวิธีการอัปเดตรายการในข้อมูลของคุณเพื่อหลีกเลี่ยงการส่งคำขอหลายรายการไปยัง DynamoDB ในคำขอเดียว

ในโมดูลถัดไป คุณจะได้เรียนรู้เกี่ยวกับการใช้ Amazon Simple Notification Service (Amazon SNS) ในการส่งข้อความ SMS เพื่อแจ้งให้ผู้ใช้ทราบเกี่ยวกับเหตุการณ์สำคัญในเกมของพวกเขา