4 คะแนน โดย GN⁺ 2024-03-20 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Garnet เป็นแคชสโตร์ระยะไกลที่สร้างโดย Microsoft Research โดยอิงตามโปรโตคอลสาย RESP จึงสามารถใช้ไคลเอนต์ Redis เดิมได้โดยไม่ต้องแก้ไข
  • เมื่อมีการเชื่อมต่อไคลเอนต์จำนวนมากและใช้แบตช์ขนาดเล็ก จะให้ throughput และ scalability สูงกว่าระบบแคชสโตร์โอเพนซอร์สที่เทียบเคียงกันได้ และเมื่อเปิด Accelerated Networking บน Azure VM ค่า latency ที่เปอร์เซ็นไทล์ 99.9 มักต่ำกว่า 300 ไมโครวินาที
  • สร้างบน .NET รุ่นใหม่ ทำงานได้ทั้งบน Linux และ Windows และสามารถสร้าง custom operation, stored procedure และโมดูลด้วย C# ได้ พร้อมรองรับ Lua scripting
  • เลเยอร์จัดเก็บข้อมูล Tsavorite รองรับการจัดเก็บแบบหลายชั้นทั้งหน่วยความจำ, SSD และคลาวด์สตอเรจ, non-blocking checkpoint, recovery, operation log เพื่อความทนทาน, ธุรกรรมหลายคีย์ และในโหมดคลัสเตอร์ยังรองรับ sharding, replication และ dynamic key migration
  • ฟีเจอร์ใหม่มี Vector Sets Preview และ Range Index Preview เพิ่มเข้ามา และงานวิจัยของ Garnet มีกำหนดตีพิมพ์ใน VLDB 2026

Garnet ที่มอบความสามารถแคชสโตร์ระยะไกล

  • Garnet คือแคชสโตร์ระยะไกลตัวใหม่จาก Microsoft Research
  • ใช้ RESP wire protocol เป็นจุดตั้งต้น ทำให้สามารถใช้ไคลเอนต์ Redis เดิมจากหลายภาษาโปรแกรมได้โดยไม่ต้องแก้ไข
  • ให้ throughput และ scalability ที่ดีกว่าโอเพนซอร์สแคชสโตร์ที่เทียบเคียงกันได้ในกรณีที่มีการเชื่อมต่อไคลเอนต์จำนวนมากและใช้แบตช์ขนาดเล็ก ซึ่งอาจช่วยลดต้นทุนของแอปและบริการขนาดใหญ่ได้
  • บน Azure VM ทั่วไป เมื่อเปิดใช้งาน Accelerated Networking ค่า client latency ที่เปอร์เซ็นไทล์ 99.9 มักอยู่ที่ ต่ำกว่า 300 ไมโครวินาที
  • พัฒนาบนเทคโนโลยี .NET สมัยใหม่ โดยมุ่งเน้นโครงสร้างแบบข้ามแพลตฟอร์ม ขยายต่อได้ และทันสมัย
    • ออกแบบมาเพื่อให้ง่ายต่อการพัฒนาและต่อยอด โดยไม่ต้องแลกกับประสิทธิภาพในกรณีใช้งานทั่วไป
    • ใช้ประโยชน์จาก ecosystem ของไลบรารี .NET เพื่อขยายขอบเขตของ API และเปิดช่องให้ปรับแต่งเพิ่มได้
    • ให้ประสิทธิภาพระดับสูงทั้งบน Linux และ Windows
  • หากต้องการบริการแบบ fully managed สามารถใช้ Azure Cosmos DB Garnet Cache ซึ่งนำ Garnet ไปให้บริการเป็นโซลูชันแคชระดับองค์กรที่มี high availability, การรับประกันประสิทธิภาพ และไม่ต้องจัดการโครงสร้างพื้นฐานเอง

ฟีเจอร์ที่เพิ่มเข้ามาล่าสุดและงานวิจัย

  • Vector Sets Preview รองรับการค้นหา approximate nearest neighbor
    • สร้างบนอัลกอริทึม DiskANN และเอนจินจัดเก็บข้อมูล Tsavorite ของ Garnet
    • จากผลลัพธ์เบื้องต้น Garnet ทำได้ดีกว่าในด้าน QPS, p99 latency และ recall
  • Range Index Preview มอบ secondary range/equality index บนคีย์ของ Garnet
  • งานวิจัยของ Garnet มีกำหนดตีพิมพ์ใน VLDB 2026
    • ชื่อบทความคือ Garnet: A Next-Generation Cache-Store for Accelerating Applications and Services
    • มี PDF ให้ดาวน์โหลด

API และโมเดลการขยายความสามารถ

  • Garnet รองรับ API ที่หลากหลาย
    • raw string: get, set, key expiration
    • analytical operation: HyperLogLog, Bitmap
    • object operation: sorted set, list เป็นต้น
  • รองรับธุรกรรมหลายคีย์
    • RESP transaction ฝั่งไคลเอนต์
    • stored procedure และโมดูลฝั่งเซิร์ฟเวอร์ที่พัฒนาด้วย C#
  • ผู้ใช้สามารถสร้าง custom operation ได้ทั้งกับ raw string และชนิดอ็อบเจ็กต์ที่กำหนดเอง
    • ใช้ประโยชน์จากความสะดวกและความปลอดภัยของ C# เพื่อลดอุปสรรคในการพัฒนาส่วนขยายแบบคัสตอม
  • รองรับ Lua scripting ด้วย

เครือข่าย ความปลอดภัย และเลเยอร์จัดเก็บข้อมูล

  • Garnet ใช้ เลเยอร์เครือข่าย ที่รวดเร็วและถอดเปลี่ยนได้
    • ทำให้สามารถขยายไปใช้สิ่งอย่าง kernel bypass stack ได้ในอนาคต
  • การสื่อสารแบบปลอดภัยรองรับ TLS ผ่านไลบรารี SslStream ของ .NET
  • มีการควบคุมการเข้าถึงขั้นพื้นฐาน
  • เลเยอร์จัดเก็บข้อมูล Tsavorite ถูกออกแบบมาเพื่อประสิทธิภาพสูง และมีฟังก์ชันฐานข้อมูลหลายอย่าง
    • scalability ระดับเธรด
    • การจัดเก็บแบบหลายชั้นที่รวมหน่วยความจำ, SSD และคลาวด์สตอเรจ
    • non-blocking checkpoint ที่รวดเร็ว
    • recovery
    • operation log เพื่อความทนทาน
    • ธุรกรรมหลายคีย์
    • การจัดการและนำหน่วยความจำกลับมาใช้ใหม่ได้ดียิ่งขึ้น

โครงสร้างการออกแบบ

  • การออกแบบของ Garnet เป็นการออกแบบใหม่ทั้งสแต็กของแคชสโตร์ ตั้งแต่การรับแพ็กเก็ตเครือข่าย การแยกวิเคราะห์และประมวลผลคำสั่งฐานข้อมูล ไปจนถึงการโต้ตอบกับระบบจัดเก็บข้อมูล
  • เลเยอร์เครือข่ายอิงตาม สถาปัตยกรรม shared memory
    • การประมวลผล TLS และการโต้ตอบกับระบบจัดเก็บข้อมูลเกิดขึ้นบนเธรดที่ทำงานเมื่อ network IO เสร็จสิ้น
    • ช่วยหลีกเลี่ยงโอเวอร์เฮดจากการสลับเธรดในกรณีทั่วไป
    • แทนที่จะย้ายข้อมูลไปยัง shard ที่เหมาะสมของเซิร์ฟเวอร์เหมือนการออกแบบเครือข่ายแบบ shuffle ดั้งเดิม ระบบจะอาศัยความสอดคล้องของ CPU cache เพื่อนำข้อมูลมาสู่ลอจิกที่ประมวลผล
  • โครงสร้างการจัดเก็บประกอบด้วยคีย์-แวลูสโตร์ Tsavorite สองชุดที่เชื่อมกันด้วย operation log แบบรวม
    • main store ปรับให้เหมาะกับการทำงานของ raw string และจัดการหน่วยความจำอย่างระมัดระวังเพื่อหลีกเลี่ยง garbage collection
    • object store แบบเลือกใช้ ปรับให้เหมาะกับอ็อบเจ็กต์ที่ซับซ้อนและชนิดข้อมูลที่ผู้ใช้กำหนดเอง
    • object store รองรับชนิดข้อมูลอย่าง Sorted Set, Set, Hash, List, Geo
    • ชนิดข้อมูลใน object store ใช้ประโยชน์จาก ecosystem ของไลบรารี .NET ในการอิมพลีเมนต์ปัจจุบัน
    • อ็อบเจ็กต์จะถูกเก็บในรูปแบบที่อัปเดตได้มีประสิทธิภาพบน memory heap และในรูปแบบ serialized บนดิสก์
  • มีแผนจะพิจารณาการใช้ดัชนีและล็อกแบบรวมเพื่อให้ง่ายต่อการบำรุงรักษาในอนาคต
  • จุดเด่นที่แตกต่างของ Garnet คือ Tsavorite storage API แบบคอดคอขวดแคบ
    • บน API นี้ มีการสร้างพื้นผิว RESP API ที่ใหญ่ สมบูรณ์ และขยายได้
    • ประกอบด้วยการอ่าน, upsert, การลบ และการทำ atomic read-modify-write
    • ผ่าน asynchronous callback ทำให้ลอจิกของ Garnet สามารถแทรกเข้าไปได้หลายจุดระหว่างแต่ละ operation
    • แยก concerns ด้าน parsing และ query processing ออกจากรายละเอียดของระบบจัดเก็บ เช่น concurrency, storage tiering และ checkpoint
  • ธุรกรรมหลายคีย์ใช้ two-phase locking

โหมดคลัสเตอร์และข้อจำกัดด้านการปฏิบัติการ

  • นอกจากการทำงานแบบโหนดเดียว Garnet ยังรองรับ cluster mode
    • สามารถสร้างและจัดการ deployment ที่มี sharding และ replication ได้
    • รองรับวิธีย้ายคีย์แบบมีประสิทธิภาพและไดนามิกเพื่อทำ shard rebalancing
  • ผู้ใช้สามารถสร้างและจัดการคลัสเตอร์ Garnet ได้ด้วยคำสั่งมาตรฐานของ Redis cluster
  • โหนดต่าง ๆ จะทำ gossip เพื่อแชร์และพัฒนาสถานะของคลัสเตอร์ร่วมกัน
  • การออกแบบ cluster mode ของ Garnet ปัจจุบันเป็นแบบ passive
    • ไม่มีการอิมพลีเมนต์ leader election
    • ตอบสนองต่อคำสั่งคลัสเตอร์ที่ออกโดย control plane ที่ผู้ใช้จัดเตรียมไว้
    • รายละเอียดที่เกี่ยวข้องอยู่ใน เอกสาร control plane

เอกสารและไลเซนส์

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

 
GN⁺ 2024-03-20
ความคิดเห็นจาก Hacker News
  • ถ้าดูกราฟประสิทธิภาพเบนช์มาร์ก(https://microsoft.github.io/garnet/docs/benchmarking/results...) จะเห็นว่า ปริมาณงานของ GET สูงกว่า Dragonfly มากกว่า 10 เท่า
    ค่า latency ที่เปอร์เซ็นไทล์ 50 สูงกว่า Dragonfly เล็กน้อย แต่เปอร์เซ็นไทล์ 99 กลับต่ำกว่าเล็กน้อย
    ทั้ง Garnet และ Dragonfly มีทั้ง throughput และ latency ดีกว่า Redis มาก จนดูเหมือนว่า Redis น่าจะต้องการการปรับแต่งประสิทธิภาพพอสมควร

    • Redis เป็นแบบ single-threaded จึงเรียบง่ายและได้ผลดี
      ไม่แน่ใจว่าจำเป็นต้องปรับแต่งจริงไหม และตอนนี้ก็มีทางเลือกอยู่แล้ว 3 ตัว
      แต่ Garnet น่าประทับใจตรงที่เป็นทางเลือกตัวแรกที่แซง Redis ได้ทั้งในสภาวะ concurrent ต่ำและสูง เลยอยากลองใช้เร็ว ๆ
    • สิ่งที่น่าประหลาดใจที่สุดคือโปรเจ็กต์นี้พัฒนาด้วย C#
      Dragonfly เขียนด้วย C++ และ Redis เขียนด้วย C
    • น่าทึ่งที่ Garnet ซึ่งสร้างด้วย ภาษาแบบ garbage collection อย่าง C# สามารถเอาชนะ Redis/Dragonfly ได้
  • Tsavorite ซึ่งเป็นชั้นจัดเก็บข้อมูลของ Garnet แยกออกมาจาก FASTER แบบโอเพนซอร์ส และมีฟีเจอร์ฐานข้อมูลที่แข็งแกร่ง เช่น การขยายสเกลของเธรด, ที่เก็บข้อมูลแบบหลายชั้น (หน่วยความจำ, SSD, cloud storage), checkpoint แบบไม่บล็อกที่รวดเร็ว, การกู้คืน, work log เพื่อความทนทาน, ธุรกรรมหลายคีย์, รวมถึงการจัดการและใช้หน่วยความจำซ้ำได้ดีขึ้น
    https://www.microsoft.com/en-us/research/blog/introducing-ga...

    • ก่อนหน้านี้เคยไล่อ่าน การทำงานของ FASTER
      ตอนนั้นคิดว่ามันดูมีอนาคตมากในฐานะไลบรารี persistence สำหรับโปรเจ็กต์พิสูจน์แนวคิดที่มีความต้องการด้านประสิทธิภาพสูงที่กำลังทำอยู่
      อนึ่ง ดูเหมือนว่าทั้งสองโปรเจ็กต์จะมีคนเดียวกันเป็นผู้นำ [1]
      [1]: https://github.com/badrishc
    • เป็นอีกหนึ่ง โปรเจ็กต์โอเพนซอร์ส ที่ Microsoft สร้างขึ้น
  • โปรเจ็กต์ที่ Microsoft และทีม .NET ลงมือแฮ็กอินฟราด้วยตัวเองแบบนี้น่าประทับใจทีเดียว
    Yarp เป็นเครื่องมือสำหรับ reverse proxy/API gateway/หรืออะไรก็ตามที่ต้องการ และตอนนี้ Garnet ก็มาในฝั่ง memory cache
    ดูเหมือนว่าพวกเขามีความต้องการภายในสูงมาก และก็เต็มใจจะแชร์สิ่งนั้นออกมาด้วย

  • อยากให้มีของแบบนี้ฝังมาใน Azure App Service
    จะได้ไม่ต้องพึ่งบริการรีโมตเพราะเรื่อง caching เสมอไป
    แต่ก่อนบน IIS มักใช้ ที่เก็บ session state นอกโปรเซส สำหรับแอป ASP.NET
    เพื่อให้เวลาที่โปรเซสของเว็บแอปรีสตาร์ต ผู้ใช้จะไม่เสีย session แล้วต้องล็อกอินใหม่ทั้งหมด
    แน่นอนว่าจะเก็บไว้ในที่เก็บข้อมูลส่วนกลางอย่าง SQL Server ก็ได้ แต่แบบนั้นทุกคำขอหน้าเว็บต้องรอโหลด session state ก่อนถึงจะประมวลผลได้
    ปกติ session state มักมีการล็อกไม่ทางใดก็ทางหนึ่ง จึงมีปัญหาด้านประสิทธิภาพมากเช่นกัน
    วิธีแก้ทั่วไปในปัจจุบันคือใช้ Redis สำหรับ cache และ session state ซึ่งโดยรวมก็พอใช้ได้
    throughput สูง แต่ Redis ใน Azure เป็นทรัพยากรแยกต่างหากและแพงเกินเหตุ
    ไม่อยากจ่ายราคาแบบ Oracle DB ให้กับของที่เรียบง่ายขนาดนี้ และการตั้งค่าการเชื่อมต่อก็ค่อนข้างจุกจิก
    บทความนี้พูดถึงเวลา response 300 ไมโครวินาที แต่ในดีไซน์แบบ zone-redundant มันแทบไม่มีความหมาย เพราะ Azure load balancer ทุกตัวใช้การเลือกโซนแบบสุ่ม
    เว็บเซิร์ฟเวอร์ในโซนสุ่มจะถูกเลือก แล้วจากนั้นก็ไปเชื่อมกับ cache server ในโซนสุ่มอีกที
    ถ้าเซิร์ฟเวอร์นั้นไม่มีคีย์ ก็อาจต้องไปอีกโซนสุ่มเพื่อดึงข้อมูล cache มาอีก
    ทราฟฟิกเลยเด้งไปมาระหว่างดาต้าเซ็นเตอร์ ทำให้เกิด latency 1-3ms ซึ่งช้ากว่าตัวเลขโฆษณาของ Garnet ได้มากสุดถึง 10 เท่า
    สถานการณ์ในอุดมคติคือสิ่งอย่าง reliable collections[1] ของ Microsoft Service Fabric
    ที่รันแบบโลคัลบนแต่ละโฮสต์โนดและทำสำเนาไปยังอีกสองโนด
    เว็บแอปจะสามารถอ่านค่า cache จากโฮสต์จริงตัวเดิมได้เสมอ
    ในบางกรณี latency ลงไปถึงระดับไมโครวินาทีเลขหลักเดียว ซึ่งไม่ว่าบริการภายนอกจะปรับแต่งมาดีแค่ไหน หากใช้รูปแบบ load balancing ธรรมดาก็ยังช้ากว่านี้หลายพันเท่า
    ไม่ได้อยากได้แค่เร็วกว่า Redis 30% แต่ต้องการ เร็วกว่า 3,000 เท่า
    [1] https://learn.microsoft.com/en-us/azure/service-fabric/servi...

    • นี่แหละเหตุผลที่ Kubernetes ที่ใช้ Cilium ดี
      มันทำให้ service วิ่งไปยัง local service ได้เสมอ หรือจะจัดเป็น topology การ routing แบบอื่นก็ได้
      ดีมากสำหรับ DNS หรือ application cache
  • เป็น ตัวแทน Redis ที่ตัวเลขเบนช์มาร์กด้าน latency และ throughput น่าประทับใจทีเดียว
    สงสัยว่าถ้านำไปใช้งานจริงบนสแตกที่ไม่ใช่ Azure จะออกมาเป็นอย่างไร

    • ไม่แน่ใจว่ามันเป็น drop-in replacement จริงหรือเปล่า
      ไม่เห็นมีระบุเรื่องรองรับ xstream
  • Garnet being multi-threaded, MSET is not atomic. For an atomic version of MSET, you would need to express it as a transaction (stored procedure).
    ตรงนี้ยังไม่ค่อยเข้าใจ
    ทำไมไม่ห่อคำสั่งด้วยทรานแซกชันภายในเพื่อให้คำสั่งเป็น atomic ไปเลย
    แล้วก็สงสัยด้วยว่ามี กับดักเรื่อง atomicity อะไรอีกบ้าง

    • ถ้าทำแบบนั้น คนที่ไม่ต้องการ atomicity ของ MSET ก็จะต้องแบกรับ ต้นทุนด้านประสิทธิภาพ ไปด้วย และก็ไม่มีทางปิดทรานแซกชันนั้นได้
      แต่ในอีกด้านหนึ่ง ถ้าตั้งเป้าเป็นตัวแทน Redis แบบ drop-in ก็ถือว่าเป็นปัญหา เพราะ Redis รับประกัน atomicity
      อย่างน้อยถ้าเป้าหมายการออกแบบคือการเป็น drop-in replacement ก็น่าจะมีตัวเลือกให้เลือกระหว่างความเข้ากันได้กับประสิทธิภาพได้
  • ต้องบอกว่าน่าประทับใจจริง ๆ
    Microsoft Research มีโปรเจ็กต์เจ๋ง ๆ ออกมาเป็นระยะ ๆ และการได้ทำงานวิจัยพัฒนาไปพร้อมกับรับเงินเดือนก็น่าจะสนุกดี
    อยากเห็นบริษัทยักษ์ใหญ่ทำโปรเจ็กต์แนววิจัยพัฒนาที่เป็นประโยชน์ต่อทั้งอุตสาหกรรมมากกว่านี้
    ถ้า Hashicorp กำลังจะถูกขาย ก็หวังว่าจะได้ผู้ซื้อที่ดี

  • สำหรับคนที่ต้องการรัน เซิร์ฟเวอร์ที่เข้ากันได้กับ Redis บน Microsoft Windows Server โดยไม่ต้องพึ่ง WSL2 นี่ถือเป็นข่าวดีมาก
    เมื่อก่อนเคยมี Redis port[1] แต่ตอนนี้ถูกเก็บถาวรแล้ว มีปัญหาเรื่องการใช้หน่วยความจำ (เท่าที่รู้ส่วนใหญ่เพราะ memory-mapped file) และไม่ได้รับการสนับสนุนอีกต่อไป
    เรื่องที่เขียนด้วย C# ก็ทำให้รู้สึกสนใจเป็นการส่วนตัวมาก
    C# เป็นภาษาหลักของผม เลยอยากหาเวลาไปขุดโค้ดดู
    [1]: https://github.com/microsoftarchive/redis

  • อยากเห็นว่ามีการใช้สิ่งนี้ที่ไหนใน production จริงบ้าง
    มีประโยคว่า “หลังจากผ่าน unit test หลายพันรายการและได้ลอง deploy Garnet ใช้งานจริงมาหลายปีกับทีม 1st-party ของ Microsoft เราก็รู้สึกว่าถึงเวลาที่จะเปิดเผยต่อสาธารณะแล้ว”
    https://microsoft.github.io/garnet/blog

  • ดูจากคอมเมนต์ที่นี่ เหมือนตอนนี้ไม่มีใครใช้ memcached กันแล้ว

    • ครั้งสุดท้ายที่ใช้คงราว ๆ ปี 2016 และการตั้งค่าก็ไม่ได้ง่ายนัก
      ตอนนั้นต้องการ LRU cache แต่มีตัวเลือกหลายอย่างและคำอธิบายก็ไม่ค่อยชัด เลยไม่รู้ว่าทำไมมันถึงไล่ item ออกตลอด
      พอเปลี่ยนไปใช้ Redis การตั้งค่าง่ายกว่าและทำงานได้ตรงตามที่คาดไว้