TrueTime adalah jam terdistribusi yang sangat tersedia dan disediakan untuk aplikasi di semua server Google1. TrueTime memungkinkan aplikasi menghasilkan stempel waktu yang meningkat secara monoton: aplikasi dapat menghitung stempel waktu T yang dijamin lebih besar dari stempel waktu T' jika T' selesai dibuat sebelum T mulai dibuat. Jaminan ini berlaku di semua server dan semua stempel waktu.
Fitur TrueTime ini digunakan oleh Spanner untuk menetapkan stempel waktu ke transaksi. Secara khusus, setiap transaksi diberi stempel waktu yang mencerminkan waktu saat Spanner menganggapnya telah terjadi. Karena Spanner menggunakan kontrol konkurensi multi-versi, jaminan urutan pada stempel waktu memungkinkan klien Spanner melakukan pembacaan yang konsisten di seluruh database (bahkan di beberapa region Cloud) tanpa memblokir operasi tulis.
Konsistensi eksternal
Spanner memberikan jaminan kontrol serentak terketat untuk transaksi kepada klien, yang disebut konsistensi eksternal2. Dalam konsistensi eksternal, sistem berperilaku seolah-olah semua transaksi dijalankan secara berurutan, meskipun Spanner sebenarnya menjalankannya di beberapa server (dan mungkin di beberapa datacenter) untuk performa dan ketersediaan yang lebih tinggi. Selain itu, jika satu transaksi selesai sebelum transaksi lain mulai melakukan commit, sistem akan menjamin bahwa klien tidak akan pernah melihat status yang menyertakan efek transaksi kedua, tetapi tidak untuk transaksi pertama. Secara intuitif, Spanner secara semantik tidak dapat dibedakan dari database satu mesin. Meskipun memberikan jaminan yang kuat, Spanner memungkinkan aplikasi mencapai performa yang sebanding dengan database yang memberikan jaminan yang lebih lemah (sebagai gantinya, performa yang lebih tinggi). Misalnya, seperti database yang mendukung isolasi snapshot, Spanner memungkinkan operasi tulis dilanjutkan tanpa diblokir oleh transaksi hanya baca, tetapi tanpa menunjukkan anomali yang diizinkan oleh isolasi snapshot.
Konsistensi eksternal sangat menyederhanakan pengembangan aplikasi. Misalnya, Anda telah membuat aplikasi perbankan di Spanner dan salah satu pelanggan Anda memulai dengan $50 di rekening giro dan $50 di rekening tabungan. Aplikasi Anda kemudian memulai alur kerja yang pertama kali melakukan transaksi T1 untuk mendepositkan $200 ke rekening tabungan, lalu mengeluarkan transaksi kedua T2 untuk mendebit $150 dari rekening giro. Selain itu, asumsikan bahwa pada akhir hari, saldo negatif di satu akun akan otomatis ditutup dari akun lain, dan pelanggan akan dikenai penalti jika total saldo di semua akunnya negatif kapan saja selama hari itu. Konsistensi eksternal menjamin bahwa karena T2 mulai melakukan commit setelah T1 selesai, semua pembaca database akan mengamati bahwa setoran T1 terjadi sebelum debit T2. Dengan kata lain, konsistensi eksternal menjamin bahwa tidak ada orang yang akan melihat status saat T2 terjadi sebelum T1; dengan kata lain, debit tidak akan pernah dikenai penalti karena dana tidak mencukupi.
Database tradisional yang menggunakan penyimpanan versi tunggal dan penguncian dua fase yang ketat memberikan konsistensi eksternal. Sayangnya, dalam sistem seperti itu, setiap kali aplikasi Anda ingin membaca data terbaru (yang kami sebut "pembacaan kuat"), sistem akan memperoleh kunci baca pada data, yang memblokir penulisan ke data yang sedang dibaca.
Stempel waktu dan kontrol konkurensi multi-versi (MVCC)
Untuk membaca tanpa memblokir operasi tulis, Spanner dan banyak sistem database lainnya menyimpan beberapa versi data yang tidak dapat diubah (sering disebut kontrol koeksistensi multi-versi). Operasi tulis membuat versi baru yang tidak dapat diubah yang stempel waktunya adalah stempel waktu transaksi tulis. "Pembacaan snapshot" pada stempel waktu menampilkan nilai versi terbaru sebelum stempel waktu tersebut, dan tidak perlu memblokir penulisan. Oleh karena itu, stempel waktu yang ditetapkan ke versi harus konsisten dengan urutan transaksi yang dapat diamati untuk melakukan commit. Kita menyebut properti ini "stempel waktu yang tepat"; perhatikan bahwa keberadaan stempel waktu yang tepat setara dengan konsistensi eksternal.
Untuk mengetahui alasan pentingnya stempel waktu yang tepat, pertimbangkan contoh perbankan dari bagian sebelumnya. Tanpa stempel waktu yang tepat, T2 dapat diberi stempel waktu yang lebih awal daripada stempel waktu yang ditetapkan untuk T1 (misalnya, jika sistem hipotetis menggunakan jam lokal, bukan TrueTime, dan jam server yang memproses T2 sedikit tertunda). Pembacaan snapshot kemudian dapat mencerminkan debit dari T2, tetapi bukan setoran T1, meskipun pelanggan melihat setoran selesai sebelum memulai debit.
Mendapatkan stempel waktu yang tepat adalah hal yang mudah untuk database satu mesin (misalnya, Anda cukup menetapkan stempel waktu dari penghitung global yang meningkat secara monoton). Mencapainya dalam sistem yang didistribusikan secara luas seperti Spanner, yang memerlukan server di seluruh dunia untuk menetapkan stempel waktu, jauh lebih sulit dilakukan secara efisien.
Spanner bergantung pada TrueTime untuk menghasilkan stempel waktu yang meningkat secara monoton. Spanner menggunakan stempel waktu ini dengan dua cara. Pertama, stempel waktu ini digunakan sebagai stempel waktu yang tepat untuk transaksi tulis tanpa memerlukan komunikasi global. Kedua, stempel waktu digunakan sebagai stempel waktu untuk pembacaan yang kuat, yang memungkinkan pembacaan yang kuat dijalankan dalam satu putaran komunikasi, bahkan pembacaan yang kuat yang mencakup beberapa server.
FAQ
Jaminan konsistensi apa yang diberikan Spanner?
Spanner menyediakan konsistensi eksternal, yang merupakan properti konsistensi terketat untuk sistem pemrosesan transaksi. Semua transaksi di Spanner memenuhi properti konsistensi ini, bukan hanya transaksi dalam partisi. Konsistensi eksternal menyatakan bahwa Spanner mengeksekusi transaksi dengan cara yang tidak dapat dibedakan dari sistem tempat transaksi dieksekusi secara serial, dan lebih jauh lagi, bahwa urutan serial konsisten dengan urutan transaksi yang dapat diamati untuk melakukan commit. Karena stempel waktu yang dihasilkan untuk transaksi sesuai dengan urutan serial, jika ada klien yang melihat transaksi T2 mulai melakukan commit setelah transaksi lain T1 selesai, sistem akan menetapkan stempel waktu ke T2 yang lebih tinggi daripada stempel waktu T1.
Apakah Spanner menyediakan linearitas?
Ya. Faktanya, Spanner memberikan konsistensi eksternal, yang merupakan properti yang lebih kuat daripada linearitas, karena linearitas tidak menjelaskan apa pun tentang perilaku transaksi. Linearitas adalah properti objek serentak yang mendukung operasi baca dan tulis atomik. Dalam database, "objek" biasanya berupa satu baris atau bahkan satu sel. Konsistensi eksternal adalah properti sistem pemrosesan transaksi, tempat klien menyintetisasikan transaksi secara dinamis yang berisi beberapa operasi baca dan tulis pada objek arbitrer. Linearitas dapat dilihat sebagai kasus khusus konsistensi eksternal, dengan transaksi hanya dapat berisi satu operasi baca atau tulis pada satu objek.
Apakah Spanner menyediakan serialisasi?
Ya. Faktanya, Spanner menyediakan konsistensi eksternal, yang merupakan properti yang lebih ketat daripada serialisasi. Sistem pemrosesan transaksi dapat diserialisasi jika menjalankan transaksi dengan cara yang tidak dapat dibedakan dari sistem tempat transaksi dijalankan secara serial. Spanner juga menjamin bahwa urutan serial konsisten dengan urutan transaksi yang dapat diamati untuk dilakukan.
Pertimbangkan kembali contoh perbankan yang digunakan sebelumnya. Dalam sistem yang menyediakan serialisasi, tetapi tidak konsistensi eksternal, meskipun pelanggan menjalankan T1, lalu T2 secara berurutan, sistem akan diizinkan untuk mengurutkannya ulang, yang dapat menyebabkan debit dikenai penalti karena dana tidak mencukupi.
Apakah Spanner memberikan konsistensi yang kuat?
Ya. Faktanya, Spanner menyediakan konsistensi eksternal, yang merupakan properti yang lebih kuat daripada konsistensi kuat. Mode default untuk operasi baca di Spanner adalah "kuat", yang menjamin bahwa operasi tersebut mengamati efek dari semua transaksi yang dilakukan sebelum operasi dimulai, terlepas dari replika mana yang menerima operasi baca.
Apa perbedaan antara konsistensi kuat dan konsistensi eksternal?
Protokol replikasi menunjukkan "konsistensi kuat" jika objek yang direplikasi dapat dilinearisasi. Seperti linearitas, "konsistensi kuat" lebih lemah daripada "konsistensi eksternal", karena tidak menjelaskan apa pun tentang perilaku transaksi.
Apakah Spanner memberikan konsistensi pada akhirnya (atau lambat)?
Spanner menyediakan konsistensi eksternal, yang merupakan properti yang jauh lebih kuat daripada konsistensi tertunda. Konsistensi pada akhirnya menukar jaminan yang lebih lemah dengan performa yang lebih tinggi. Konsistensi pada akhirnya bermasalah karena berarti pembaca dapat mengamati database dalam status yang tidak pernah benar-benar ada (misalnya, pembaca dapat mengamati status saat Transaksi B di-commit, tetapi Transaksi A tidak, meskipun A terjadi sebelum B). Spanner menyediakan pembacaan yang sudah tidak berlaku, yang menawarkan manfaat performa yang serupa dengan konsistensi tertunda, tetapi dengan jaminan konsistensi yang jauh lebih kuat. Pembacaan yang sudah tidak berlaku menampilkan data dari stempel waktu "lama", yang tidak dapat memblokir operasi tulis karena versi data sebelumnya tidak dapat diubah.