2 คะแนน โดย GN⁺ 2024-10-15 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Durable Object ของ Cloudflare เปลี่ยนจากที่เก็บข้อมูลแบบคีย์/ค่าไปเป็นที่เก็บข้อมูลเชิงสัมพันธ์บน SQLite ทำให้แอปพลิเคชันลอจิกและข้อมูลทำงานอยู่บนโฮสต์จริงเดียวกัน
  • การขยายระบบทำโดยแยก Durable Object ตาม หน่วยสถานะแบบตรรกะ เช่น เอกสาร ผู้ใช้ หรือชาร์ดของฐานข้อมูล แทนการขยายวัตถุเดียวให้ใหญ่ขึ้น โดยวัตถุเดี่ยวมีข้อจำกัดจากการทำงานบนเครื่องเดียวและเธรดเดียว
  • ในระบบที่มีหน่วยสถานะชัดเจนอย่างการจองเที่ยวบิน สามารถมี Durable Object เฉพาะพร้อมฐานข้อมูล SQLite ของตัวเองสำหรับแต่ละเที่ยวบินได้ ทำให้สายการบินหนึ่งอาจมีฐานข้อมูลใหม่หลายพันรายการต่อวัน
  • ความทนทานของข้อมูลประกอบด้วย การสตรีม WAL entry การจัดเก็บลง object storage และการทำสำเนาไปยังดาต้าเซ็นเตอร์ใกล้เคียง โดยทำเป็นแบตช์ทุก 16MB หรือทุก 10 วินาที และรองรับการกู้คืนแบบ point-in-time ย้อนหลังได้สูงสุด 30 วัน
  • JavaScript API เลือกใช้รูปแบบ blocking สำหรับงาน persistence แบบเธรดเดียวที่รวดเร็ว และตำแหน่งของ Durable Object จะคงที่หลังสร้างเสร็จ แต่มีแผนรองรับการย้ายตำแหน่งแบบไดนามิกในอนาคต

สถาปัตยกรรม Durable Object ที่เปลี่ยนมาใช้ SQLite

  • Durable Object ของ Cloudflare ได้รับการอัปเกรดจากที่เก็บข้อมูลแบบคีย์/ค่าไปเป็น ระบบเชิงสัมพันธ์บน SQLite
  • แกนสำคัญคือการวางแอปพลิเคชันลอจิกไว้ ในที่เดียวกัน กับข้อมูลที่ลอจิกนั้นจัดการ
    • Durable Object หนึ่งตัวประกอบด้วยโค้ดที่ทำงานบนโฮสต์จริงเดียวกันกับฐานข้อมูล SQLite ที่มันใช้งาน
    • แนวทางนี้มุ่งให้การอ่านและเขียนเกิดขึ้นได้โดยไม่ต้องมี network round trip จึงช่วยลด latency ได้ง่าย
  • การรองรับงานขนาดใหญ่ใช้วิธีสร้างวัตถุเพิ่ม แทนการเพิ่ม throughput ของวัตถุเดี่ยว
    • วัตถุเดี่ยวหนึ่งตัวทำงานบน single thread ของ single machine จึงมีข้อจำกัดด้าน throughput โดยธรรมชาติ
    • ถ้าให้วัตถุแยกกันรับผิดชอบ หน่วยสถานะแบบตรรกะ ที่ต่างกัน เช่น เอกสาร ผู้ใช้ หรือ database shard ก็จะขยายระบบได้ง่ายกว่า
  • ในระบบจองเที่ยวบิน สามารถแมปแต่ละเที่ยวบินไปยัง Durable Object เฉพาะพร้อมฐานข้อมูล SQLite ของตัวเองได้
    • ในโครงสร้างนี้ สายการบินหนึ่งอาจสร้างฐานข้อมูลใหม่หลายพันรายการต่อวัน
  • Durable Object แต่ละตัวมีชื่อเฉพาะของตัวเอง และเครือข่ายของ Cloudflare จะ route คำขอไปยังตำแหน่งของวัตถุนั้นภายในเครือข่ายทั่วโลก

ความทนทานด้วย WAL streaming และการทำสำเนา

  • ระบบที่ใช้ Durable Object ได้แรงบันดาลใจจาก Litestream โดยจะสตรีมลำดับของ WAL entry ของแต่ละวัตถุไปยัง object storage อย่างต่อเนื่อง
    • ทำเป็นแบตช์ทุก 16MB หรือทุก 10 วินาที
    • สามารถ replay ธุรกรรมที่บันทึกไว้เพื่อทำ point-in-time recovery ย้อนหลังได้สูงสุด 30 วัน
  • เพื่อเสริมความทนทานภายในหน้าต่างเวลา 10 วินาที การเขียนข้อมูลจะถูกส่งต่อไปยังสำเนา 5 ชุดในดาต้าเซ็นเตอร์ใกล้เคียงที่แยกจากกันทันทีหลัง commit
    • ต้องมี 3 ชุดยืนยันก่อนจึงจะอนุมัติการตอบกลับการเขียน
  • ระบบพื้นฐานของ Durable Objects คือ Storage Relay Service และ Cloudflare ได้ใช้งาน D1 SQLite system ที่แยกต่างหากนี้มานานกว่าหนึ่งปีแล้ว

API และพฤติกรรมตำแหน่งของวัตถุ

  • JavaScript API ใช้รูปแบบ blocking ไม่ใช่ async
    • เป้าหมายของการออกแบบคือการให้การทำงาน persistence แบบ single thread ที่รวดเร็ว
    • โค้ดตัวอย่างจงใจใช้รูปแบบ N+1 query โดยดึงรายการเอกสารก่อน แล้วค่อยดึงชื่อผู้เขียนของแต่ละเอกสารด้วย query แยก
    • SQLite ถูกยกให้เป็นกรณีที่เหมาะกับการจัดการรูปแบบนี้
  • ปัจจุบัน Durable Object จะไม่ย้ายตำแหน่งหลังจากถูกสร้างแล้ว
    • โดยปกติจะถูก instantiate ในดาต้าเซ็นเตอร์ที่อยู่ใกล้กับตำแหน่งที่เกิดคำขอ get() ครั้งแรก
    • หากต้องการสร้างในตำแหน่งอื่นแบบกำหนดเอง สามารถส่งพารามิเตอร์เสริม locationHint ให้กับ get() ได้
    • การ ย้ายตำแหน่งแบบไดนามิก ของ Durable Object ที่มีอยู่แล้วเป็นแผนในอนาคต
  • where.durableobjects.live เป็นเว็บไซต์สำหรับติดตามว่า Durable Object ใหม่ถูกสร้างขึ้นที่ไหนในเครือข่ายของ Cloudflare
    • ในตัวอย่างการเข้าชม เมื่อโหลดหน้าเว็บจาก Half Moon Bay พบว่า worker ใน San Jose ได้สร้าง Durable Object ใน San Jose

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

 
GN⁺ 2024-10-15
ความคิดเห็นบน Hacker News
  • มีประเด็นน่าสนใจเพิ่มเติมอยู่หลายอย่าง: API สำหรับเขียนเป็นแบบ synchronous แต่มีการรอแบบ asynchronous ที่ซ่อนไว้ ดังนั้นถ้าการเขียนล้มเหลวตอนกำลังส่ง response ถัดไป runtime จะเปลี่ยน response นั้นให้เป็น HTTP failure
    ด้วยเหตุนี้ runtime จึงสามารถ จัด batch อัตโนมัติ สำหรับการเขียนและสมมติในเชิง optimistic ว่าจะสำเร็จได้ โดยที่ผู้ใช้ไม่ต้องจัดการ error หรือการรออย่างชัดเจน
    ไม่มี read transaction ซึ่งน่าจะมีประโยชน์สำหรับการได้ pointer ไปยัง snapshot ณ ช่วงเวลาหนึ่ง
    แต่ละ instance ของ runtime ถูกจำกัดไว้ที่ RAM 128MB
    WebSocket สามารถเข้าสู่สถานะ hibernate ได้ และจะไม่ถูกคิดค่าใช้จ่ายในช่วงที่หลับอยู่ จึงสามารถคง client ให้เชื่อมต่ออยู่ได้แม้ในระหว่างที่ DO หลับ
    ยังมีฟีเจอร์คล้าย RPC อัตโนมัติที่ทำให้เรียก DO หรือ Worker อื่นเหมือนการเรียก JS ปกติได้ แต่ในความเป็นจริงอาจเป็นการเรียกไปยัง data center อื่น และ runtime จะจัดการ serialization กับ parsing ให้

    • ฝั่ง RPC ค่อนข้างน่าสนใจ รายละเอียดอยู่ที่นี่: https://blog.cloudflare.com/javascript-native-rpc/
    • การรอแบบ asynchronous ที่ซ่อนไว้ใน API สำหรับเขียนทำให้นึกถึง commit_delay ของ PostgreSQL หลักการไม่ได้เหมือนกันเป๊ะ แต่ให้ความรู้สึกคล้ายกัน: https://www.postgresql.org/docs/current/runtime-config-wal.h...
      Litestream ที่กล่าวถึงในบทความก็เสนอเทคนิคที่คล้ายกัน
    • สงสัยว่าที่นี่มี use case เฉพาะแบบไหนที่จำเป็นต้องใช้ read transaction ระดับ database
      ใน SQLite ทั่วไป read transaction มีประโยชน์เพราะหลาย process สามารถเข้าถึง database เดียวกันพร้อมกันได้
      แต่ที่นี่มีเพียง process เดียวที่เข้าถึง database ได้ ดังนั้นถ้าทำการอ่านทั้งหมดภายใน synchronous function เดียว หรือ implement lock ระดับ process เอง ก็จะได้ผลลัพธ์แบบเดียวกัน
  • การที่รายการ WAL ถูก stream แบบ batch ไปยัง object storage ทุก 16MB หรือทุก 10 วินาที ดูเหมือนหมายความว่า การอ่านข้อมูลที่เขียนจากทั่วโลกได้อย่างน่าเชื่อถืออาจใช้เวลาสูงสุด 10 วินาที
    ผมไม่ค่อยเข้าใจว่าสิ่งนี้จะมาแทน cluster database แบบแยกตามภูมิภาคที่ตอบสนองระดับมิลลิวินาทีข้ามทวีปได้อย่างไร
    เข้าใจว่าใช้ stream แต่ปลายทางมีเพียง follower 5 ตัว และ Cloudflare มี data center หลายร้อยแห่ง
    ถ้า SQLite instance ทั้งหมดไม่ได้เชื่อมต่ออยู่ตลอดเวลา ก็รับประกันการอ่านระดับวินาทีไม่ได้ในทางกายภาพ และแม้จะเชื่อมต่ออยู่ packet delay ก็อาจก่อปัญหาได้

    • เท่าที่รู้ การเขียนและการอ่านเกิดขึ้นได้เฉพาะใน process เดียวกัน ดังนั้น long-term storage จะถูกนำมาใช้เฉพาะเมื่อ process ปัจจุบันอยู่ในสถานะ hibernate เท่านั้น
      ถ้าเขียนแล้วอ่านทันที จะเห็นผลทันที เพราะการเขียนจะอัปเดต สถานะใน memory ของ process ปัจจุบันไปพร้อมกันด้วย
      ถ้า process อื่น เช่น DO หรือ Worker อื่น ต้องการเข้าถึงข้อมูล ก็ต้องผ่าน DO ที่ถือข้อมูลอยู่ จึงจะส่งคำขอ RPC หรือ HTTP และได้รับข้อมูลล่าสุด
      hibernate จะเกิดหลังจากไม่มี activity ไปสักระยะ ดังนั้นกรณีที่การเขียนกลายเป็น unavailable ผิดจากที่คาด น่าจะมีเพียงสถานการณ์ที่ DO หรือ Worker crash ทันทีหลังเขียน
    • การเขียนถูก stream ไปยัง follower 5 ตัว แทบจะ real-time และได้รับการยืนยันทันทีเกือบทั้งหมด
      บทความบล็อกของ Cloudflare อธิบายส่วนนี้ละเอียดกว่า ดังนั้นจึงรักษาความเร็วของการเขียนไว้ได้พร้อมกับได้ durability
    • ดูเหมือนจะเข้าใจวิธีทำงานของ Durable Objects ผิดไป ทุก traffic ที่มุ่งไปยัง object เดียวกันจะถูก route ไปยัง เครื่องเดียว ที่ object นั้นอยู่
      เครื่องนั้นจะมีมุมมองที่สอดคล้องเสมอต่อ database SQLite ของตัวเอง
      สามารถสร้าง object ได้หลายพันล้านตัว แต่แต่ละ object มี database แยกกัน
      ไม่มีวิธีอ่าน database นั้นโดยตรงจากเครื่องอื่นที่ไม่ใช่เครื่องที่ DO กำลังรันอยู่
    • รายการ WAL ที่ถูก stream ไปยัง object storage น่าจะมีไว้สำหรับ backup
      DO แต่ละตัวมีเอกลักษณ์ระดับ global และ DO ของ ID หนึ่ง ๆ จะรันอยู่ที่ใดที่หนึ่งเพียงตัวเดียว โดยใช้ SQLite บน storage local ของ data center นั้น
  • ส่วนที่ยังไม่ค่อยเข้าใจเกี่ยวกับ Durable Objects คือ ตำแหน่งทางกายภาพ
    สงสัยว่ามันอยู่ในรีเจียนที่โฮสต์ API call ซึ่งเป็นสาเหตุให้ถูกสร้างขึ้นครั้งแรกหรือไม่
    ถ้าเป็นอย่างนั้น ก็สงสัยต่อว่ามีกลไกย้าย DO ไปยังตำแหน่งอื่นโดยอัตโนมัติไหม เมื่อพบว่ามันถูกสร้างในอเมริกาเหนือ แต่หลังจากนั้นทราฟฟิกอ่าน/เขียนทั้งหมดมาจากออสเตรเลีย เป็นต้น

    • โดยพื้นฐานแล้วจะอยู่ใน รีเจียน ที่สร้างขึ้น แต่เป็นทางเลือกสามารถระบุ locationHint ได้ ออสเตรเลียใช้ "oc" ได้: https://developers.cloudflare.com/durable-objects/reference/...
      ควรทราบด้วยว่า “การย้ายตำแหน่งแบบไดนามิกของ Durable Objects ที่มีอยู่แล้วเป็นแผนในอนาคต”
    • https://where.durableobjects.live เป็นไซต์ที่ดีที่แสดงว่า DO อยู่ที่ไหน
      มีเพียงประมาณ 10~11% ของ Cloudflare PoP เท่านั้นที่โฮสต์ Durable Objects
      คำขอที่เข้ามายัง PoP อื่นเพื่อสร้าง DO จะถูกส่งต่อไปยังหนึ่งใน PoP ใกล้เคียงที่โฮสต์สิ่งนี้
    • ปัจจุบัน Durable Objects จะไม่เปลี่ยนตำแหน่งหลังจากถูกสร้างขึ้น และ การย้ายตำแหน่งแบบไดนามิก ของ Durable Objects ที่มีอยู่แล้วเป็นแผนในอนาคต: https://developers.cloudflare.com/durable-objects/reference/...
      เท่าที่จำได้ Orleans(https://www.microsoft.com/en-us/research/wp-content/uploads/...) สามารถย้าย actor ระหว่างเครื่องได้ ซึ่งโมเดลนี้น่าจะเข้ากันได้ดีกับวิธีการย้าย DO ระหว่างตำแหน่ง
    • Durable Objects มีที่เก็บข้อมูลระยะยาว และถูก hydrate จากที่เก็บนั้น ดังนั้นในแง่นั้นจึงสามารถย้ายไปยังศูนย์ข้อมูล Cloudflare ใดก็ได้
      แต่ไม่มี API call สำหรับย้าย Durable Object
      ต้องไม่มีการเชื่อมต่ออยู่ และจะถูกสร้างขึ้นใหม่ในศูนย์ข้อมูลที่ใกล้ที่สุดกับการเชื่อมต่อถัดไปหรือการเชื่อมต่อแรก
      ตอนนั้นหน่วยความจำจะหายไป แต่ที่เก็บข้อมูลยังคงอยู่
      ช่วงหลังมีฟีเจอร์ย่อยเกี่ยวกับ hibernation เพิ่มเข้ามา ดังนั้นคำอธิบายนี้อาจเก่าไปเล็กน้อย
    • ไม่ใช่คำตอบของคำถาม แต่ขอแนะนำ https://where.durableobjects.live/
  • สงสัยว่ามีคนอื่นอีกไหมที่รู้สึกว่ายากที่จะเข้าใจเทคโนโลยีคลาวด์ใหม่ ๆ แบบนี้
    ทำเว็บมามากกว่า 15 ปี และใช้สแต็ก Laravel / Postgres / Redis มาตลอด แต่พออ่านบทความแบบนี้แล้วก็รู้สึกว่า มันไม่เข้ากับตัวเอง

    • ตามบทความ ระบุว่าให้ดู Cloudflare’s durable multiplayer moat ของ Paul Butler เพื่อเป็นพื้นหลังที่มีประโยชน์ของ Durable Objects เวอร์ชันแรก และเขาพูดถึงเหตุผลที่มันได้รับความนิยมในการสร้าง แอปพลิเคชันทำงานร่วมกันแบบเรียลไทม์ บน WebSocket
      แอปทำงานร่วมกันแบบเรียลไทม์ที่นึกออกทันทีคือ Google Docs/Sheets, Notion, Miro, Figma เป็นต้น
      ทั้งหมดเป็นแอปทำงานร่วมกันระดับโลก และไม่แน่ใจว่าสแต็ก Laravel จะรองรับกรณีใช้งานแบบนี้ได้หรือไม่
      Google คงต้องทำเองเกือบทั้งหมด และน่าจะเป็นผู้บุกเบิกการใช้ CRDT
      แต่เมื่อแพตเทิร์นเริ่มชัดเจนและองค์ประกอบต่าง ๆ กลายเป็น SaaS การทำงานร่วมกันแบบเรียลไทม์ขนาดใหญ่ก็ไม่ใช่ปัญหาวิศวกรรมมหึมาอีกต่อไป และทำให้ผลิตภัณฑ์ที่น่าสนใจกว่านี้เป็นไปได้
  • ชอบการออกแบบ Durable Object มาก โดยเฉพาะตรงที่เข้าใจได้ง่ายว่าภายในทำงานอย่างไร
    ต่างจากโซลูชันจำนวนมากที่ออกแบบมาสำหรับข้อมูลเรียลไทม์ Durable Objects มี ความเรียบง่าย แบบ Redis กับอาหารอิตาเลียน คือเห็นวัตถุดิบทั้งหมด
    ถ้ามีเวลา ทรัพยากร และศูนย์ข้อมูลเพียงพอ โปรแกรมเมอร์ที่มีฝีมืออ่านเอกสาร DO แล้วน่าจะสร้างสิ่งที่คล้ายกันขึ้นมาใหม่ได้
    จึงตัดสินใจเรื่อง trade-off ที่เกี่ยวข้องได้ง่าย
    แต่ก็กังวลว่า DO เหมาะกับการสร้างประสบการณ์เรียลไทม์ที่เร็วและมีโอเวอร์เฮดต่ำ เช่น ฟีเจอร์ให้คนห้าคนแก้ไขเอกสารแบบเรียลไทม์ แต่จะทำให้การวิเคราะห์และการสร้างภาพรวมทำได้ยากมาก
    เช่นคำถามว่ากลุ่มไหนแก้ไขเอกสารใดเมื่อสัปดาห์ที่แล้ว และถ้าใส่ข้อมูลไว้ใน SQLite ก็อาจยิ่งยากขึ้น
    เพราะคงต้องหาวิธี query อินสแตนซ์ SQLite ขนาดเล็กจำนวนมหาศาล แล้วรวมผลลัพธ์เข้าด้วยกัน จึงสงสัยว่า DO มีอะไรสำหรับเรื่องนี้หรือไม่
    สุดท้ายเหตุผลที่กลับไปหา Postgres อยู่เสมอก็คือเรื่องนี้ เพราะใช้ได้ทั้งกับฟังก์ชันหลักของแอป รวมถึงภาพรวมและ BI ต่าง ๆ

  • เป็นการออกแบบที่น่าสนใจมาก แต่ระบบฉลาด ๆ แบบนี้สำหรับผมมักอยู่ใน uncanny valley เสมอ
    กรณีที่จำเป็นจริง ๆ มีแค่สองแบบเท่านั้น: ต้องขยายระบบที่มีโหลดสูงมากอย่างชาญฉลาด หรือทำโปรเจกต์ของเล่นเพื่อความสนุก
    ถ้าเป็นโปรเจกต์ของเล่น จะใช้อะไรก็ได้
    แต่ถ้าเป็นโปรดักชันหรือใช้ในงานจริง ก็ต้องการสิ่งที่ผ่านการพิสูจน์แล้ว
    ถ้าคุณไม่รู้ว่าจำเป็นต้องใช้สิ่งนี้ ก็แปลว่าไม่จำเป็น และใช้ของน่าเบื่ออย่างฐานข้อมูล Postgres กับ VM ก็พอ
    แต่ในทางกลับกัน ถ้าคุณรู้ว่าจำเป็นต้องใช้ ก็จะลำบากขึ้น เพราะมันยังใหม่และยังไม่สุกงอมพอ จึงมีโอกาสสูงที่จะเจอ edge case แปลก ๆ จำนวนมาก ซึ่งคุณคงไม่อยากดีบักหรือยอมรับมัน
    สุดท้ายก็ไม่รู้ว่าระบบแบบนี้ทำมาเพื่อใคร
    มันเฉพาะทางเกินไปจนยากที่จะมีผู้เล่นจริงจังจำนวนมากใช้งานและทำให้สุกงอมได้ง่าย และก็ซับซ้อนเกินไปพร้อมข้อแลกเปลี่ยนเยอะเกินไปสำหรับ 99.9% ของบริษัท
    กลุ่มเป้าหมายที่ชัดเจนดูเหมือนจะมีแค่นักพัฒนาที่เห็นของแวววาวแล้วสร้างบริษัทขึ้นมา หรือแย่กว่านั้นคือเอาบริษัทของคนอื่นไปสร้างทับบนนั้น แล้วไม่นานก็เสียใจและย้ายไปใช้สิ่งที่น่าเบื่อกว่า

    • ดูเหมือนว่า killer app ของ Durable Objects คือ มัลติเพลเยอร์
      ถ้าอยากสร้างอะไรแบบ Figma หรือ Google Docs อีกตัวหนึ่ง โมเดลการเขียนโปรแกรมของ Durable Objects ก็สะดวกมาก
      บทความนี้ลงรายละเอียดมากกว่า: https://digest.browsertech.com/archive/browsertech-digest-cl...
      บทความเก่านี้ก็ค่อนข้างเกี่ยวข้อง: http://ithare.com/scaling-stateful-objects/
      สำหรับคนที่อ่านบทความมัลติเพลเยอร์ของ Figma แล้วคิดว่า “นี่แหละประมาณสิ่งที่ฉันต้องการ” Durable Objects น่าจะเหมาะ: https://www.figma.com/blog/rust-in-production-at-figma/
      มีแนวทางอื่นด้วย ก่อนหน้านี้เคยลองใช้ CRDT บน WebRTC แล้วรู้สึกเหมือนเป็นเทคโนโลยีแห่งอนาคตจริง ๆ
      แต่มันซับซ้อนกว่าพื้นฐานที่เป็น WebSocket ที่อยู่สักที่ในคลาวด์กับอินสแตนซ์ของคลาสเดียวมาก
    • ฐานข้อมูลเป็นสาขาที่เติบโตช้ามากพอ ๆ กับภาษาโปรแกรม และไม่ใช่ว่าทุกอย่างที่ออกนอก Postgres จะเป็นเทคโนโลยีฮิปสเตอร์แวววาว
      การวางข้อมูลกับพฤติกรรมไว้ ในตำแหน่งเดียวกัน ช่วยลดความซับซ้อนได้จริงในเชิงปริมาณ
      เพราะตัดความกังวลเรื่อง latency และ bandwidth ออกไป จึงลดทั้งความกังวลด้านปฏิบัติการและด้านการพัฒนา ผลกระทบของปัญหา N+1 อันโด่งดังก็ลดลงมากด้วย
      คุณอาจโต้แย้งได้ว่า Postgres ที่เชื่อมผ่านเครือข่ายดีกว่าด้วยเหตุผลอื่น และจริง ๆ ก็อาจถูก
      แต่ SQLite นั้นขึ้นชื่อเรื่องความน่าเบื่อและคาดเดาได้ และมีจุดแข็งที่เป็นที่รู้กันชัดเจน
      ดังนั้นมันจึงกำลังได้รับความนิยมมากขึ้นบนฝั่งเซิร์ฟเวอร์ด้วย
      อย่างไรก็ตาม วิธีสร้างฐานข้อมูลเล็ก ๆ จำนวนมากตามที่ Durable Objects เสนอนั้นผมไม่ค่อยชอบ
      มันทำให้นึกถึงฝันร้ายของ NoSQL และอาจทำลาย invariant สำคัญ ๆ ของฐานข้อมูลเชิงสัมพันธ์ได้
      ผมมองว่า SQLite เหมาะกว่ามากเมื่อใช้เป็น ฐานข้อมูลแบบเดี่ยว เหมือนผลิตภัณฑ์ D1 ของ Cloudflare
    • ถ้าเข้าข่ายข้อ 1 ก็ไปคุยกับ Cloudflare ได้เลย
      Cloudflare ต้องการกรณีความสำเร็จจากลูกค้าที่ดี และมีโอกาสสูงที่วิศวกรเก่ง ๆ จะช่วยดูให้ว่าเรื่องนี้ทำงานอย่างไร ช่วยได้อย่างไร และจะจัดการบั๊กอย่างไร เพื่อแลกกับการได้กรณีความสำเร็จ
      เมื่อพิสูจน์แล้วก็คงกลายเป็นความสัมพันธ์แบบบริการ แต่ช่วงแรกจะใกล้เคียงกับ พาร์ตเนอร์ชิป
    • การแบ่งตรงนี้ผมมองบนแกนของ ความสามารถในการดีบัก และความสามารถในการสังเกตภายใน
      มีบริการจำนวนมาก เช่น เครื่องมือภายใน ที่ไม่ต้องการการจูนประสิทธิภาพหรือการสังเกตภายในเชิงลึก
      ในกรณีเหล่านี้ ผมคิดว่าเฟรมเวิร์ก serverless เหมาะ เพราะช่วยลดเวลาที่ใช้กับการ deploy ได้มาก
      ถ้าเร็วก็ย่อมดี แต่แทบไม่ค่อยเป็นข้อกำหนดหลัก
      โดยทั่วไปข้อกำหนดหลักคือสร้างได้เร็วและต้องดูแลรักษาน้อย
      Cloudflare อาจมอบประสบการณ์นักพัฒนาที่ดีในจุดนี้ได้ แต่นั่นไม่ใช่จุดขายหลักของพวกเขา และก็มีบริการคู่แข่งอีกมากที่บอกว่าช่วยให้พัฒนาแบบนี้ได้เร็ว
      ในทางกลับกัน หากต้องการความสามารถในการดีบักและการสังเกตภายในสูง ผมคิดว่าบริการแบบนี้ไม่ค่อยเหมาะ
      สิ่งสำคัญคือจะได้ metric อะไรบ้าง มีข้อมูลพอไหมที่จะเข้าใจว่าทำไม Durable Objects บางตัวถึงช้า แก้ได้ไหม การ logging เป็นอย่างไร และค่าใช้จ่ายเท่าไร
      บริการแบบนี้อาจดีสำหรับสตาร์ทอัพที่อยากสร้างระบบกระจายตัวที่ฉลาดตั้งแต่วันแรกเพื่อเลื่อนความกังวลเรื่องการสเกลออกไป
      แต่ถ้าเป็นบริษัทระดับ scale-up ผมคิดว่าน่าจะอยากย้ายไปใช้สิ่งที่มองลึกลงไปได้มากกว่า และการเปลี่ยนผ่านนั้นคงยาก
    • การวิเคราะห์นี้เฉียบคมมาก ผมคิดว่าคนส่วนใหญ่ควรวิเคราะห์แบบนี้ก่อนออกแบบระบบ
      อย่างที่คนอื่น ๆ พูดกัน กรณีใช้งานคือมัลติเพลเยอร์ เพราะถ้าอยากให้แอปรู้สึกดี ทุกคนต้องเห็นการเปลี่ยนแปลงให้เร็วที่สุด
      มองให้กว้างขึ้น อุตสาหกรรม storage พยายามมานานที่จะสร้างสิ่งที่สอดคล้องกัน, latency ต่ำ และเหมาะกับผู้ใช้หลายคน
      แม้ในเชิงฟิสิกส์ก็มักมีข้อแลกเปลี่ยนระหว่าง consistency กับ latency จึงเป็นเรื่องยากมาก
      ดังนั้นจึงกำลังลองหลายโมเดล และการทดลองจำนวนมากก็เกิดขึ้นรอบ ๆ SQLite แต่ไม่ใช่ทั้งหมด มีข้อยกเว้นอย่าง Yugabyte หรือ Cockroach ด้วย
  • ผมยังคงทึ่งกับการออกแบบของ DO
    เรามักมีปฏิกิริยาโดยสัญชาตญาณว่าวิธีนี้ต้องมีอะไรผิดแน่ ๆ แต่จริง ๆ แล้วผมคิดว่าผลิตภัณฑ์จริงจำนวนมากถูกจัดวางแบบนี้โดยนัยอยู่แล้ว
    กล่าวคือสำหรับทุกหน่วยอะตอมิกที่ต้องการความสอดคล้องของทรานแซกชัน จะมีงานซับซ้อนจำนวนมากถูกทำในสเกลที่เล็กมาก
    เมื่อมองย้อนกลับไป สิ่งที่เราสร้างที่ Framer สำหรับโปรเจกต์รองรับมัลติเพลเยอร์ ก็เป็นเวอร์ชันที่ประยุกต์มากขึ้นของสิ่งที่ DO ทำอยู่ตอนนี้
    เนื้อหาการแก้ไขถูกทำซ้ำที่ 60 FPS และถูกนำไปใช้กับไคลเอนต์ทุกตัวตามลำดับที่ถูกต้อง และสุดท้ายเราก็สร้างสิ่งที่คล้าย WAL สำหรับการแก้ไขออบเจกต์ JSON ด้วย
    ดังนั้นแม้อินสแตนซ์ของโปรเจกต์จะ crash ตัวสำรองก็สามารถรับช่วงต่อได้เหมือนไม่มีอะไรเกิดขึ้น
    แม้ว่าจะยังไม่มีเวลาคอมมิต JSON patch ลงในออบเจกต์ข้อมูลโปรเจกต์ขนาดใหญ่ก็ตาม ก็ใช้วิธีประมวลผลทุก ๆ การอัปเดต N ครั้งหรือทุก ๆ M วินาทีตามที่อธิบายไว้ที่นี่

  • อาจเป็นคำถามโง่ ๆ ก็ได้ แต่สงสัยว่าในโครงสร้างแบบนี้จัดการ schema migration กันอย่างไร
    เท่าที่เข้าใจ ดูเหมือนจะตั้งเป้าไปที่ฐานข้อมูลต่อ tenant หรือโครงสร้างที่แตกย่อยกว่านั้นอีก
    เลยสงสัยว่ามีวิธีจัดการ schema migration อย่างมีสติหรือไม่ หรือคาดหวังว่าฐานข้อมูลลักษณะนี้จะมีอายุสั้นกว่า จึงต้องรองรับ DB/DO หลายเวอร์ชันไปจนกว่าจะถูกลบ
    ในหัวคิดว่าถ้าทำบริการบุ๊กมาร์กที่มี DO ต่อผู้ใช้ก็น่าจะสนุกดี
    แต่ทันทีที่อยากเพิ่มฟิลด์ใหม่ลงในตารางเดิม ก็จะเจอปัญหาค่อนข้างยุ่งยากที่ต้องนำการเปลี่ยนแปลงนั้นไปใช้กับ DO แต่ละตัว
    บางทีตัวอย่างนั้นอาจเป็นข้อมูลที่อยู่ยาวเกินไป และการออกแบบนี้อาจเหมาะกับการใช้งานที่ชั่วคราวกว่านั้น
    ถ้ามีใครเคยทำจริง อยากรู้ว่าจัดการกันอย่างไร

    • คงต้องทำ migration เอง
      มีเวอร์ชันสำหรับ SQLite ที่เขียนด้วย Python อยู่ แต่ไม่แน่ใจว่าจะรันบน Durable Objects ได้ไหม ผ่าน WASM กับ PyOdide อาจเป็นไปได้
      ไม่อย่างนั้นก็ต้องพอร์ตเป็น JavaScript
      https://github.com/simonw/sqlite-migrate
  • ช่วงนี้ดูเหมือน Cloudflare กำลังผลักดันให้นักพัฒนา ใช้ DO ทุกที่ มากกว่า Worker
    การเชื่อมต่อ WebSocket ของ Worker ก็ timeout หลังประมาณ 30 วินาที และวิธีที่แนะนำคือใช้ DO

    • ผมคิดว่าใน Cloudflare Workers นั้น Durable Objects เป็นวิธีที่แนะนำสำหรับการเชื่อมต่อ WebSocket มาโดยตลอด อย่างน้อยก็เท่าที่จำได้
      เดโมแชทเดิมก็ใช้ DO กับ WebSocket มาตั้งแต่ปี 2020: https://github.com/cloudflare/workers-chat-demo
  • นี่หมายความว่า SQLite สำหรับ DO อาจสูญเสียข้อมูลได้สูงสุด 10 วินาที ในสถานการณ์ที่ DO ล้มเหลวหรือเปล่า?

    • มีตอนหนึ่งที่บอกว่า “เพื่อรับประกันความทนทานเกินกรอบเวลา 10 วินาที การเขียนจะถูกส่งต่อไปยัง replica 5 ชุดในดาต้าเซ็นเตอร์อื่นที่อยู่ใกล้ทันทีที่ commit และต้องมี 3 ชุดในนั้นยืนยันก่อนการเขียนจึงจะได้รับการอนุมัติ”
      ตรงนี้ดูเหมือน Simon น่าจะตั้งใจพูดว่า within ไม่ใช่ “beyond”