2 คะแนน โดย GN⁺ 2024-01-11 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • ต้นตอของความซับซ้อนฝั่งแบ็กเอนด์ไม่ได้อยู่ที่ข้อบกพร่องของผลิตภัณฑ์ใดผลิตภัณฑ์หนึ่ง แต่เป็นเพราะ โครงสร้างเชิงแนวคิด ที่ฐานข้อมูลยึดถือมายาวนานยังคงจำกัดการออกแบบแอปพลิเคชันอยู่
  • ฐานข้อมูลทำงานเสมือน สถานะส่วนกลางที่เปลี่ยนแปลงได้ และผลักภาระของโมเดลข้อมูลแบบตายตัว, สคีมาที่จำกัด, และความตึงเครียดระหว่างการทำ normalization กับ denormalization ไปให้ผู้พัฒนารับมือเอง
  • ทางเลือกที่เสนอคือการผสาน event sourcing กับ materialized views เพื่อแยกข้อมูลต้นทางออกจากมุมมองแบบดัชนี และปฏิบัติต่อดัชนีในฐานะโครงสร้างข้อมูลแบบคงทนแทนที่จะเป็น data model
  • Rama ของ Red Planet Labs รวม depots, ETL, PStates, query topologies เข้าด้วยกันเป็นแพลตฟอร์มเดียวสำหรับการเก็บข้อมูล, ประมวลผล, ทำดัชนี, คิวรี, การดีพลอย และการมอนิเตอร์
  • ในกรณีศึกษาการเขียน Mastodon ใหม่ที่ระดับขนาดของ Twitter, Rama ใช้เวลา 10k บรรทัดโค้ดและ 9 คน-เดือน ขณะที่ผลิตภัณฑ์ฝั่งผู้ใช้ของ Twitter ที่นำมาเทียบกันใช้ 1M บรรทัดและราว 200 คน-ปี

จุดเริ่มต้นของความซับซ้อนในฐานข้อมูล

  • แก่นของปัญหาไม่ได้อยู่ที่ API, ความยากในการปฏิบัติการ, หรือข้อจำกัดเฉพาะหน้าของผลิตภัณฑ์ฐานข้อมูลใด ๆ แต่คือ โครงสร้างเชิงแนวคิดแบบหมู่คณะ ที่ยังคงสืบทอดมาจนถึงปัจจุบัน
  • ปัญหาของแนวทางเดิมจะเห็นชัดเมื่อมีวิธีที่ดีกว่าเกิดขึ้น และข้อเสนอในที่นี้คือการผสาน event sourcing กับ materialized views

ฐานข้อมูลในฐานะสถานะส่วนกลางที่เปลี่ยนแปลงได้

  • โปรแกรมเมอร์ถูกสอนให้ลดการใช้ตัวแปรส่วนกลางให้น้อยที่สุด แต่ฐานข้อมูลเองก็โดยเนื้อแท้คือ สถานะส่วนกลางที่เปลี่ยนแปลงได้
  • ฐานข้อมูลมีแง่มุมที่จัดการยากกว่าตัวแปรส่วนกลางทั่วไป
    • ปฏิสัมพันธ์กระจายอยู่ในหลายระบบ จึงยากต่อการอนุมานสถานะ
    • สถานะมีความคงทน ดังนั้นแม้จะแก้บั๊กแล้ว ข้อมูลที่เสียหายก็ไม่ได้ฟื้นกลับเองโดยอัตโนมัติ
    • บางครั้งยากที่จะระบุขอบเขตของความเสียหายอย่างแม่นยำ หรือแก้ไขให้สมบูรณ์ได้ทั้งหมด
    • การย้อนกลับไปใช้แบ็กอัปหรือรวมบางส่วนจากแบ็กอัปไม่ใช่ทางออกที่ดีที่สุดเสมอไป
  • หากใช้ event sourcing และ materialized views ก็สามารถคำนวณมุมมองใหม่จาก source log ได้ ทำให้มีโอกาสแก้ไขสถานะดัชนีที่เสียหายได้

ข้อจำกัดของโมเดลข้อมูลแบบตายตัว

  • ฐานข้อมูลถูกออกแบบโดยมี data model เป็นศูนย์กลาง เช่น key/value, document, relational, column-oriented, graph
  • เนื่องจาก data model แบบเดียวรองรับทุก use case ได้ยาก องค์กรมักต้องใช้ฐานข้อมูลหลายแบบร่วมกัน
  • นามธรรมของดัชนีที่ทั่วไปกว่านั้นไม่ใช่ data model แต่คือ โครงสร้างข้อมูล
    • Key/value: map
    • Document: map of maps
    • Relational: map of maps, ส่วน secondary indexes คือ map เพิ่มเติม
    • Column-oriented: map of sorted maps
  • โครงสร้างข้อมูลแบบคงทนสามารถเก็บบนดิสก์และขยายขนาดได้มาก รวมถึงใช้แทนโครงสร้างข้อมูลแบบซ้อนกันได้
  • หากระบุดัชนีเป็นการประกอบกันของโครงสร้างข้อมูล ก็จะสร้างได้ไม่เฉพาะ data model แบบเดิม แต่รวมถึงรูปแบบดัชนีที่หลากหลายกว่าเดิมด้วย
  • หากสามารถปรับรูปแบบของสตอเรจให้เข้ากับ domain model แทนที่จะบิด domain model ให้เข้ากับฐานข้อมูล ความซับซ้อนพื้นฐานก็จะลดลง

ความตึงเครียดระหว่าง normalization และ denormalization

  • ผู้ใช้ฐานข้อมูลเชิงสัมพันธ์ย่อมต้องเผชิญกับทางเลือกระหว่าง normalization กับ denormalization
  • การจัดเก็บแบบ normalized สร้างแหล่งความจริงที่ชัดเจนและลดโอกาสข้อมูลไม่สอดคล้องกัน แต่ก็อาจทำให้มี join มากขึ้นและต้นทุนของคิวรีสูงขึ้น
  • หากเพื่อประสิทธิภาพแล้วเก็บข้อมูลเดียวกันไว้หลายรูปแบบ ก็อาจเกิดข้อมูลไม่สอดคล้องกันได้เมื่อมีบั๊ก
  • สถาปัตยกรรม RDBMS รวมทั้งแหล่งความจริงและสตอเรจดัชนีสำหรับคิวรีเร็วไว้ใน datastore เดียวกัน
  • แนวทางแก้คือการแยกสองบทบาทนี้ออกจากกัน
    • ระบบย่อยหนึ่งใช้แทน แหล่งความจริง
    • อีกระบบย่อยหนึ่ง materialize สตอเรจดัชนีได้ตามต้องการจากแหล่งนั้น
    • หากระบบที่สองคำนวณดัชนีใหม่จากข้อมูลต้นทางได้ ก็สามารถแก้ไขความไม่สอดคล้องกันได้

สคีมาที่จำกัดและการแทนโดเมน

  • ฐานข้อมูลแต่ละผลิตภัณฑ์แตกต่างกันมากในเรื่องชนิดของค่าที่จัดเก็บได้
    • บางฐานข้อมูลยอมรับได้แค่ blob เช่น byte array
    • บางฐานข้อมูลรองรับหลายชนิด เช่น จำนวนเต็ม, จำนวนทศนิยม, สตริง, วันที่ เป็นต้น
  • การจัดเก็บให้อยู่ในรูป การแทนแบบชั้นหนึ่ง ที่สามารถคิวรีหรือ aggregate ข้อมูลซ้อนภายใน domain object ได้โดยตรงนั้นพบได้ไม่บ่อย
  • ภาษา implementation ของฐานข้อมูลกับภาษาแอปพลิเคชันมักต่างกัน ทำให้ทำงานร่วมกันได้ยาก และส่วนขยายอย่าง protobuf extension สำหรับ Postgres ก็ทั้งยุ่งยากและมีข้อจำกัด
  • ORM ช่วยแมปการแทนโดเมนกับการแทนในฐานข้อมูล แต่ abstraction อาจรั่วและก่อปัญหาได้
  • หากต้องทำดัชนีข้อมูลในรูปแบบที่ต่างจากการแทนโดเมนที่เหมาะสมที่สุด ก็จำเป็นต้องมีโค้ดตัวแปลง และประเภทคิวรีที่ทำได้อย่างมีประสิทธิภาพก็อาจถูกจำกัดไปด้วย

การดีพลอยที่ซับซ้อนและโมเดล à la carte

  • แบ็กเอนด์ที่สมบูรณ์ไม่ได้ประกอบด้วยแค่ฐานข้อมูล แต่ต้องมีทั้งฐานข้อมูล, ระบบประมวลผล, เครื่องมือมอนิเตอร์, ตัวตั้งเวลา และเครื่องมืออื่น ๆ ร่วมกัน
  • แบ็กเอนด์ขนาดใหญ่อาจต้องประกอบจากเครื่องมือหลายสิบตัว และการอัปเดตแอปพลิเคชันก็ขยายกลายเป็นการประสาน migration, อัปเดตโค้ด, และเปลี่ยนแปลงโครงสร้างพื้นฐาน
  • ความพร้อมสำหรับโปรดักชันต้องมี telemetry ที่เพียงพอ แต่แต่ละเครื่องมือก็เก็บข้อมูลต่างวิธีกัน ทำให้การรวมเป็นแดชบอร์ดมอนิเตอร์เดียวกลายเป็นงานวิศวกรรมอีกชิ้นหนึ่ง
  • แนวทางพัฒนาที่ครองตลาดในปัจจุบันใกล้เคียงกับ โมเดล à la carte ที่เลือกเครื่องมือที่ดีที่สุดสำหรับแต่ละส่วนของสถาปัตยกรรมแล้วนำมาต่อกัน
  • งานในการทำให้เครื่องมือที่ออกแบบแยกกันทำงานร่วมกันได้มีขนาดใหญ่ในตัวเอง และเพราะ data model แบบตายตัวกับสคีมาที่จำกัด จึงมักกลายเป็นว่าต้องปรับแอปพลิเคชันให้เข้ากับเครื่องมือ มากกว่าจะปรับเครื่องมือให้เข้ากับแอปพลิเคชัน
  • โมเดล à la carte ฝังรากได้เพราะยังไม่มีโมเดลที่มีความเป็นเอกภาพสำหรับการประกอบแบ็กเอนด์ และในโมเดลที่มีความเป็นเอกภาพนั้นจะมีช่องทางสำหรับ abstraction, automation, และการนำกลับมาใช้ใหม่มากขึ้น

โมเดลแบบเรียบง่ายสำหรับมองแบ็กเอนด์

  • หน้าที่หลักของแบ็กเอนด์คือ รับข้อมูลใหม่ และ ตอบคำถามเกี่ยวกับข้อมูลนั้น
  • คิวรีที่ทั่วไปที่สุดสามารถเขียนเป็นการรันฟังก์ชันกับข้อมูลทั้งหมดที่แบ็กเอนด์ได้รับ
    • query = function(all data)
  • ในโลกจริง ชุดข้อมูลอาจมีขนาด 10PB และเวลาตอบคิวรีอาจต้องอยู่ในระดับมิลลิวินาที ดังนั้นระบบที่ใช้งานได้จริงจึงต้องมีดัชนี
  • เมื่อเพิ่มดัชนีเข้าไป โมเดลจะเป็นดังนี้
    • indexes = function(data)
    • query = function(indexes)
  • แบ็กเอนด์แบบเดิมมักนำองค์ประกอบของโมเดลนี้ไปแยกทำด้วยเครื่องมือเฉพาะทางหลายตัว
    • แบ็กเอนด์ที่ใช้ RDBMS จะใช้ RDBMS สำหรับทั้งข้อมูลและดัชนี และอาจเพิ่มฐานข้อมูลแยกอย่าง ElasticSearch เพื่อทำดัชนีเพิ่มเติม
    • การคำนวณมักอยู่ใน handler ของ API server หรือในงานเบื้องหลังที่ขับเคลื่อนด้วยคิวและเวิร์กเกอร์
    • แบ็กเอนด์ขนาดใหญ่อาจประกอบเครื่องมืออย่าง Cassandra, MongoDB, Neo4j, Kafka, Hadoop, Storm, Kafka Streams เข้าด้วยกัน
  • จึงนำไปสู่ข้อสรุปว่า หากมีเครื่องมือที่ทำทุกองค์ประกอบเหล่านี้ได้อย่างบูรณาการและใช้งานได้ทั่วไป ก็จะหลีกเลี่ยงความซับซ้อนก่อนหน้าได้

โครงสร้างของ Rama และกรณีศึกษา Mastodon

  • Rama คือแพลตฟอร์มพัฒนาแบ็กเอนด์ที่ออกแบบบนหลักการเหล่านี้
  • Red Planet Labs เปิดตัว Rama เมื่อวันที่ 15 สิงหาคม พร้อมแท็กไลน์ “the 100x development platform”
  • ในฐานะกรณีศึกษาการลดต้นทุน บริษัทนำเสนอการ เขียน Mastodon ใหม่ให้รองรับระดับขนาดของ Twitter
    • บอต 100M ตัวโพสต์รวมกัน 3,500 ครั้งต่อวินาที
    • ค่า fanout เฉลี่ยอยู่ที่ 403
    • มีการเปรียบเทียบว่าผลิตภัณฑ์ฝั่งผู้ใช้ที่เทียบเท่ากันของ Twitter ใช้ 1M บรรทัดโค้ดและราว 200 คน-ปี
    • ส่วน implementation บน Rama ใช้ 10k บรรทัดและ 9 คน-เดือน
    • implementation นี้เป็น โอเพนซอร์ส และถูกระบุว่า complete, high-performance, production-ready
  • มีการเปรียบเทียบว่า Twitter สร้างฐานข้อมูลเฉพาะทางขึ้นเอง เช่น social graph database และ in-memory timeline database เพื่อให้ถึงระดับสเกลดังกล่าว และยังมีการดีพลอยที่ซับซ้อนจนแม้แต่การตั้งค่า Puppet ก็มี มากกว่า 1M บรรทัด
  • ส่วน implementation ที่ใช้ Rama ระบุว่าไม่ได้สร้างอินฟราสตรักเจอร์เฉพาะสำหรับแต่ละปัญหาย่อยใหม่ แต่ใช้การประกอบ primitive ของ Rama เพื่อแก้ปัญหาด้านประสิทธิภาพและการขยายขนาดที่คล้ายกัน
  • performance numbers ของ implementation Mastodon ถูกระบุว่าทัดเทียมหรือดีกว่าค่าของ Twitter

โมเดลการเขียนโปรแกรมของ Rama

  • แนวคิดของ Rama สอดคล้องโดยตรงกับโมเดลแบ็กเอนด์ที่อธิบายไว้ก่อนหน้า
    • Depots: distributed log สำหรับเก็บข้อมูลใดก็ได้ ตรงกับ data
    • PStates: ย่อมาจาก partitioned state และตรงกับดัชนี
    • ETLs: ตรงกับ function(data)
    • Queries: ตรงกับ function(indexes)
  • PStates สามารถสร้างได้ตามต้องการในรูปการผสมกันของโครงสร้างข้อมูลแบบคงทน
  • ETL และ query ถูกเขียนด้วย dataflow API ที่มีความสามารถเทียบเท่า Turing-complete และสามารถกระจายการคำนวณได้
  • Rama มีเอกสารสอนใช้งาน Java API และยังมี Clojure API ด้วย

วิธีที่ Rama ลดความซับซ้อนของฐานข้อมูล

  • PStates ของ Rama ทำหน้าที่คล้ายฐานข้อมูล แต่สามารถเขียนได้จาก ETL topology ที่เป็นเจ้าของ PState นั้นเท่านั้น
    • เพราะการเขียนทั้งหมดอยู่ในโค้ด ETL เดียวกัน จึงอนุมานสถานะได้ง่ายขึ้น
    • PStates ทำงานเป็น materialized views บน event sourcing log
    • เนื่องจาก depot data คือแหล่งความจริง PState จึงคำนวณใหม่ได้
  • ข้อจำกัดของ data model ถูกจัดการด้วยวิธีระบุ PStates เป็นโครงสร้างข้อมูล
    • implementation ของ Mastodon ใช้ PStates 33 ตัว แม้จะมีเพียง profiles, statuses, timelines
    • PState บางตัวรองรับได้ 10 use cases ขณะที่บางตัวรองรับเพียง use case เดียว
  • PStates มีคุณสมบัติ durable, partitioned, incrementally replicated
    • incremental replication หมายถึง เมื่อ leader partition ล้มเหลว จะมี partition อื่นพร้อม takeover
    • สิ่งที่มองเห็นได้จาก leader ปัจจุบันจะถูกรับประกันว่ายังมองเห็นได้ใน leader ถัดไป
  • ปัญหา normalization กับ denormalization ถูกจัดการด้วยการแยก depots และ PStates ออกจากกันอย่างชัดเจน
  • ปัญหาสคีมาที่จำกัดถูกบรรเทาด้วยการใช้การแทนโดเมนได้โดยตรง
    • โครงสร้างข้อมูลทั่วไปอย่าง hash map, list
    • Protocol Buffers
    • นิยามอ็อบเจ็กต์แบบซ้อนกัน
    • สำหรับชนิดที่ Rama ไม่รู้จัก สามารถจัดการได้ด้วยการลงทะเบียน custom serializer

การดีพลอย, การบูรณาการ, การมอนิเตอร์

  • แอปพลิเคชัน Rama ถูกเรียกว่า modules โดยหนึ่ง module สามารถมี depots, ETLs, PStates, และ query topologies ได้หลายตัว
  • Rama มีกลไกในตัวสำหรับการดีพลอย, อัปเดต, และขยาย module ซึ่งระบุว่าสามารถทำแต่ละอย่างได้ด้วย one-liner บนเทอร์มินัล
  • Rama ไม่ใช่เครื่องมือแบบ “all or nothing” แต่ถูกออกแบบให้ เชื่อมต่อ กับระบบอื่นได้ง่าย จึงสามารถค่อย ๆ นำไปใช้ในสถาปัตยกรรมเดิมได้
  • เพราะเป็นแพลตฟอร์มแบบบูรณาการ จึงทำการมอนิเตอร์ภายในตัวเองด้วย
    • การเก็บข้อมูลมอนิเตอร์
    • การประมวลผล
    • การทำดัชนี
    • การแสดงผล
  • cluster UI telemetry ใช้เพื่อทำความเข้าใจประสิทธิภาพของ module, ตรวจจับและวินิจฉัยปัญหา, และตัดสินใจจังหวะในการขยายระบบ

การเรียนรู้และเส้นทางการนำไปใช้

  • มีการแนะนำทรัพยากรต่อไปนี้สำหรับผู้ที่ต้องการเรียนรู้ Rama เพิ่มเติม
  • หากต้องการใช้ Rama เพื่อสร้างฟีเจอร์ใหม่ในโปรดักชัน, ขยายระบบเดิม, หรือทำให้อินฟราสตรักเจอร์เรียบง่ายขึ้น สามารถสมัคร private beta ได้
  • ระบุว่าผู้ใช้ private beta จะได้รับการช่วยเหลือไม่เพียงแค่การเรียนรู้ Rama แต่รวมถึงการเขียนโค้ด, การปรับแต่งประสิทธิภาพ, และการทดสอบร่วมกันด้วย

1 ความคิดเห็น

 
GN⁺ 2024-01-11
ความคิดเห็นจาก Hacker News
  • “เดี๋ยวจะอธิบายทีหลัง แต่วิธีที่ดีกว่าคือ event sourcing กับ materialized views” งั้นสุดท้ายคำตอบก็คือ เพิ่มความซับซ้อน สินะ ก็แน่อยู่แล้ว

    • ถ้าทำให้ถูกต้อง สถาปัตยกรรมแบ็กเอนด์กลับจะเรียบง่ายขึ้นมาก แอประดับไม่ใหญ่มากก็มักใช้หลายฐานข้อมูลอย่าง Postgres และ ElasticSearch พร้อมมีคิวงานเบื้องหลังกับ worker อยู่แล้ว
      การทำ Mastodon ระดับสเกล Twitter ที่เราสร้างคือกรณีตัวอย่างตรง ๆ มันใช้โค้ดน้อยกว่าโค้ดที่ Twitter ต้องเขียนเพื่อทำฟังก์ชันแบบเดียวกันในระดับสเกลเดียวกันถึง 100 เท่าตามตัวอักษร และยังน้อยกว่า implementation ทางการของ Mastodon มากกว่า 40% ไม่ใช่เพราะใช้เครื่องมือเดิมเป็นครั้งที่สองเลยออกแบบได้ดีกว่า แต่เพราะมันสร้างบน abstraction ที่ดีกว่าอย่างเป็นรากฐาน
    • ความซับซ้อนไม่ได้หายไป แต่แค่ ย้ายไปอยู่ที่อื่น เท่านั้น สำหรับงานจำนวนมาก trade-off ของวิธีนี้อาจแย่ก็ได้
      แต่เมื่อเกินสเกลระดับหนึ่งไป ทุกอย่างก็จะกลายเป็นปัญหาด้าน data engineering และเมื่อมองในบริบทของทั้งระบบ วิธีนี้ก็อาจกลายเป็นคำตอบที่เรียบง่ายกว่าโดยเปรียบเทียบ คำแนะนำว่า “ก็ใช้ mySQL/SQLite/Postgres ไปสิ” นั้นยอดเยี่ยม จนกว่าจะถึงจุดที่มันใช้ไม่ได้อีกต่อไป
    • ซับซ้อนขึ้นอีกเหรอ? ผู้เขียนทำให้มันง่ายมาก แค่ใช้ผลิตภัณฑ์ของตัวเอง Rama ก็พอ
    • ทุกบริษัทที่ฉันเคยทำงานมา event sourcing + materialized views นำไปสู่ความโกลาหลอย่างหนัก บั๊กมากขึ้น และเหตุขัดข้องที่ยาวนานขึ้น ส่วนวิธีที่ง่ายกว่าอย่าง MySQL หรือ PostGres หรือ Redis/DynamoDB กลับทำงานได้ดีกว่าทั้งหมด
      ฉันเชื่ออย่างจริงใจว่าถ้าบทความ event sourcing ต้นฉบับของ Martin Fowler ไม่เคยถูกเขียนขึ้นมาเลย มันจะดีกับทุกคนมากกว่า ใน 99% ของกรณีฉันมองว่ามันเป็นไอเดียที่ไม่ดี
    • ถ้าโดเมนของโปรแกรมจำเป็นต้องมีความซับซ้อนโดยเนื้อแท้ระดับ X ยังไงคุณก็ต้องลงมือทำความซับซ้อนนั้นอยู่ดี จะฝากให้ โค้ดของคนอื่น ที่ถูกเขียนและพิสูจน์แล้วในงานจริงจัดการให้ก็ได้ หรือจะสร้างขึ้นมาใหม่เองก็ได้ ซึ่งอย่างหลังอาจใช้เวลามากและผลลัพธ์แย่กว่า ไม่มีอาหารกลางวันฟรี
  • ฉันอาจพลาดอะไรไป แต่ดูเหมือนบทความนี้จะข้ามแนวคิดอย่าง concurrency, isolation, constraints ไปทั้งหมด และสิ่งที่เรียกว่า “query topology” ก็ดูไม่ declarative แถมเหมือนโยนภาระเรื่อง query planning/optimization ไปให้คนเขียนเอง แบบนี้ยังนับว่าเป็นประสบการณ์นักพัฒนาที่ดีกว่าจริงหรือ?

    • เรื่องพวกนี้อธิบายไว้ครบในเอกสารแล้ว บทความนี้พูดถึงความซับซ้อนของการพัฒนาแบ็กเอนด์และ Rama จัดการกับมันอย่างไร ไม่ได้ตั้งใจอธิบายทุกแง่มุมของ Rama แบบครบถ้วน เพราะถ้าจะอธิบายทั้งหมดมันจะยาวเกินไป ถ้าลองศึกษา Rama ต่อ คุณจะเห็นว่าคุณสมบัติและการรับประกันของมันแข็งแกร่งมาก
      และใช่ แนวทางการ query ของ Rama เหนือกว่ามากจริง ๆ ที่ต้องมี query planner ซับซ้อน ส่วนใหญ่เกิดจากข้อจำกัดของวิธีทำดัชนีข้อมูล โดยเฉพาะความตึงเครียดระหว่าง normalization กับ denormalization ใน Rama นั้นสามารถ materialize หลาย view ที่เตรียมไว้ในรูปแบบที่การ query ต้องใช้ได้อย่างมั่นคง
      มีทิวทอเรียลสำหรับแนะนำแนวคิดของ Rama แบบค่อยเป็นค่อยไปอยู่ที่นี่: https://redplanetlabs.com/docs/~/tutorial1.html
  • สำหรับคำกล่าวที่ว่า “ไม่มี data model แบบเดียวที่รองรับได้ทุก use case” ในทางทฤษฎีแล้ว ไม่มีโดเมนหรือชุดโดเมนจำกัดใดที่ไม่สามารถจำลองได้อย่างแม่นยำด้วยทูเพิลของสิ่งต่าง ๆ และความสัมพันธ์
    ในทางปฏิบัติ ขอบเขตของ database/schema ใด ๆ มักถูกจำกัดอยู่ในธุรกิจเดียวหรือขอบเขตของปัญหาหนึ่ง แต่ตราบใดที่ type ไม่ซ้อนทับกันอย่างไม่เหมาะสม ก็ไม่ใช่ปัญหาใหญ่อะไร แค่ระวังเรื่องชื่อ ก็สามารถใส่ทั้งร้านค้าปลีกบนเว็บกับบริษัทประกันไว้ใน schema เดียวกันแล้วให้ทำงานได้ดีพอ
    การใส่ทุกอย่างไว้ใน database เดียวอย่างถูกต้องคือ พลังวิเศษ เหตุผลหลักที่ฉันยืนยันเรื่องนี้หนักมากคือเพื่อหลีกเลี่ยง distributed transaction ที่คร่อมหลาย data store ถ้าธุรกิจทั้งหมดเกิดขึ้นภายใน transactional system เดียว semantics จะเรียบง่ายลงอย่างมาก

    • เห็นด้วยเป็นพิเศษกับคำว่า “การใส่ทุกอย่างไว้ใน database เดียวคือพลังวิเศษ”
      เมื่อคนเริ่มเขียนข้อมูลจริง ๆ DB server ใหญ่ราคาเป็นล้านดอลลาร์กลับถูกกว่าการมี database ราคาถูกจำนวนมากซ้ำซ้อนกันมาก นักพัฒนา นักวิเคราะห์ หรือผู้บริหาร ต่างก็ประหยัดเวลาได้ทั้งหมด อาจยกเว้น DBA บางคน
    • database ขนาดใหญ่ไม่ใช่เรื่องใหม่ ถ้าแค่นั้นคือทั้งหมด คนก็คงทำแบบนั้นต่อเนื่องมาตลอด 40 ปีที่ผ่านมาแล้ว แต่ความจริงคือมันไม่ได้เวิร์กเสมอไป และบางครั้งก็แย่มากอยู่บ่อย ๆ
      ต่อให้ในทางทฤษฎีนั่นคือทั้งหมด ปัญหาต่อเนื่องอีกอย่างก็คือการ implementation ทุกวันนี้นักพัฒนาส่วนใหญ่ไม่ค่อยเข้าใจว่า database ทำงานอย่างไรและควรใช้อย่างไร จึงใช้งานมันได้แย่มาก เลยพยายามหนีข้อเท็จจริงนี้ด้วยการสร้าง database แบบใหม่อย่าง NoSQL และพยายามใช้หัวให้น้อยลงแต่เขียน glue code ให้มากขึ้น ซึ่งก็พิสูจน์แล้วว่าให้ผลลัพธ์ที่แย่มาก
      อีกไม่นานกระแสก็จะเปลี่ยนอีก และ “แค่ database ใหญ่ตัวเดียว” ก็จะหลุดเทรนด์อีกครั้ง พร้อมมี paradigm แห่ง “ความเรียบง่าย” แบบใหม่ออกมา เหมือนยุค microservices ที่ “database ใหญ่ตัวเดียว” อาจถูกมองว่าซับซ้อนกว่า “database เล็กจำนวนมาก” ถ้าไม่เข้าใจประวัติศาสตร์ ก็หนีไม่พ้นการทำซ้ำมัน
    • การบอกว่าสามารถจำลอง use case บางอย่างด้วยทูเพิลและความสัมพันธ์ได้ ไม่ได้แปลว่า database จะตอบสนอง ข้อกำหนดด้านประสิทธิภาพ ของ use case นั้นได้ ถ้าทำตามข้อกำหนดด้านประสิทธิภาพไม่ได้ ก็ถือว่าไม่ได้รองรับ use case นั้น
      มันก็เหมือนในการเขียนโปรแกรมทั่วไปที่ไม่มีโครงสร้างข้อมูลแบบเดียว หรือชุดผสมของโครงสร้างข้อมูล ที่รองรับได้ทุก use case บางครั้งต้องใช้ map บางครั้งต้องใช้ list, set, แบบผสม หรือแม้แต่อะไรที่ต่างไปโดยสิ้นเชิง
    • เห็นด้วยกับคำว่า “การใส่ทุกอย่างไว้ใน database เดียวคือพลังวิเศษ” บริษัทก่อนหน้าของฉันใช้ microservices แบบคาร์โกคัลต์ ที่มี DB แยกตามแต่ละแอป ทำให้ซับซ้อนและแพงโดยไม่จำเป็นโดยไม่มีประโยชน์ทางธุรกิจอะไรเลย แน่นอนว่ามันอาจมีประโยชน์ต่อการแต่งเรซูเม่ แต่ไม่ควรทำให้ระบบซับซ้อนจนกว่าจะถูกบังคับว่าจำเป็นจริง ๆ
    • ฟังดูเหมือนความฝันและเป็นแนวคิดที่สวยงามมาก แต่ในความเป็นจริงมันไม่เวิร์ก มีใครทำสำเร็จจริงหรือ? ถ้ามองแบบสุดโต่ง ก็เหมือนกำลังบอกว่าโลกทั้งโลกควรมี integrated database เพียงหนึ่งเดียวและระบบสิทธิ์ผู้ใช้เพียงชุดเดียว
      แน่นอนว่าโครงสร้างข้อมูลมีความหลากหลาย ต้องการประสิทธิภาพ และมันจะกลายเป็นคอขวดที่สำคัญมากจนคนทั่วไปแตะต้องไม่ได้ อีกทั้งทุกการเปลี่ยนแปลงต้องปลอดภัยอย่างยิ่ง ยังมีเรื่องความปลอดภัยด้วย ถ้ามีใครหาวิธีข้ามจากส่วนบั๊กของนักพัฒนาไปยังส่วนการเงินสำหรับ HR หรือผู้บริหารเท่านั้นได้จะทำอย่างไร? ใครก็ตามที่เคยทำระบบ ERM แบบครอบจักรวาลคงรู้ดีว่าระบบรวมศูนย์นั้นยากและเจ็บปวดแค่ไหน
      อย่างไรก็ดี นี่คือกรณีสุดโต่ง ฉันสงสัยว่าถ้าตามอุดมคตินี้จริง ๆ ผู้คนไปได้ไกลแค่ไหนและทำอย่างไร ฉันไม่เคยเห็นธุรกิจที่รันอยู่บนระบบเดียว แล้วระบบจัดการความรู้ส่วนบุคคลล่ะ? ทุกอย่างเข้ากันได้จริงไหม? หรือสุดท้ายก็ยังใช้สเปรดชีตกับงานที่ต้องการความเร็ว และใช้ไฟล์ข้อความกับงานแบบอิสระอยู่ดี?
  • ดูเหมือนเป็นชุดคำฮิตมากกว่า ฉันทำงานกับ database มาหลายปีในบริษัทระดับใหญ่ที่สุดแห่งหนึ่งของโลก แต่ไม่เคยได้ยินคำว่า topology มาก่อน
    ต่อให้มันช่วยประหยัดเวลาได้ เวลานั้นก็คงถูกใช้ไปกับการเรียน Java และ framework นี้อยู่ดี ตัว database เองไม่ได้มีปัญหาอะไร

    • มี implementation ของ Mastodon ที่พร้อมใช้ใน production ซึ่งสร้างความสามารถเทียบเท่ากันในระดับขนาดของ Twitter โดยใช้โค้ดน้อยกว่าโค้ดที่ Twitter เขียนเองถึง 100 เท่า ดังนั้นจึงยากที่จะเห็นด้วยกับคำวิจารณ์ว่าเป็น “ชุดคำฮิต”: https://github.com/redplanetlabs/twitter-scale-mastodon
    • สำหรับฉันมันดูเหมือนตัวอย่างหนึ่งของโฆษณาแบบนี้
      เดิมทีฉันพยายามทำตารางข้อความที่นี่ แต่การแสดงผลของหน้าเพี้ยนหนักมาก เลยอัปเป็นภาพหน้าจอแทน: https://imgur.com/a/XtwSkyx
  • ถ้าจะอธิบาย Rama ให้เด็กห้าขวบฟัง มันคืออะไร? เอกสารก็งงเหมือนกัน: https://redplanetlabs.com/docs/~/index.html
    อยากให้ตัดคำฮิตอย่าง “การเปลี่ยนกระบวนทัศน์” หรือ “แพลตฟอร์ม” ออกไป ถ้าต้องใช้ไดอะแกรมก็อยากอ่านบทความที่อธิบายให้ชัดกว่านี้

    • มันคือ แพลตฟอร์มพัฒนาแบ็กเอนด์ ที่รองรับความต้องการด้านการเก็บรวบรวม ประมวลผล ทำดัชนี และคิวรีข้อมูลของแอปพลิเคชันได้ในทุกสเกล แทนที่จะต้องเอาฐานข้อมูลหลายตัว ระบบประมวลผล คิว และตัวจัดตารางงานมาปะปนกันเพื่อประกอบเป็นแบ็กเอนด์ ก็ทำทั้งหมดได้ภายในแพลตฟอร์มเดียวคือ Rama
      Rama รันเป็นคลัสเตอร์ และแอปพลิเคชันหลายตัวจะถูกดีพลอยลงไปบนคลัสเตอร์นั้นในรูปแบบของ “โมดูล” โดยมีระบบ telemetry แบบลึกและละเอียดติดตั้งมาให้ในตัว
      โมเดลการเขียนโปรแกรมของ Rama คือ event sourcing และ materialized views ตอนสร้างแอปบน Rama คุณจะ materialize ดัชนีได้มากเท่าที่ต้องการ ในรูปแบบที่ต้องการ โดยอาศัยการประกอบกันของโครงสร้างข้อมูลถาวรหลายแบบ ดัชนีเหล่านี้ถูก materialize ผ่าน API ของ dataflow แบบกระจายศูนย์
      Rama แตกต่างจากของเดิมที่มีอยู่มาก จึงอธิบายระดับสูงได้ประมาณนี้ แหล่งข้อมูลที่ดีที่สุดสำหรับเริ่มจากพื้นฐานคือ rama-demo-gallery ซึ่งมีตัวอย่างแบบสั้น รันได้จนจบ และใส่คอมเมนต์อธิบายละเอียดว่าประยุกต์ใช้ Rama กับกรณีใช้งานต่าง ๆ อย่างไร ทั้งหมดขยายระบบได้และทนต่อความขัดข้อง: https://github.com/redplanetlabs/rama-demo-gallery
    • เท่าที่ผมอ่าน มันคือ Kappa architecture หรือก็คือรูปแบบหนึ่งของ event sourcing
      มี event log แบบเขียนเพิ่มอย่างเดียวที่เรียกว่า “Depot” แล้วสร้างวิวแบบใดก็ได้ไว้ด้านบน ซึ่งเรียกว่า “P-States” ซอฟต์แวร์ Rama สัญญาว่าจะอัปเดตวิวเหล่านี้ด้วย latency ต่ำ แอปพลิเคชันที่สร้างอยู่บนนี้จะคิวรีวิวและส่ง event/command ใหม่เข้าไปยัง Depot
    • มันดูเหมือนฐานข้อมูลแบบ event sourcing โดยพื้นฐานคือแทนที่จะเขียนข้อมูลโดยตรง คุณจะเขียนข้อความ แล้วสร้าง ตารางแบบอ่านอย่างเดียว ที่อัปเดตตามข้อความนั้นได้ ในบางโดเมนตอนนี้ก็ทำแบบนี้กันอยู่แล้ว แต่แน่นอนว่าซับซ้อนกว่าฐานข้อมูลแบบดั้งเดิม
    • ดูเหมือนความพยายามทำ NoSQL อีกครั้ง “แต่ครั้งนี้มันต่างออกไป!”
  • ผมเคยทำโปรเจกต์หนึ่งปีเพื่อสร้างเอนจิน materialized views ที่ยืดหยุ่นบนชุดข้อมูลเหตุการณ์สดขนาด 1~10TB และก่อนจะย้ายไปโปรเจกต์อื่น สถาปัตยกรรมของเราก็เริ่มลงเอยกับแนวคิดประมาณ ส่งโค้ดไปยังที่ที่มีดัชนีอยู่
    ผมค่อนข้างสนใจ Rama แต่ด้วยเหตุผลที่ไม่สมเหตุสมผลล้วน ๆ ก็คงไม่ใช้เพราะ JVM ผมแค่ไม่ชอบ Java/JVM ถ้าสถาปัตยกรรมนี้ถูกพอร์ตไปสภาพแวดล้อมอื่นก็น่าสนใจ

  • ที่ทำงานเราแยก read model กับ write model ออกจากกัน write model หรือ แหล่งความจริง เป็นโดเมนโมเดลเชิงสัมพันธ์แบบดั้งเดิมที่มี invariant/constraint ครบถ้วน และผมคิดว่าสำหรับนักพัฒนาส่วนใหญ่ที่คุ้นกับ ORM มันไม่ได้ยากจะทำความเข้าใจนัก
    คำสั่งเกือบทั้งหมดจะสร้าง event ขึ้นมาด้วยและเผยแพร่ไปยังคิว shared domain events ส่วน read model จะให้ worker ที่ consume event ไปสร้างวิวตามที่แต่ละตัวต้องการ และสร้างใหม่ได้ด้วย เช่น บริการจัดการผู้ใช้เป็นแหล่งความจริง ส่วนบริการอื่นจะเป็น view service เพื่อแสดง UI ที่ซับซ้อน โดยสร้าง read model/index ของตัวเองจาก event ของบริการผู้ใช้และบริการอื่น ๆ ถ้าไม่มีแบบนี้ก็คงต้องใช้ join มหาศาลหรือไม่ก็เรียก API ข้ามบริการที่ช้า
    ในเชิงเทคนิคสามารถ replay event ได้ และจริง ๆ เราเคย replay event ทั้งหมดตลอด 3 ปีที่ผ่านมาเพราะบั๊กในโค้ดแพลตฟอร์ม แต่ผมคิดว่าแทบไม่เคยมีครั้งไหนที่จำเป็นจริง ๆ บางครั้งต้องสร้างวิวใหม่เพราะบั๊ก แต่ปกติก็จัดการด้วยสคริปต์เฉพาะกิจหรือโปรแกรมชั่วคราวอย่าง SQL migration ผมไม่รู้จะเรียกสถาปัตยกรรมของเราว่าอะไรเป๊ะ ๆ และไม่เคยได้ยินใครเรียกมันว่า “event sourcing”
    สุดท้ายมันก็คือ MySQL เก่า ๆ + RabbitMQ กับโค้ดกาวนิดหน่อย แต่ถ้าจะทำให้ดีจริงก็ไม่ใช่เรื่องเล็กเลย เพราะต้องมี transactional outbox, การรับประกันการส่งอย่างน้อยหนึ่งครั้ง, eventual consistency, การรักษาลำดับการประมวลผล event ให้ถูกต้อง, การจัดชุดข้อมูล event, การดูแล DB, การรับมือเมื่อ event handler ตาย ฯลฯ ในสถานการณ์ที่มันเป็นองค์ประกอบซึ่งพิสูจน์แล้วในภาคสนาม เป็นอิสระจากภาษา และเรามีทั้ง producer/consumer ที่เป็น PHP และ Go ผมเลยสงสัยว่าถ้าไม่ใช้ Rama เรากำลังพลาดอะไรไป และ Rama จะแก้ปัญหาในรายการข้างต้นอย่างไร Rama ดูเหมือนจะเหมาะกับฝั่ง Java มากกว่า

    • ฟังดูเหมือนคุณออกแบบวิธีจัดการความซับซ้อนโดยใช้ RDBMS ได้ดีมาก และ Rama ก็มีบางอย่างที่เพิ่มขึ้นมาจากตรงนั้น
      ดัชนีของ Rama ยืดหยุ่นกว่ามาก ตัวอย่างเช่น ถ้าต้องการ nested set ที่มีองค์ประกอบ 100 ล้านตัว ก็เป็นเรื่องง่าย ตัวอย่างดัชนี social graph อย่าง user ID → เซ็ตของ follower ID ก็เป็นกรณีที่พบบ่อย เช่นเดียวกับดัชนี time-series ที่แยกตาม granularities ต่าง ๆ เช่น entity → granularity → time bucket → สถิติ ซึ่งก็ทำได้ง่ายมาก
      ชนิดข้อมูลที่เก็บใน Rama ไม่มีข้อจำกัด คิวรีของ Rama ทรงพลังมาก และทำคิวรีแบบกระจายศูนย์ตามต้องการกับดัชนีบางส่วนหรือทั้งหมดแบบเรียลไทม์ได้ง่าย อีกทั้งยังมี telemetry แบบลึกและละเอียดครอบคลุมทั้งแอปพลิเคชันในตัว จึงไม่ต้องไปสร้างหรือดูแลแยกเอง
      การดีพลอยก็มีมาให้ในตัวเช่นกัน ในวิธีที่คุณใช้อยู่ตอนนี้ การอัปเดตแอปอาจครอบคลุมหลายระบบ เช่น โค้ดของ worker หรือ schema migration และถ้าต้องการ zero-downtime โดยเฉพาะ มันจะกลายเป็นงานวิศวกรรมที่ค่อนข้างยาก Rama รวม computation กับ storage เข้าด้วยกันแบบครบวงจร จึงทำให้การรีลีส อัปเดต และขยายแอปทำได้ด้วยคำสั่งบรรทัดเดียวในเทอร์มินัล
      Rama ขยายระบบได้มากกว่ามาก นี่คือ Rama ในมุมของฟีเจอร์ ส่วนตอนเขียนโค้ดกับ Rama ความจริงที่ว่าไม่มี impedance mismatch นั้นสร้างความต่างอย่างมาก ซึ่งยากจะอธิบายเป็นคำพูดและต้องลองใช้เองจึงจะเข้าใจ Rama สำหรับ JVM จึงใช้ได้กับภาษาใดก็ได้บน JVM และตอนนี้มี API สำหรับ Java และ Clojure
    • คำสั่งอย่าง “อัปเดตที่อยู่ลูกค้า” นี่คือรัน SQL แล้วให้ RDBMS trigger ส่ง event ไปที่ RabbitMQ หรือว่า ORM ส่ง SQL แล้วก็ publish ไปที่ RabbitMQ?
      แล้ว event ถูกเก็บไว้ที่ไหน ในรูปแบบอะไร? อยากฟังรายละเอียดเพิ่ม
      ตอนนี้สิ่งที่ขาดไปดูเหมือนจะเป็นชื่อเท่ ๆ สำหรับเอาไปติดให้ทั้ง ecosystem
  • การทำให้ข้อมูลเป็นรูปธรรมตั้งแต่จุดที่มีการเปลี่ยนแปลงอาจมีประโยชน์เมื่อผลิตภัณฑ์ต้องทำงานเพียงอย่างเดียวให้เร็วมาก ๆ แต่พอเริ่มมีทรานแซกชันที่ซับซ้อนซึ่งต้องอัปเดตร่วมกันด้วย atomic write หรือเมื่อต้องการเพิ่มฟีเจอร์ใหม่ที่ต้องจัดระเบียบข้อมูลในรูปแบบอื่น ก็จะเริ่มลำบาก
    ในส่วนของการสร้างแอปพลิเคชัน แนวคิดทำนองว่า “ก็แค่เพิ่ม index เข้าไปอันหนึ่งก็พอ” ก็น่าผิดหวังมากเช่นกัน index เป็น state แบบ global และแค่ถูกย้ายลงไปอีกหนึ่งชั้นเท่านั้น

    • เพราะว่า “แค่ถูกย้ายลงไปอีกหนึ่งชั้น” นั่นเอง ข้อสำคัญคือเราไม่ต้องจัดการมันโดยตรงอีกต่อไป สิ่งที่ต้องทำมีแค่บอกระบบว่าจะทำ index อะไรบ้าง และนั่นไม่ใช่ state หรือข้อมูล แต่เป็นโค้ด
  • ต่อให้อ่านเอกสารนี้ก็ยังไม่ชัดเจนว่ากลุ่มผู้อ่านเป้าหมายคือใคร และกำลังพยายามแก้ปัญหาอะไร: https://redplanetlabs.com/docs/~/why-use-rama.html#gsc.tab=0
    น่าจะช่วยได้มากถ้ายก use case จริงมาสักหนึ่งกรณี แล้วแปลงให้ดูว่าเมื่อทำด้วย RAMA จะง่ายและมีประสิทธิภาพแค่ไหน

    • มีการเผยแพร่ตัวอย่างไว้จำนวนมากแล้ว
      ตัวอย่างแรกคือ การทำ Mastodon ที่สเกลระดับ Twitter ซึ่งใช้โค้ดน้อยกว่าที่ Twitter เขียนเพื่อสร้างสิ่งเดียวกันในระดับสเกลนั้นถึง 100 เท่า โดยนับเฉพาะผลิตภัณฑ์ฝั่งผู้ใช้ ยิ่งกว่านั้นยังใช้โค้ดน้อยกว่าการติดตั้ง Mastodon อย่างเป็นทางการซึ่งขยายสเกลไม่ได้อยู่แล้วมากกว่า 40%: https://github.com/redplanetlabs/twitter-scale-mastodon
      ใน repository rama-demo-gallery ก็มีตัวอย่างสั้น ๆ แบบแยกอิสระและใส่คอมเมนต์อธิบายละเอียดจำนวนมาก ที่แสดงการใช้ Rama กับ use case ที่แตกต่างกันมาก เช่น การจัดการโปรไฟล์ผู้ใช้ การวิเคราะห์อนุกรมเวลา และการโอนเงินระหว่างธนาคารที่เป็น atomic และทนทานต่อความขัดข้อง: https://github.com/redplanetlabs/rama-demo-gallery
  • ถ้าไม่ได้กำลังรันเว็บไซต์ที่มีผู้ใช้ต่อวัน 40 ล้านคนจริง ๆ ก็ดูเหมือนจะยังอ้างไม่ได้ว่าเรื่องนี้ได้รับการพิสูจน์แล้วด้วย “Mastodon client ระดับ Twitter scale” การจำลองสภาพแวดล้อมจริง รวมถึงการเปลี่ยนแปลงของโค้ดและโครงสร้างพื้นฐาน ผู้ใช้จริง ปริมาณการใช้งานเครือข่ายจริง ฯลฯ เป็นเรื่องที่ทำไม่ได้