ย้อนกลับไปเมื่อปี 2007 Amazon ต้องการแก้ปัญหา relational database ของตัวเองที่ไม่สามารถ scale ได้ดั่งใจอยาก ทีมงานของ Amazon จึงตัดสินใจคิดค้น database ใหม่ที่ไม่ใช้ consistency ของ SQL แต่นำเสนอการใช้ eventual consistency เข้ามาแทน พร้อมยังเผยแพร่ Dynamo paper เพื่ออธิบายหลักคิดทั้งหมดของแนวคิดนี้อีกด้วย

ผ่านไปแค่ปีเดียวหลังจากที่ Dynamo paper ถูกเผยแพร่ Facebook ก็ดำเนินมาถึงจุดที่ Amazon เคยประสบปัญหาเช่นกัน คือต้องการ scale Inbox Search ให้เร็วกว่าที่เป็นอยู่ Facebook จึงตัดสินใจคิดค้น Cassandra ขึ้นมาแก้ปัญหา โดยได้รับแรงบันดาลใจทั้งจาก Dynamo และ BigTable

ดังนั้น Cassandra จึงมีวิธีการ distribute data ในแบบ Dynamo คือเชิดชู eventual consistency แต่กลับเลือกใช้ data model แบบ BigTable แทน

เนื่องจากเป็น database ประเภท AP ตาม CAP theorem - sacrifice consistency เพื่อ high availability - Cassandra จึงไม่เหมาะกับงานที่ต้องการ strong consistency แต่เหมาะกับงานที่ต้องการ write high throughput และ low latency สูงๆ เช่น Real time application, iot logs, หรือใช้เป็น time series database ก็ได้

แนะนำให้อ่าน post นี้ควบคู่ไปกับ สรุป SSTable & B-tree index และ Hbase ครับ

ลักษณะเฉพาะ

คำศัพท์พื้นฐาน

เนื่องจากการอธิบาย Cassandra ในบทเดียวเป็นไปได้ยากมาก สำหรับคนที่ยังงงๆอยู่ ให้ข้ามไปอ่านวิธีการทำงานได้เลยครับ

cassandra-token-ring

หลักการทำงาน

Cassandra ใช้หลักการทำงานที่เรียกว่า SSTables และ LSMTree ซึ่งเจ้าสองเทคนิคนี้แหละที่เป็นเคล็ดลับความเร็วในการ write ของมัน

แนะนำให้อ่านควบคู่ไปกับ สรุป SSTable & B-tree index

Write

cassandra-write
https://docs.datastax.com/en/archived/cassandra/3.0/cassandra/dml/dmlHowDataWritten.html
  1. เลือก node ที่จะ write โดยทำการ hash primary key เพื่อหา token value ที่เหมาะสมและหา node ที่ดูแล token range นั้นๆอยู่
  2. Cassandra writes data แบบ sequential write หรือ append log ไปเรื่อยๆ ทำให้ write ได้เร็ว
  3. ทุกๆครั้งที่ Cassandra writes, จะทำการ commit log (Write Ahead Log/ WAL) ลงใน disk ไปพร้อมกัน โดยใน WAL นั้นจะเก็บ record ทั้งหมดไว้ก่อนที่ data จะโดน memtable flush ลง disk เพื่อป้องกัน data สูญหายก่อนทำการ flush
  4. ต่อจากข้อ 3 Cassandra จะยังไม่ write ลง disk ในทันที เนื่องจากมันช้า จึงใช้การ write ลงใน Memtable (in-memory) ก่อน ซึ่งตัว memtable จะเหมือนกับ SSTable (on disk) เลย เพียงแค่ทำงานอยู่ใน memory เท่านั้น เมื่อถึงจุด threshold ที่เราตั้งไว้ จึง flush หรือการ write ลง persistent disk
  5. ก่อน flush จะทำการสร้าง Index ไปในตัวโดย sort string ของ Primary key ไว้ (hash แล้วนะครับ) และนั้นคือที่มาของชื่อ SSTable
  6. SSTable บน disk เป็น immutable data จะไม่มีการทำ update หรือ delete row ตรงๆเนื่องจาก operation เหล่านี้ต้องการ I/O ที่สูง
  7. เพื่อแก้ปัญหา update/delete และเป็นการ save พื้นที่ใน disk ด้วยไปในตัว Cassandra จะใช้เทคนิคที่เรียกว่า Compaction - merge หลายๆ SSTable เล็กเข้าด้วยกันและใช้ timestamp เป็นตัวดูว่า record ใน SSTable ไหนใหม่กว่ากัน และจะ return SSTable ที่มี data ใหม่ที่สุดตาม timestamp (last-write-wins)
  8. หลักการลบก็คล้ายๆกัน โดยใช้ Tomestone mark row ที่จะ delete ไว้แล้วค่อยมาทำ Batch deletion ทีเดียวตอน compact segement file เลย
cassandra-compaction
https://docs.datastax.com/en/archived/cassandra/3.0/cassandra/dml/dmlHowDataMaintain.html

Read

cassandra-read
https://docs.datastax.com/en/archived/cassandra/3.0/cassandra/dml/dmlAboutReads.html
  1. Client สามารถเริ่มอ่านจาก nodeใดก็ได้ โดยตัว Cassandra เองจะเลือกให้เราตาม closest location, non-busy node หรือ random
  2. Node ที่ Client connect จะเรียกว่า ‘Coordinator’ หาก ​data ไม่ได้อยู่ใน Coordinator node, ตัว Coordinator จะทำการถาม node อื่นให้ผ่าน Gossip protocol ว่า node ใดกันแน่ที่มีจริงๆ
  3. จะเริ่มหาจาก Memtable ก่อนเนื่องจากเข้าถึงได้เร็วสุด, ตามด้วย row cache (หากมี), Bloom filter, partition key cache และ ​SSTable ตามลำดับ
  4. เราสามารถปรับแต่ง consistency ได้ โดยตัว node จะทำการ check กับ node อื่นที่ทำ replicas ไว้เพื่อตรวจสอบ consistency ให้เรา: ANY (ใครก็ได้), ONE (one node ของ replicas ที่ดูแล key นั้นๆ), QUORUM (ส่วนใหญ่ของ replicas), LOCAL_QUORUM (ส่วนใหญ่ของ replicas ใน data center เดียวกัน), ALL (ทุก replicas)