เปรียบเทียบ Hazelcast กับ Redis สำหรับ In-Memory Caching Part 3
สวัสดีครับทุกคนหลังจากที่เราได้เห็นทั้งแนวคิดของ Stream Processing (Hazelcast Jet) กับตัวอย่างการใช้งานจริงสำหรับส่วนของ In-Memory (Hazelcast IMDG)ในการ Caching ไปแล้วก็จะเห็นได้ว่า Hazelcast นั้นเป็น Platform เกี่ยวกับการ Processing Data ซึ่งทำได้หลายๆอย่างบน Platform ของตัวเองซึ่งจะเป็นจุดที่ Overlap กับอีกหลายๆ Tool
แต่ในครั้งนี้เราจะเปรียบเทียบเฉพาะส่วนของความสามารถ Feature ที่ Hazelcast มีในส่วนของ In-Memory ก็จะมี Tool ที่ใกล้เคียงกันอย่าง Redis โดยการใช้งาน Redis แบบพื้นฐานกับ Node.JS ผมก็เคยเขียนไว้ที่ Blog นี้ ในแว้บแรกเราก็คงจะรู้สึกว่าทั้งสอง Tool นี้มีความคล้ายกันแบบมากๆและปัจจุบันก็มีการพัฒนา Feature ให้เพิ่มเท่าๆกันตามไปอีกโดยผมจึงได้สรุปข้อมูลเปรียบเทียบแตกต่างระหว่าง Redis และ Hazelcast มาให้ดังนี้ทั้งหมด 5 ประเภทดังนี้
- Caching
- Clustering
- Querying
- Streaming
- Compute
1.Caching
เริ่มจากในหัวข้อแรกคือการ Caching ซึ่ง Usecase ที่ทำให้เราตัดสินใจจะใช้ Tool อย่าง Redis หรือ Hazelcast IMDG ก็ถือการที่เราอยากให้ข้อมูลจากเดิมที่เคยเก็บไว้ใน Disk Storage ที่มีการเข้าถึงช้าแต่ถูกเรียกใช้บ่อยๆซ้ำๆ Pattern เดิมๆสามารถดึงได้เร็วขึ้น โดยไม่ต้องไปโหลดจาก Disk ใหม่ทุกครั้งตัวอย่างการใช้งานจริงก็จะเป็นการ Cache ค่าบางอย่างจาก SQL Database มาฝากไว้ที่ Caching Layer ซึ่งถ้าเราใช้ Spring Boot เราก็สามารถใช้พวก API อย่าง Spring Caching เพื่อให้มี Annotation ในการช่วยตรวจจับค่า Key ของ Value ที่เราต้องการจะ Cache หรือจะดึงมาได้ซึ่งก็มี Blog ที่พี่ Phayao ได้เขียนไว้ในตัวอย่างการใช้ Spring Boot Redis Cache
โดยถ้าหากเราเปลี่ยนมาใช้เป็น Hazelcast เองเราก็สามารถใช้ Interface ของ Spring Boot ได้เหมือนเดิมตามปกติเช่นกันซึ่งเราสามารถดูตัวอย่างได้ที่ Blog
แต่ในส่วนของเทคนิคความแตกต่างของ Hazelcast กับ Redis กับการ Caching นั้นจะอยู่ที่ Redis จะต้องใช้ท่าการ Cache แบบ “Cache aside” pattern เท่านั้นซึ่งท่านี้จะทำให้เกิด Hop ของ Network มากขึ้นเพราะคนที่ทำหน้าที่จัดการเช็คว่า Cache นั้นกำลังมีอยู่หรือเปล่าจะต้องทำที่ฝั่งของ Application โดยคนเขียนโค้ดต้องเป็นคนออกแบบจัดการ ส่วนถ้าเป็น Hazelcast สามารถมีได้ทั้งสองแบบคือ “Cache aside” และ “Read/Write Through Cache” โดยจะมีเฉพาะ Logic ในการ update และ read เท่านั้นที่ต้องเขียนเอง หรือ Pattern อื่นอย่าง “write behind” ก็สามารถทำได้ซึ่งจะต่างจาก Redis ที่รองรับเฉพาะ Pattern “Cache-aside”
โดยภาพบนคือการเปรียบเทียบระหว่าง Cache-Aside ที่มีทั้งคู่และ Read/Write Through Pattern ที่มีเฉพาะใน Hazelcast โดยให้เราดูจากฝั่งของภาพซ้ายก่อนจะเห็นว่าตัวโปรแกรมจำเป็นที่จะต้องมี Database Library Client ในการเช็คเทียบ Sync Logic ว่าถ้าหาก ขอเรียกข้อมูลไปหา Cache Cluster แล้วพบว่าข้อมูลไม่มีก็จะต้องไปดึงข้อมูลจาก Database ต่อซึ่งถ้าหากภาษาหรือโปรแกรมของเราไม่มี Library อย่าง Spring Cache ให้ก็คงต้องเขียน If-Else เองเพิ่มเยอะเหมือนกัน แต่ถึงจะใช้ Spring Cache แล้วก็จะพบว่าจริงๆก็ยังต้องมีในส่วนของการจัดการ Database อยู่ดีดังนั้นในตัว Service Application ของเราก็จะต้องมีการต่อตรงไปหา Database เช่นกันและเมื่อได้ข้อมูลจาก Database ไปแล้วก็ค่อยบันทึกลงไปใน Cache Cluster จากนั้นจึงจะ Return ผลลัพธ์ออกไป
แต่สำหรับ Read&Write Though Pattern ที่มีเฉพาะใน Hazelcast ก็คือ Pattern ที่ Layer ของการจัดการตัว Database นั้นจะไปเกาะกับที่ Cache Cluster แทนทำให้ตัว Code Service Application เราไม่จำเป็นต้องรู้จัก Database ตรงๆก็ได้ตัว Code ก็จะลดความซับซ้อนในการจัดการ Logic ของ Database นั่นเองด้วยภาพการอ่านแบบต่อทะลุไปเป็น Layer Cache กับ Layer Database ก็เลยเรียกว่า Passthrough (ผ่านทะลุไป) และตัว Sync Logic ซึ่งอาจจะมี Inconsistency Gap ระหว่าง Cache กับ Database เช่น Cache อัพเดทสำเร็จแต่ว่าบันทึกลง DB ปุ๊ปมี Error เกิดข้ึนพวกนี้ก็ต้องไปเขียนในService Application ทำให้เพิ่มความซับซ้อนขึ้นมาได้ แต่ถ้าเราเปลี่ยนไปใช้ท่า Read/Write Though ก็จะลดความซับซ้อนในส่วนนี้ไปได้เพราะถูกจัดการใน Layer ของ Cache Cluster ที่ต่อตรงไปหา Database ตั้งแต่แรก และสังเกตว่าจำนวน Hop ที่เกิดขึ้นก็จะมีมากกว่าท่า Read/Write Through ซึ่งก็อาจจะทำให้เกิด Latency/Delay เพิ่มมากขึ้นไปอีกได้นั่นเอง
ส่วน Pattern สุดท้ายคือ Write Behind ซึ่งตอนนี้จะแตกต่างจากที่ทาง Blog ของ Hazelcast บอกเอาไว้นิดหน่อยคือปัจจบันนี้ Redis ก็สามารถทำได้เหมือนกัน ใน “Redis-Enteprise Version”
ซึ่งเทคนิคนี้จะใช้ในการแก้ปัญหากรณีที่ Database หรือ Datastore ที่เราจะนำข้อมูลเหล่านั้นมา Caching มีความช้ากว่าปกติมาก แบบรับการเขียนต่อไปค่อยไหวแล้วดังนั้นการ Acknowledgement ระหว่าง Servuce Application กับ Cache จะให้ถือว่ายอมรับให้ผ่านไปก่อนเลยหากสามารถเขียนลงไปใน Cache ได้แล้ว แต่จังหวะของการ Sync บันทึกลง Database/Datastore เรานั้นจะอยู่ในรูปแบบ Asynchronous นั่นเองด้วยการที่เข้า Queue รอไว้ก่อนที่ Hazelcast Platform และค่อยๆทยอย Sync ลงไป Datastore ทีหลัง ด้วยวิธีนี้ทำให้ Latency ระหว่างที่ต้องรอทั้ง Datastore และ Cache Layer Acknowledge ทั้งคู่พร้อมๆกันจึงถูกตัดไปเหลือแค่ Cache Layer เท่านั้นทำให้ Application/Service สามารถตอบสนองได้เร็วขึ้น ซึ่งถ้าสนใจ Pattern เหล่านี้เพิ่มเติมสามารถไปดูต่อได้ที่การเปรียบนี้ Cache pattern นี้เลย
2. Cluster Maintenance
ตัว Concept ของ Hazelcast นั้นถูกสร้างมาโดยไม่มีด้วยการที่ไม่มี Master Node และ Backup Node ตั้งแต่แรกทำให้การ Maintenance Cluster นั้นง่ายกว่าถ้าเทียบกับ Redis ที่มีเรื่องของการทำ Sharding ซึ่งในสมัยก่อน Redis นั้นต้องทำ Manual Resharding ถ้าหากใช้ Redis Opensource แต่ในปัจจุบัน Redis Cluster สามารถทำ Auto Re-shardining ได้แล้ว โดยไม่จำเป็นต้องเป็น Enterprise Version อีกต่อไป แต่ในเรื่องของ Architecture Hazelcast นั้นมีรูปแบบเป็น Peer-to-Peer ซึ่งไม่มีแนวคิดของ Master หรือ Slave จึงไม่มี Single Point of Failure และจากบทความของ Part 1 เรื่องการที่ Hazelcast นั้นจะพยายามให้มีข้อมูล Backup สำรองในทุกๆ Node แบบเท่าๆกันตลอดทำให้จึงไม่เกิด Single Point of Failure
ซึ่งถ้าเป็น Redis ในสมัยก่อนเมื่อนานมาแล้วก็จะมีโอกาสเกิด Single Point of Failure ได้แต่ในปัจจุบัน Redis ก็มีการพัฒนามาหลายอย่างจนมี ทั้ง Sentinal และ Redis Cluster ที่เข้ามาแก้ไขปัญหา Single Point of Failure ไปหมดแล้วจึงเรียกได้ว่าข้อนี้เป็นอะไรที่ใกล้เคียงกันมากๆถ้าไม่นับจุดเล็กๆอย่างที่ Hazelcast แค่ Start Node มาก็ได้พวก Feature เหล่านี้ได้เลยอย่างที่ได้แสดงให้ดูใน Blog Part 2 ไปในเรื่องของการจำลอง Node ล่มก็ยังสามารถ Query ข้อมูลที่อีก Node ได้ทันทีโดยไม่ต้องทำอะไรเพิ่มเติมเพราะ Hazelcast ถูกออกแบบมาแบบนี้ตั้งแต่ต้นอยู่แล้วนั่นเอง ส่วน Redis จำเป็นที่จะต้องรันคำสั่งเพิ่มนิดหน่อย (แค่บรรทัดเดียวเองเท่านั้น)
แต่ก็จะเห็นว่าจะ Official Docs ของ Redis ในปัจจุบันสำหรับการ Re-sharded ก็ยังไม่ครบสมบูรณ์นั่นเอง
สำหรับการ Deploy ด้วย Kubernetes Environment ก็เรียกได้ว่าทำได้ปกติดีทั้งคู่เพราะก็มีทั้ง Helm, Operator คล้ายๆกันหมด
สรุปทั้งหมดก็จะพบว่าข้อของ Cluster Maintenance นี้ก็อาจจะถือว่ารวมๆแล้วดูคล้ายๆกันแต่ต่างกันในรายละเอียดนิดเดียวเองครับผม ~
3. Querying
ทั้ง Redis และ Hazelcast นั้นเก็บข้อมูลในรูปแบบของ Key/Values ทั้งคู่แต่สำหรับตัว Hazelcast เองนั้นการใช้ Data structure แบบ Complex Type ที่หมายถึงพวก Class ที่มี Attribute เป็น Object Value ซ้อนๆกันเหมือน JSON หลายๆชั้นและรองรับการใช้ Graph Database ซึ่งในอดีตเมื่อนานแล้ว Redis ยังไม่มีรองรับ Graph Database และเรื่องของการ Query ในรูปแบบคล้ายๆกับ SQL ก็ยังไม่มีเช่นกันแต่ในปัจจุบันเรียกว่า Redis ก็เพิ่มขึ้นมาแล้วอย่าง SQL Interface แต่ว่าตัวนี้เองนั้นไม่เช่น Module Native ของ Redis โดยตรงที่ต่างจากแนวคิดของการ Query ผ่าน Mappings ของ Hazelcast ที่เป็น Native อยู่แล้วเพราะตัว Redis SQL เป็นตัวที่ถูกพัฒนาขึ้นมาขายโดย Thrid Party Library มากกว่า (มี license เสียเงิน) แต่ในส่วนของ Redis Graph และสุดท้ายก็คือเรื่องของการทำ Index ซึ่ง Hazelcast จะรองรับการทำ Index สำหรับ Query ข้อมูลตั้งแต่ต้นแบบ Native Indexing ที่ตัว Redis ไม่ได้ Support การทำ Native ตั้งแต่ต้นโดย Programmer จะต้องเป็นคนพัฒนาสร้าง Data Structure ของ Redis ขึ้นมาเองอ้างอิงจาก Redis Indexing ที่บอกด้วยเช่นกันว่า “Implementing and maintaining indexes with Redis is an advanced topic” ดังนั้น Redis เองก็อาจจะสรุปได้ว่าตัว Hazelcast นั้นมีแบบ Native ตั้งแต่แรกแต่สำหรับ Redis เองก็พัฒนามาตาม Hazelcast ไปเลยแต่บาง Component อาจจะเป็น Thrid Party อย่าง Redis SQL
4. Streaming
Hazelcast นั้นมาพร้อมกับ Streaming Platform ตั้งแต่แรกอยู่แล้วที่เราเห็นใน Hazelcast Jet แต่ด้วยปัจจุบันใน Redis Version 5 เองก็มี Redis Streaming ตามมาด้วยไปอีก 5555 ซึ่งเพราะด้วยการมี Feature เพิ่มมาตามๆกันทำให้เรื่องเทคนิคการ Caching หลายๆอย่างทั้ง Redis กับ Hazelcast ก็เลยเริ่มมีอะไรเหมือนกันไปหมด รวมถึงทั้งคู่ก็สามารถทำ Change Data Capture ได้ทั้งคู่เพราะว่าก็อิงมาจาก Dezium นั่นเองเหมือนตอนที่เราใช้ Kafka Connect ในการ Deploy Source/ Sink Connector ดังนั้นตรงข้อนี้ในปัจจุบันผมคิดว่าไม่น่าจะต่างกันมากครับ 5555
5. Computing
ในเรื่องการเขียน Event หรือ Script ในส่วนของ Engine เพื่อ Modify Script event ที่จะเกิดขึ้นเพื่อให้เราใช้คำสั่งโดยตรงไปยัง Node ทาง Redis นั้นจะใช้ Lua ส่วน Hazelcast นั้นรองรับด้วยการใช้ Java, Python, Go ซึ่งก็สามารถไปดูเพิ่มเติมได้ที่ Hazelcast Client Docs แต่ถ้าปกติเราไม่ได้แก้ไขเพื่อ tuning cluster อะไรโดยตรงเราก็น่าจะใช้แค่ Client ปกติอยู่แล้วซึ่งทั้ง Redis และ Hazelcast ก็สามารถเชื่อมต่อได้เยอะหลากหลายเหมือนกันทั้งคู่ไม่ต่างกัน
ซึ่งทั้งหมดนี้ก็เป็นข้อมูลการเปรียบเทียบเพื่อให้เพื่อนๆพี่ได้ลองไปดูเพิ่มเติมและตรวจสอบดูจากลิ้งค์ได้เลย อีกทีนึงว่าลึกๆแล้ว Hazelcast กัน Redis ทั้งสอง Platform นั้นอะไรน่าจะเหมาะสมกับเรามากที่สุดเพราะด้วยความที่ Feature ค่อยๆพัฒนาตามๆกันตลอดมาครับผม
อ้างอิง
Hazelcast and Redis: https://hazelcast.org/compare-with-redis/
Redis with Spring Boot Cache: https://phayao.medium.com/f00b9009796f
Hazelcast with Spring Boot Cache: https://hazelcast.com/blog/spring-boot/
Redis Write Behind for Enterprise Edition: https://docs.redis.com/latest/modules/redisgears/python/recipes/write-behind/
Redis Support Re-Shardding (not completely) 2022: https://redis.io/docs/manual/scaling/#scripting-a-resharding-operation
Hazelcast Architecture: https://docs.hazelcast.com/imdg/3.12/hazelcast-overview
Hazelcast support Native Index: https://docs.hazelcast.com/imdg/latest/query/how-distributed-query-works.html#indexing-queries
Redis Index is for advance user: https://redis.io/docs/reference/patterns/indexes/
Redis SQL is 3rd party commercial: https://redisql.com/
Redis Graph is support 2022: https://redis.io/docs/stack/graph/
Redis Streaming: https://redis.io/docs/manual/data-types/streams/