ทำไมต้อง PostgreSQL? ลิงก์ไปยังหัวข้อ

สมมติว่าคุณได้ตัดสินใจใช้ PostgreSQL เป็นฐานข้อมูลของคุณแล้ว ทำไม? เพราะมันเป็นระบบฐานข้อมูล object-relational แบบโอเพนซอร์สที่ทรงพลัง มีการพัฒนาอย่างต่อเนื่องมากว่า 30 ปี ใช่ไหม? เราจะปล่อยปัญหาเรื่องที่เก็บและวิธีการเก็บข้อมูลไว้ก่อนในโอกาสหน้า

RDS Aurora (PostgreSQL Compatible) หรือ RDS PostgreSQL ลิงก์ไปยังหัวข้อ

ถ้าไม่มีข้อกำหนดเฉพาะเจาะจง เราอาจเลือก Aurora เป็นตัวเลือกเริ่มต้น ระบบจัดเก็บข้อมูลคือความแตกต่างหลักระหว่างสองตัวนี้ คุณไม่ต้องกังวลเรื่องพื้นที่เต็ม Aurora จะช่วยคุณเอง Aurora จะปรับขนาดพื้นที่จัดเก็บอัตโนมัติได้สูงสุดถึง 128 TB (พฤศจิกายน 2024) “ข้อมูลจะถูกทำสำเนาอัตโนมัติข้าม Availability Zones ข้อมูลของคุณจะมีความทนทานสูงและมีโอกาสสูญหายน้อย” คุณสามารถมี instance เดียวที่มีข้อมูลอยู่ใน 3 ที่ต่างกัน ถ้าคุณต้องการเพิ่มอีกหนึ่ง region มันจะทำให้เรามี 6 ที่ต่างกันทั่วโลกที่เก็บข้อมูล มหัศจรรย์ใช่ไหม?

พารามิเตอร์ของ PostgreSQL ลิงก์ไปยังหัวข้อ

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

  • log_min_duration_statement = 4000 - ระยะเวลาของคำสั่งในหน่วยมิลลิวินาทีที่เกินกว่านี้จะถูกบันทึก 0 จะบันทึกทุกคำสั่ง ค่าเริ่มต้นคือ -1 ปิดการบันทึก ข้อมูลเพิ่มเติม
  • rds.force_ssl = 1 - บังคับใช้ SSL สำหรับการเชื่อมต่อทั้งหมด ค่าเริ่มต้นคือ 0 (ปิด) บังคับการเข้ารหัสระหว่างทาง ข้อมูลเพิ่มเติม
  • log_lock_waits = 1 - บันทึกการรอคอยล็อกนาน ค่าเริ่มต้นคือปิด ข้อมูลเพิ่มเติม
  • max_locks_per_transaction - กำหนดจำนวนล็อกสูงสุดต่อธุรกรรม ค่าเริ่มต้นคือ 64 ข้อมูลเพิ่มเติม
  • shared_preload_libraries = pg_stat_statements,pgaudit - ระบุไลบรารีที่จะแชร์และโหลดล่วงหน้าเข้าไปในหน่วยความจำเซิร์ฟเวอร์ ค่าเริ่มต้นคือสตริงว่าง ข้อมูลเพิ่มเติม: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Extensions.html
  • idle_in_transaction_session_timeout = 300000 - ยุติ session ที่มีธุรกรรมเปิดและไม่มีการใช้งานเกินเวลาที่กำหนดในหน่วยมิลลิวินาที ค่าเริ่มต้นคือ 0 (ปิด) ข้อมูลเพิ่มเติม
  • log_autovacuum_min_duration = 60000 - กำหนดเวลาการทำงานขั้นต่ำที่เกินกว่านี้การทำงาน autovacuum จะถูกบันทึก ค่าเริ่มต้นคือ -1 ปิดการบันทึก ข้อมูลเพิ่มเติม

การสร้างจากคอนโซล ลิงก์ไปยังหัวข้อ

สมมติว่าความต้องการเร่งด่วนและขาดเวลาและความรู้บังคับให้เราใช้คอนโซล จะเลือกอะไร คลิกตรงไหน?

  1. เลือกเทมเพลต production เสมอ กำหนด DB cluster identifier ซึ่งจะใช้ใน connection string ใช้ชื่อผู้ใช้ root ใดก็ได้ ตามค่าเริ่มต้นสำหรับ AWS Secrets Manager Integration ซึ่งจะเพิ่มการหมุนรหัสผ่าน root อัตโนมัติ

Image

  1. ขนาดและพื้นที่จัดเก็บ ใช้ Aurora Standard และคลาส T ใดก็ได้เพื่อปรับงบประมาณให้เหมาะสม คุณสามารถเปลี่ยนแปลงได้ภายหลัง

Image

  1. Serverless v2 ถ้าคุณใช้ไม่บ่อยและไม่รู้จักโหลด คุณสามารถใช้ serverless v2 ได้ มันจะปรับขนาดอัตโนมัติ จาก 0 ถึงสูงสุด แพงกว่ามากแต่ยืดหยุ่นมาก

Image

  1. การเชื่อมต่อ ระวัง! อย่าใช้ default VPC ที่นี่ การคลิกสร้าง VPC แยกต่างหากใช้เวลาประมาณ 5-10 นาที และหลังจากสร้างฐานข้อมูลแล้วคุณไม่สามารถเปลี่ยน VPC ได้ เป็นจุดสำคัญ การย้ายฐานข้อมูล production อาจใช้เวลาหลายชั่วโมง เช่นเดียวกับการเข้าถึงแบบสาธารณะ หลีกเลี่ยง ใช้ VPNs, Direct Connect, Balancers และ RDS Proxy ใช้เวลาศึกษาว่ามีอะไรเข้าถึงฐานข้อมูลจากภายนอกบ้าง

Image

  1. การเชื่อมต่ออีกครั้ง อย่าใช้ security group (ไฟร์วอลล์) เริ่มต้น สร้างอันใหม่ แม้ว่ากฎจะไม่ดีหรือผิดพลาด ก็ยังดีกว่ามี entity แยกที่ใช้เฉพาะกับฐานข้อมูลนี้

Image

  1. พารามิเตอร์ฐานข้อมูล เลือกกลุ่มพารามิเตอร์แบบกำหนดเองที่สร้างไว้ข้างต้น ไม่ใช่ค่าเริ่มต้น สามารถเปลี่ยนแปลงได้แต่ต้องรีบูต instance/cluster

  2. การเข้ารหัสข้อมูลขณะพัก สร้าง KMS key แบบ multi-region แยกต่างหากเสมอ อย่างน้อยหนึ่ง Customer Managed KMS key จะช่วยได้มาก เราไม่สามารถเปลี่ยนพารามิเตอร์การเข้ารหัสหลังจากสร้างฐานข้อมูลแล้ว เช่นเดียวกับ performance insights

Image

การสร้างจาก Terraform ลิงก์ไปยังหัวข้อ

เหมือนกับข้างต้น แต่เป็นโค้ด ไม่จำเป็นต้องอธิบายซ้ำ โค้ดนี้มีให้แล้ว https://github.com/terraform-aws-modules/terraform-aws-rds-aurora/blob/master/examples/postgresql/main.tf

provider "aws" {
  region = local.region
}

data "aws_availability_zones" "available" {}

locals {
  name   = "ex-${basename(path.cwd)}"
  region = "eu-west-1"

  vpc_cidr = "10.0.0.0/16"
  azs      = slice(data.aws_availability_zones.available.names, 0, 3)

  tags = {
    Example    = local.name
  }
}

################################################################################
# RDS Aurora Module
################################################################################

module "aurora" {
  source  = "terraform-aws-modules/rds-aurora/aws"
  version = "~> 9.0"

  name            = local.name
  engine          = "aurora-postgresql"
  engine_version  = "16.3"
  master_username = "pgroot"
  storage_encrypted = true
  kms_key_id        = module.kms.key_id
  instances = {
    1 = {
      instance_class          = "db.t4.medium"
    }
  }
  vpc_id               = module.vpc.vpc_id
  db_subnet_group_name = module.vpc.database_subnet_group_name
  security_group_rules = {
    vpc_ingress = {
      cidr_blocks = module.vpc.private_subnets_cidr_blocks
    }
  }

  apply_immediately   = true

  engine_lifecycle_support = "open-source-rds-extended-support-disabled"

  create_db_cluster_parameter_group      = true
  db_cluster_parameter_group_name        = local.name
  db_cluster_parameter_group_family      = "aurora-postgresql16"
  db_cluster_parameter_group_description = "${local.name} example cluster parameter group"
  db_cluster_parameter_group_parameters = [
    {
      name         = "log_min_duration_statement"
      value        = 4000
      apply_method = "immediate"
      }, {
      name         = "rds.force_ssl"
      value        = 1
      apply_method = "immediate"
      }, {
      name         = "log_lock_waits"
      value        = "1"
      apply_method = "immediate"
      }, {
      name         = "max_locks_per_transaction"
      value        = "1000"
      apply_method = "pending-reboot"
      }, {
      name         = "shared_preload_libraries"
      value        = "pg_stat_statements,pgaudit"
      apply_method = "pending-reboot"
      }, {  
      name         = "idle_in_transaction_session_timeout"
      value        = "300000" # Max 5 minutes per transaction
      apply_method = "immediate"
      }, {
      name         = "log_autovacuum_min_duration"
      value        = "60000" # 1m, minimum execution time above which autovacuum actions will be logged
      apply_method = "immediate"
    }
  ]

  create_db_parameter_group      = true
  db_parameter_group_name        = local.name
  db_parameter_group_family      = "aurora-postgresql16"
  db_parameter_group_description = "${local.name} example DB parameter group"
  db_parameter_group_parameters = [
    {
      name         = "log_min_duration_statement"
      value        = 4000
      apply_method = "immediate"
    }
  ]

  enabled_cloudwatch_logs_exports = ["postgresql"]
  create_cloudwatch_log_group     = true

  cloudwatch_log_group_tags = {
    Sensitivity = "high"
  }

  tags = local.tags
}

################################################################################
# Supporting Resources
################################################################################

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "~> 5.0"

  name = local.name
  cidr = local.vpc_cidr

  azs              = local.azs
  public_subnets   = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)]
  private_subnets  = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)]
  database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)]

  tags = local.tags
}

module "kms" {
  source  = "terraform-aws-modules/kms/aws"
  version = "~> 2.0"

  deletion_window_in_days = 7
  description             = "KMS key for ${local.name} cluster activity stream."
  enable_key_rotation     = true
  is_enabled              = true
  key_usage               = "ENCRYPT_DECRYPT"

  aliases = [local.name]

  tags = local.tags
}

ต่อไป? ตัวเลือกอื่นๆ? ลิงก์ไปยังหัวข้อ

วันนี้เราครอบคลุม PostgreSQL บน RDS Aurora แล้ว แต่ยังมีตัวเลือกอื่นๆ อีกมากมาย ถูกที่สุดคือเก็บข้อมูลดิบเป็นวัตถุใน S3 ทนทานและมีการทำสำเนา แต่ช้าได้ Key-value stores อย่าง DynamoDB เร็ว แต่ไม่ใช่ฐานข้อมูลเชิงสัมพันธ์ สิ่งสำคัญที่สุดคือเริ่มจากปัญหาแล้วเลือกเครื่องมือที่เหมาะสมกับมัน