TrueTime adalah jam terdistribusi yang sangat tersedia yang 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 daripada stempel waktu T' jika T' selesai dihasilkan sebelum T mulai dibuat. Jaminan ini berlaku di semua server dan semua stempel waktu.
Fitur TrueTime digunakan oleh Spanner untuk menetapkan stempel waktu pada transaksi. Secara khusus, setiap transaksi diberi stempel waktu yang mencerminkan instan saat Spanner menganggap transaksi tersebut telah terjadi. Karena Spanner menggunakan kontrol konkurensi multi-versi, jaminan pengurutan pada stempel waktu memungkinkan klien Spanner melakukan pembacaan yang konsisten di seluruh database (bahkan di beberapa region Cloud) tanpa memblokir penulisan.
Konsistensi eksternal
Spanner memberi klien jaminan kontrol konkurensi paling ketat untuk transaksi, yang disebut konsistensi eksternal2. Dengan konsistensi eksternal, sistem berperilaku seolah-olah semua transaksi dijalankan secara berurutan, meskipun Spanner sebenarnya menjalankannya di beberapa server (dan mungkin di beberapa pusat data) untuk mendapatkan performa dan ketersediaan yang lebih tinggi. Selain itu, jika satu transaksi selesai sebelum transaksi lain mulai di-commit, sistem menjamin bahwa klien tidak akan pernah dapat melihat status yang menyertakan efek dari transaksi kedua, tetapi bukan yang pertama. Secara intuitif, Spanner secara semantik tidak dapat dibedakan dengan database satu mesin. Meskipun memberikan jaminan yang kuat, Spanner memungkinkan aplikasi mencapai performa yang sebanding dengan database yang memberikan jaminan yang lebih lemah (sebagai imbalan atas performa yang lebih tinggi). Misalnya, seperti database yang mendukung isolasi snapshot, Spanner memungkinkan penulisan dilanjutkan tanpa diblokir oleh transaksi hanya baca, tetapi tanpa menunjukkan anomali yang diizinkan 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 tabungannya. Selanjutnya, aplikasi Anda akan memulai alur kerja yang pertama kali melakukan transaksi T1 untuk menyetorkan $200 ke rekening tabungan, lalu menerbitkan transaksi kedua T2 untuk mendebit $150 dari rekening giro. Selain itu, asumsikan bahwa pada penghujung hari, saldo negatif di satu akun tercakup secara otomatis dari akun lain, dan pelanggan akan dikenai penalti jika total saldo di semua akun mereka negatif kapan saja selama hari tersebut. Konsistensi eksternal menjamin bahwa karena T2 mulai di-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 yang akan pernah melihat status ketika T2 terjadi sebelum T1; dengan kata lain, debit tidak akan pernah dikenai penalti karena dana tidak cukup.
Database tradisional yang menggunakan penyimpanan satu versi dan penguncian dua fase yang ketat memberikan konsistensi eksternal. Sayangnya, dalam sistem seperti itu, setiap kali aplikasi Anda ingin membaca data terbaru (yang kita sebut "pembacaan kuat"), sistem 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 penulisan, Spanner dan banyak sistem database lainnya menyimpan beberapa versi data yang tidak dapat diubah (sering disebut kontrol serentak multi-versi). Operasi tulis akan membuat versi baru yang tidak dapat diubah, yang stempel waktunya adalah transaksi penulisan. "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 di-commit. Kita menyebut properti ini "stempel waktu yang tepat"; perlu diperhatikan bahwa keberadaan stempel waktu yang tepat sama dengan konsistensi eksternal.
Untuk mengetahui alasan pentingnya stempel waktu yang tepat, pertimbangkan contoh perbankan dari bagian sebelumnya. Tanpa stempel waktu yang tepat, T2 dapat ditetapkan stempel waktu yang lebih awal dari stempel waktu yang ditetapkan ke T1 (misalnya, jika sistem hipotesis menggunakan jam lokal, bukan TrueTime, dan jam server yang memproses T2 sedikit terlambat). Pembacaan snapshot kemudian dapat mencerminkan debit dari T2, tetapi tidak dengan setoran T1, meskipun pelanggan melihat setoran tersebut selesai sebelum memulai debit.
Mencapai stempel waktu yang tepat itu 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, di mana server di seluruh dunia perlu menetapkan stempel waktu, jauh lebih sulit untuk dilakukan secara efisien.
Spanner bergantung pada TrueTime untuk menghasilkan stempel waktu yang meningkat secara monoton. Spanner menggunakan stempel waktu ini dalam dua cara. Pertama, fitur ini menggunakannya sebagai stempel waktu yang tepat untuk transaksi tulis tanpa memerlukan komunikasi global. Kedua, layanan ini menggunakannya sebagai stempel waktu untuk pembacaan yang kuat, yang memungkinkan pembacaan yang kuat untuk dieksekusi dalam satu putaran komunikasi, bahkan pembacaan kuat yang mencakup beberapa server.
FAQ
Jaminan konsistensi apa yang diberikan Spanner?
Spanner memberikan konsistensi eksternal, yang merupakan properti konsistensi ketat 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 yang menjalankan transaksi secara serial, dan lebih jauh lagi, bahwa urutan serial konsisten dengan urutan transaksi yang dapat diamati untuk dilakukan. Karena stempel waktu yang dihasilkan untuk transaksi sesuai dengan urutan serial, jika ada klien yang melihat transaksi T2 mulai di-commit setelah transaksi lain T1 selesai, sistem akan menetapkan stempel waktu ke T2 yang lebih tinggi daripada stempel waktu T1.
Apakah Spanner menyediakan linearisasi?
Ya. Faktanya, Spanner memberikan konsistensi eksternal, yang merupakan properti yang lebih kuat daripada linearizability, karena linearizability tidak menjelaskan apa pun tentang perilaku transaksi. Linearizabilitas 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 menyintesis transaksi secara dinamis yang berisi beberapa operasi baca dan tulis pada objek arbitrer. Linearizabilitas dapat dilihat sebagai kasus khusus konsistensi eksternal, di mana transaksi hanya dapat berisi satu operasi baca atau tulis pada satu objek.
Apakah Spanner menyediakan serialisabilitas?
Ya. Faktanya, Spanner memberikan konsistensi eksternal, yang merupakan properti yang lebih ketat daripada kemampuan serialis. Sistem pemrosesan transaksi dapat diserialisasi jika menjalankan transaksi dengan cara yang tidak dapat dibedakan dari sistem yang menjalankan transaksi secara berurutan. Spanner juga menjamin bahwa urutan serial konsisten dengan urutan transaksi yang dapat diobservasi untuk di-commit.
Pertimbangkan lagi contoh perbankan yang digunakan sebelumnya. Dalam sistem yang memberikan serialisabilitas, tetapi bukan konsistensi eksternal, meskipun pelanggan mengeksekusi T1 lalu T2 secara berurutan, sistem akan diizinkan untuk mengubah urutannya, yang dapat menyebabkan debit akan dikenai penalti karena dana yang tidak memadai.
Apakah Spanner memberikan konsistensi yang kuat?
Ya. Faktanya, Spanner memberikan konsistensi eksternal, yang merupakan properti yang lebih kuat daripada konsistensi yang kuat. Mode default untuk pembacaan di Spanner adalah "kuat", yang menjamin bahwa pembacaan tersebut mengamati efek dari semua transaksi yang dilakukan sebelum operasi dimulai, terlepas dari replika yang menerima pembacaan.
Apa perbedaan antara konsistensi kuat dan konsistensi eksternal?
Protokol replikasi menunjukkan "konsistensi yang kuat" jika objek yang direplikasi dapat di linear. Seperti halnya linearisasi, "konsistensi kuat" lebih lemah daripada "konsistensi eksternal", karena tidak menjelaskan apa pun tentang perilaku transaksi.
Apakah Spanner memberikan konsistensi tertunda (atau lambat)?
Spanner memberikan konsistensi eksternal, yang merupakan properti yang jauh lebih kuat daripada konsistensi tertunda. Konsistensi tertunda mengorbankan jaminan yang lebih lemah untuk performa yang lebih tinggi. Konsistensi tertunda menimbulkan masalah karena pembaca dapat mengamati database dalam status tidak pernah benar-benar berada dalam database (misalnya, bacaan dapat mengamati status tempat Transaksi B di-commit, tetapi Transaksi A tidak terjadi, meskipun A terjadi sebelum B). Spanner memberikan pembacaan yang sudah tidak berlaku, yang menawarkan manfaat performa yang serupa dengan konsistensi tertunda, tetapi dengan jaminan konsistensi yang jauh lebih kuat. Operasi baca yang sudah tidak berlaku menampilkan data dari stempel waktu "lama", yang tidak dapat memblokir penulisan karena versi data sebelumnya tidak dapat diubah.