- Dalam pengujian, Datomic Pro 1.0.7075 tampak memiliki keamanan antartansaksi yang lebih kuat daripada klaim dalam dokumentasinya, tetapi semantik internal transaksi sangat berbeda dari model eksekusi serial yang umum
- Semua histori pengujian tampak Serializable, dan satu sesi peer mendekati Strong Session Serializable, sementara penulisan dan pembacaan
d/sync mendekati Strong Serializable
- add, retract, dan transaction function Datomic tidak dieksekusi secara akumulatif berurutan di dalam transaksi; setiap fungsi beroperasi dengan hanya melihat status DB pada saat awal
- Jika transaction function yang secara independen aman, seperti
approve dan deny, digabungkan dalam transaksi yang sama, hasil komposisinya dapat menimbulkan pelanggaran invariant
- Saat memasukkan beberapa transaction function ke dalam satu transaksi, periksa hubungan read set dan write set, serta gunakan constraint eksplisit seperti entity predicate, attribute predicate, dan entity spec secara bersamaan
Model dan Arsitektur Datomic Pro
- Datomic adalah database OLTP Entity-Attribute-Value yang memodelkan konsep waktu secara eksplisit
- Status DB pada titik waktu tertentu direpresentasikan sebagai kumpulan datom berbentuk
[entity, attribute, value]
- Setiap datom juga menyimpan transaksi mana yang menambahkan atau menariknya kembali
- Seluruh datom berbentuk 5-tuple
[entity, attribute, value, transaction, asserted-or-retracted?]
- Karena Datomic adalah temporal database, pengguna dapat meminta snapshot bukan hanya untuk saat ini, tetapi juga berdasarkan waktu logis atau waktu wall-clock di masa lalu
- Dengan tampilan histori penuh, pengguna juga dapat mengueri apakah suatu fakta tertentu pernah ada di masa lalu
- Untuk metode kueri, Datomic menyediakan API bergaya Datalog, API traversal graf, dan tipe
Entity bergaya ODM
- Datomic Pro adalah versi yang dapat dioperasikan sendiri oleh pengguna, sedangkan Datomic Cloud berjalan di AWS dan arsitekturnya sebagian berbeda
- Datomic Pro memiliki struktur yang terdiri dari beberapa komponen yang bekerja sama
- Transactor bertanggung jawab menjalankan transaksi tulis, memelihara indeks, dan mencatat ke storage
- Peer adalah klien tebal yang menyertakan library JVM; ia mengirimkan transaksi, menjalankan kueri baca ke target storage, dan melakukan caching
- Untuk aplikasi dalam bahasa lain, Datomic juga menyediakan thin client dan model client-server berbasis peer server
- Secara internal, Datomic melakukan append setiap transaksi ke log berdasarkan urutan waktu, dan memelihara 4 indeks yang diurutkan menurut kombinasi entity, attribute, value, dan time
- Log dan indeks disimpan sebagai tree yang persisten dan immutable di storage seperti Cassandra atau DynamoDB
- Karena node tree bersifat immutable, backing storage cukup menjamin eventual consistency saja
- Saat commit, transactor menyimpan node tree immutable baru lalu memajukan root pointer dengan compare-and-set(CaS); CaS ini memerlukan Sequential consistency
- Sequential CaS menjamin urutan global transaksi, tetapi mengikat throughput tulis pada kecepatan satu transactor
- Datomic biasanya hanya memiliki satu active transactor pada satu waktu, dan men-deploy beberapa transactor untuk toleransi kegagalan
- Peer terhubung langsung ke storage dan transactor, serta masing-masing mempertahankan salinan root pointer yang meningkat secara monoton
- Karena pembacaan dapat meng-cache node tree immutable, menambah jumlah peer memungkinkan penskalaan baca yang hampir linear
Model Transaksi Datomic
- Datomic tidak menyediakan interactive transaction seperti database OLTP pada umumnya
- Modelnya bukan memulai transaksi, menerima hasil operasi, mengirimkan operasi berikutnya, lalu commit di akhir
- Ada transaction function yang mirip stored procedure, tetapi tidak dapat mengembalikan nilai arbitrer kepada pemanggil
- Jalur baca dan tulis dipisahkan secara ketat
db mengembalikan status DB terbaru yang diketahui peer
d/sync melakukan sinkronisasi dengan transactor untuk mendapatkan status terbaru menurut semua peer atau status setelah waktu tertentu
d/as-of mendapatkan status DB pada titik waktu di masa lalu
- Karena status DB bersifat immutable, beberapa kueri terhadap status yang sama dijalankan pada waktu logis yang persis sama
- Transaksi tulis direpresentasikan sebagai operation berbentuk ordered list
- Contohnya mencakup
:db/add, :db/retract, db/cas, dan pemanggilan transaction function buatan pengguna
- Transaction function menerima status DB pada saat transaksi dimulai beserta argumen, lalu mengembalikan kumpulan operation baru
- Pemanggilan fungsi diperluas secara rekursif hingga hanya menyisakan assertion dan retraction
- Transaction function dapat melakukan pembacaan di dalamnya untuk menentukan penulisan bersyarat, tetapi tidak mengembalikan hasil baca atau informasi arbitrer secara langsung kepada pemanggil
transact
transact mengembalikan status DB tepat sebelum transaksi, status DB hasil transaksi, dan kumpulan datom yang telah diperluas
- Pemanggil dapat menggunakan pre-state dan post-state untuk menentukan apakah penulisan bersyarat terjadi
- Datomic adalah model yang dirancang untuk memecahkan masalah dengan berpusat pada snapshot DB yang murah dan mudah diteruskan
- Nubank adalah perusahaan pengembang Datomic saat ini; perusahaan ini menyediakan layanan finansial kepada sekitar 94 juta pengguna dan memproses rata-rata 2,3 miliar transaksi pengguna per hari
- Hampir semua produk Nubank menggunakan Datomic sebagai system of record
Klaim konsistensi dan desain pengujian
- Dokumentasi Datomic mengklaim transaksi ACID, dengan transaksi dicatat ke storage sebagai satu atomic write, dan setiap peer mengamati semua transaksi yang telah selesai hingga titik waktu tertentu dalam urutan total
- Sebelum acknowledgement ke klien, transaksi di-flush ke durable storage
- Dokumentasi pada saat analisis dimulai pada awal Januari 2024 secara informal mengklaim bahwa transaksi tulis bersifat Serializable
- Dokumentasi juga menyebut Datomic sebagai sistem “single-writer”, tetapi Jepsen menilai penjelasan ini tidak akurat karena dua alasan
- Untuk toleransi kegagalan, beberapa transactor dapat dijalankan, dan karena pendeteksi kegagalan tidak bisa sempurna, bisa muncul jendela waktu ketika beberapa transactor menganggap dirinya aktif secara bersamaan
- Bahkan jika hanya ada satu transactor, keterlambatan jaringan dapat membuat pesan storage terselang-seling dengan pesan transactor lain
- Keamanan Datomic dinilai berasal bukan dari logika “single-writer”, melainkan dari Sequential consistency pada operasi CaS di storage
- Meski ada beberapa transactor konkuren, CaS harus menyediakan keamanan
- Pengujian menggunakan Datomic test suite yang ditulis dengan Jepsen testing library
- Datomic Pro 1.0.7075 dipasang pada klaster node Debian Bookworm
- Storage menggunakan table AWS DynamoDB
- Dua node menjalankan transactor, dan node lainnya menjalankan peer
- Peer adalah program Clojure kecil yang menggunakan Datomic peer library, dan mengekspos HTTP API untuk operasi pengujian
- Pengujian menjalankan baik mode yang memungkinkan stale read dengan
d/db maupun mode yang menjamin kemutakhiran dengan d/sync
- Fault injection diterapkan pada transactor maupun peer
- Menyuntikkan process pause, crash, dan clock error
- Membuat partisi jaringan antara transactor dan peer, serta antara node dan storage
- Juga meminta Datomic garbage collection
- Transactor berhenti sendiri jika tidak dapat mempertahankan koneksi yang stabil dengan storage
- Pada node di luar AWS, penggunaan timeout default 5 detik membuatnya berhenti setiap beberapa menit bahkan karena fluktuasi jaringan normal
- Di lingkungan pengujian EC2 pun, pada timeout 1 detik transactor berhenti setiap 10–20 menit
- Datomic merekomendasikan operator me-restart transactor dengan supervisor daemon, dan pengujian menggunakan systemd service dengan pengaturan
Restart=on-failure
Empat workload
-
List Append
- Workload List Append digunakan bersama Elle transaction checker
- Secara logis menangani daftar-daftar elemen integer, dengan setiap daftar diidentifikasi oleh primary key integer
- Klien menjalankan transaksi acak yang terdiri dari pembacaan daftar atau append elemen unik
- Elle memeriksa aborted read, intermediate read, pelanggaran internal consistency, dan ketidaksesuaian urutan elemen, lalu mencari cycle pada dependency graph untuk menentukan pelanggaran model konsistensi
- Di Datomic, daftar dienkode sebagai satu entity dengan dua atribut
append/key berperan sebagai primary key
append/elements adalah atribut multi-nilai yang menyimpan elemen integer daftar
- Karena atribut multi-nilai adalah set tanpa urutan, Jepsen mengurutkan elemen berdasarkan transaction timestamp tiap datom agar Elle memperoleh urutan yang dibutuhkan
- Batasan bahwa tidak ada mixed read-write transaction diakali dengan transaction function dan perhitungan pre-state
- Penulisan dilakukan dengan transaction function
- Dengan pre-state yang dikembalikan oleh
transact, dihitung apa yang kira-kira dilihat oleh pembacaan di dalam transaksi
- Fungsi yang sama dijalankan dua kali: sekali di
transact, dan sekali di peer untuk melengkapi pembacaan berbasis pre-state
-
List Append with CaS
- Workload List Append with CaS menggunakan pola
db/cas
- Pengguna dapat membaca keadaan saat ini dengan
d/db, lalu misalnya mengirim [:db/cas 123 :counter/value 4 5] yang mengubah nilai menjadi 5 hanya ketika nilainya 4
- Jika
db/cas digunakan untuk semua penulisan, ad hoc Snapshot Isolation dapat dibangun di atas logical “user transaction”
- Workload ini menyimpan daftar bukan sebagai multi-nilai, melainkan sebagai single-valued comma-separated string
- Pada awal transaksi, sistem membaca; kemudian menerapkan pembacaan dan penulisan secara lokal; lalu menyusun transaksi CaS yang menjamin nilai tidak berubah sejak dibaca
-
Internal
- Workload Internal mengukur konsistensi internal transaksi secara langsung
- Kasus meng-assert 1 lalu meng-assert 2 pada entity attribute yang sama
- Kasus meng-assert dan me-retract fact dalam transaksi yang sama
- Kasus meng-assert nilai lalu mencoba mengubahnya dengan CaS
- Kasus melakukan beberapa CaS seperti 1→2 dan 2→3
- Kasus membuat entity lalu memodifikasinya dengan lookup ref
- Termasuk kasus mencoba melakukan increment nilai dua kali dengan transaction function
-
Grant
- Workload Grant memeriksa apakah transaction function mempertahankan invariant fungsi
- Grant dienkode sebagai satu entity dengan tiga atribut:
created-at, approved-at, dan denied-at
- Grant tidak boleh berada dalam status approved dan denied secara bersamaan
- Fungsi
approve dan deny terlebih dahulu memeriksa apakah grant sudah approved atau denied, lalu melakukan abort jika perlu
- Pengujian memeriksa apakah grant menjadi approved dan denied secara bersamaan pada berbagai kombinasi transaction boundary
Hasil pengujian: keamanan antatransaksi tampak kuat
- Jepsen tidak menemukan perilaku yang bertentangan dengan klaim keamanan inti Datomic
- Transaksi tampak diterapkan seolah-olah dalam total order
- Urutan tersebut konsisten dengan local operation order pada setiap peer
- Histori yang dibatasi hanya pada transaksi tulis, serta histori yang menggunakan
(d/sync conn) pada pembacaan, konsisten dengan real-time order
- Jepsen menilai ini tampak sebagai Strict Serializable
- Jika session diikat ke satu peer dan ditafsirkan demikian, Datomic tampak menjamin Strong Session Serializability
- Histori transaksi tidak dapat dibedakan dari histori yang dijalankan dalam suatu total order
- Order tersebut konsisten dengan urutan yang diamati pada tiap peer
d/db mengembalikan salinan DB yang diperbarui secara asinkron, sehingga stale read mungkin terjadi
- Dokumentasi Datomic juga menyatakan bahwa peer read bisa saja tidak mengamati sebagian transaksi yang baru di-commit
d/sync mencegah stale read dengan melakukan sinkronisasi dengan transactor
- Verifikasi eksperimental masih memiliki keterbatasan
- Keberadaan bug dapat dibuktikan, tetapi ketiadaannya tidak dapat dibuktikan
- Correctness error pada sistem storage yang menjadi dependensi Datomic dapat menyebabkan pelanggaran jaminan Datomic
- Datomic di atas DynamoDB hanya seaman compare-and-set operation milik DynamoDB
Semantik internal transaksi: konkurensi, bukan urutan
- Sebagian besar basis data dan formalisasi utama isolasi transaksi menyediakan semantik eksekusi serial di dalam transaksi
- Jika
set x = 1; read x;, read biasanya melihat 1
- Formalisasi oleh Adya, Cerone·Bernardi·Gotsman, Crooks·Alvisi·Pu·Clement, dan lainnya secara eksplisit menyatakan urutan operasi di dalam transaksi serta sifat bahwa “write sebelumnya diamati oleh read berikutnya”
- Transaction request Datomic berupa ordered list, tetapi eksekusinya tidak mempertahankan urutan tersebut
- add, retract, dan transaction function berperilaku seolah-olah dijalankan secara bersamaan
- transaction function selalu mengamati keadaan DB pada saat awal transaksi
- Tidak melihat efek dari assertion, retraction, atau transaction function sebelumnya
- Jika CaS yang sama dimasukkan dua kali pada entity yang nilai saat ini
0, di Datomic keduanya melihat keadaan awal 0 dan berhasil
[[:db/cas 123 :internal/value 0 1]
[:db/cas 123 :internal/value 0 1]]
- Dalam model serial, CaS pertama seharusnya mengubah nilai menjadi
1 dan CaS kedua seharusnya gagal
- Di Datomic, kedua CaS membuat assertion duplikat dan nilai akhirnya menjadi
1
- Dua kali increment transaction function juga menghasilkan hasil yang berbeda dari model serial
[['internal/increment "x"]
['internal/increment "x"]]
- Jika nilai awal
0, hasil model serial adalah 2
- Di Datomic, kedua fungsi sama-sama melihat keadaan awal
0 dan nilai akhirnya menjadi 1
- transaction function juga tidak melihat assertion sebelumnya
[[:db/add id-of-x :internal/value 1]
['internal/increment "x"]]
- Di Datomic, nilai akhirnya menjadi
1, bukan 2
- lookup ref juga menggunakan keadaan DB pada saat awal transaksi
- Setelah menambahkan entity dalam transaksi yang sama, entity tersebut tidak dapat dirujuk dengan lookup ref
- Dalam kasus ini transaksi di-abort dengan kesalahan
Unable to resolve entity
Deteksi konflik dan pseudo write skew
- Jika Datomic meng-assert nilai yang berbeda pada atribut single cardinality dalam transaksi yang sama, transaksi di-abort dengan
:db.error/datoms-conflict
- Untuk nilai awal
0, jika nilai 2 di-assert dan pada saat yang sama increment function membuat assertion nilai 1, maka terjadi konflik
- Deteksi konflik ini kemungkinan mencegah banyak hasil mengejutkan yang muncul dari komposisi transaction function yang keliru
- Jika write set berupa pasangan
[entity, attribute] yang berbeda, sulit menjaga invariant hanya dengan deteksi konflik
- Workload grant menunjukkan situasi ini
approve dan deny masing-masing memeriksa apakah grant belum approved maupun denied, lalu menambahkan atribut yang berbeda
- Jika
approve dan deny dipanggil dalam transaksi yang berbeda, transaksi Serializable Datomic menjamin invariant
- Namun jika keduanya dipanggil bersama dalam transaksi yang sama, keduanya melihat keadaan awal dan berhasil
[['grant/approve id]
['grant/deny id]]
- Akibatnya, grant memiliki
approved-at dan denied-at sekaligus
- Invariant bahwa “grant tidak boleh menjadi approved dan denied secara bersamaan” dilanggar
- In-transaction conflict checker Datomic tidak mencegah ini karena kedua fungsi membuat assertion pada atribut yang berbeda
- Fenomena ini mirip dengan Write Skew dari Berenson dkk.
- Karena kedua fungsi tidak dapat melihat efek satu sama lain, muncul read-write anti-dependency cycle
- Jika transaction function dipandang seperti transaksi, ini mirip dengan anomali G2-item yang dilarang oleh Repeatable Read dan Serializability
- Datomic dan Nubank memandang perilaku ini bukan sebagai bug, melainkan sebagai perilaku yang diharapkan dari Datomic
- Nubank berencana mempertahankan concurrent intra-transaction semantics Datomic
Memperkuat invariant dengan entity predicate
- Datomic menyediakan mekanisme constraint seperti tipe, uniqueness, attribute predicate tertentu, dan entity predicate
- entity predicate menerima candidate DB state setelah semua efek transaksi diterapkan serta entity ID, lalu mengembalikan
true atau false untuk menentukan apakah commit diizinkan
- Namanya entity predicate, tetapi karena dapat mengakses seluruh keadaan DB, ia juga dapat mengekspresikan constraint global yang melampaui entity tertentu
- Dalam contoh grant, predicate
valid-grant? dapat dibuat agar approved-at dan denied-at tidak ada secara bersamaan
(defn valid-grant?
[db eid]
(let [{:grant/keys [approved-at denied-at]}
(d/pull db '[:grant/approved-at
:grant/denied-at]
eid)]
(not (and approved-at denied-at))))
- Pada schema, entity spec ditambahkan untuk merujuk predicate ini
- entity predicate yang terhubung dengan entity spec tidak diterapkan otomatis pada semua transaksi
- Datomic menganggap apakah entity spec diterapkan sebagai domain decision, dan berpandangan bahwa setiap transaksi harus memintanya secara eksplisit
- Fungsi
approve dan deny dapat meminta penerapan entity spec dengan virtual datom :db/ensure setelah menambahkan atribut
(defn approve
[db id]
[[:db/add id :grant/approved-at (Date.)]
[:db/add id :db/ensure :grant/valid?]])
- Dengan menggunakan entity spec ini, ketika mencoba approve dan deny bersama dalam transaksi yang sama, terjadi kesalahan entity predicate dan invariant tetap terjaga
- Kesalahan tersebut mencakup
:db.error/entity-pred, :db.error/pred-return false
Perubahan Dokumentasi dan Rekomendasi untuk Pengguna
- Datomic merevisi dokumentasinya secara signifikan setelah berkolaborasi dengan Jepsen
- transaction safety documentation mencerminkan jaminan keamanan yang lebih kuat yang dianggap benar-benar disediakan oleh Datomic
- Menyatakan Serializability global, monotonicity per peer, serta Strict Serializability untuk pembacaan yang menggunakan penulisan atau
sync
- Argumen “single-writer” dihapus dari dokumentasi keamanan
- Dokumen transaction syntax and semantics membahas secara menyeluruh struktur transaction request, aturan ekspansi map form dan transaction function, serta proses penerapan transaction
- Dokumen transaction functions juga direvisi
- Menjelaskan berbagai mekanisme yang menjamin consistency, pembuatan dan pemanggilan function, serta perilaku function bawaan
- Ungkapan bahwa transaction function dapat “atomically analyze and transform database values” atau menjamin “atomic read-modify-write processing” dihapus
- Datomic bermaksud ke depannya menyebut struktur data yang diberikan ke
d/transact sebagai transaction request, bukan “transaction”
- Elemennya akan disebut “data”, bukan “statements” atau “operations”
[:db/add ...] dan [:db/retract ...] masing-masing adalah assertion request dan retraction request
- Ini membantu membedakan datom assertion yang sebenarnya dari assertion request yang belum lengkap di dalam transaction request
- Hal-hal yang perlu diperhatikan pengguna sudah jelas
- Serializability antar-transaction di Datomic dapat dipercaya
- Concurrent execution semantics di dalam transaction adalah pilihan yang tidak umum, sehingga perlu berhati-hati saat memanggil beberapa transaction function dalam transaction yang sama
- Terutama waspadai kasus ketika read set saling tumpang tindih dan write set terpisah
- Beberapa increment dapat diam-diam collapse menjadi satu update
- Attribute predicate dan entity spec dapat digunakan, tetapi entity spec harus diminta secara eksplisit pada semua transaction yang membutuhkannya
- Dari sisi operasional, restart transactor dan fluktuasi jaringan juga perlu diperhitungkan
- Datomic transactor akan berhenti sendiri jika tidak dapat berkomunikasi dengan storage selama beberapa menit
- Jepsen merekomendasikan penambahan retry loop pada transactor agar lebih tahan terhadap fluktuasi jaringan
Batasan dan Pertanyaan Riset Mendatang
- Dalam pengujian ini masih ada item yang berada di luar cakupan evaluasi
- Excision dan historical query tidak dievaluasi
- Datomic client library juga tidak diselidiki, tetapi Jepsen menilai perilakunya kemungkinan mirip dengan peer yang digunakan untuk pengujian
- Storage engine yang digunakan hanya DynamoDB
- Datomic Cloud juga tidak dievaluasi, dan Datomic Cloud menggunakan arsitektur yang sedikit berbeda
- Jepsen menyatakan bahwa mereka hampir tidak mengetahui sistem atau formalisasi yang menyediakan Serializability antar-transaction sekaligus concurrent semantics di dalam transaction
- Model Datomic memunculkan sejumlah pertanyaan riset
- Apakah Datomic transaction dapat dipandang sebagai dual dari transaction tradisional atau sebagai model “co-transaction”
- Apakah kelebihan dan kekurangan model seperti ini dapat dimitigasi melalui static analysis, runtime check, atau API extension
- Seberapa besar kemungkinan pengguna nyata menulis transaction yang melanggar invariant
- Sebagai pembanding, disebutkan proyek riset temporal Datalog Alvaro’s Dedalus dan Fauna
- Dedalus, seperti Datomic, juga memiliki transaction yang terjadi “all at once”
- Fauna adalah temporal database yang juga mendukung Strong Serializability, dan berbeda dari Datomic, tampaknya menyediakan serial execution dan incremental side effect di dalam transaction
- Kemiripan antara end-of-transaction conflict checker Datomic dan aturan first-committer-wins pada Snapshot Isolation juga tetap menjadi peluang riset
- Bagian mana dari literatur Snapshot Isolation yang dapat diterapkan ke Datomic
- Bagaimana cycle di dalam Datomic transaction direpresentasikan sebagai anti-dependency edge
- Masih ada pertanyaan apakah fenomena seperti lost update, Fractured Read, read-only transaction anomaly, dan Long Fork memiliki analogue dalam semantik internal
- Keterkaitan dengan CALM theorem juga dapat ditelaah lebih lanjut
- Apakah transaction function yang secara logis monotonic dapat digabungkan dengan aman di dalam Datomic transaction yang sama
- Dapat diteliti apakah program Datalog tanpa negation juga aman dalam model eksekusi ini
1 komentar
Komentar Hacker News
Saya menyaksikan pekerjaan ini berlangsung dari dekat, dan proses diskusinya benar-benar menarik untuk diikuti
Fakta bahwa Jepsen tidak menemukan bug fatal juga mengejutkan, dan sekadar memperjelas dokumentasi serta perilaku khusus yang memang disengaja sudah menjadi hasil yang sangat berguna
Mengingat kami menjalankan bank di atas Datomic, ini jelas layak sebagai latihan untuk membangun kepercayaan
Tulisannya benar-benar bagus, dan setiap kali merasa diri cukup pintar, membaca analisis Jepsen adalah cara yang baik untuk kembali rendah hati
Ini pertama kalinya saya membaca laporan Jepsen secara mendalam, dan saya menyukai bagian yang menjelaskan dengan jelas cara kerja internal transaksi Datomic
Saya juga menyadari betapa saya belum memahami perbedaan antara transaksi Datomic dan transaksi database SQL
Yang terutama menarik perhatian saya adalah paragraf: “Datomic dulu menyebut struktur data yang diteruskan ke
d/transactsebagai ‘transaction’, dan elemen-elemennya sebagai ‘statements’ atau ‘operations’. Ke depannya, struktur ini akan disebut ‘transaction request’, dan elemen-elemennya ‘data’”Saya penasaran apa artinya ini bagi d/transact-async di namespace
datomic.apidan fungsi-fungsi terkaitSaya sudah hampir setahun tidak memakai Datomic, dan tampaknya banyak hal telah berubah
Semua fungsi di
datomic.apitetap seperti semulaIni laporan yang sangat bagus dan terperinci tentang database yang benar-benar bagus
Sangat menyenangkan juga melihat dokumentasinya diperjelas dan diperbarui
Selain itu, saya sungguh berharap Apple mau membiayai analisis Jepsen untuk FoundationDB
Saya tahu Aphyr mengatakan “pengujian mereka mungkin lebih baik”, tetapi jika Jepsen benar-benar tidak menemukan masalah di FoundationDB, itu akan menjadi bukti kuat lain bahwa FoundationDB adalah database yang hebat
Saya bukan orang yang sangat paham bidang ini, tetapi setiap kali melihat ucapan seperti “semoga $foo mau membiayainya”, telinga saya langsung tertarik
Modal berlimpah, tetapi menunggu Apple melakukan sesuatu, menurut pengalaman saya, bisa memakan waktu lama
Jepsen menemukan situasi yang jelas yang berujung pada pelanggaran invariant, dan yang menarik, respons dari pihak Datomic tampaknya hanya berupa klarifikasi dokumentasi
Jadi apakah itu berarti tim Datomic menerima bahwa pelanggaran seperti ini terjadi, tetapi tidak menganggapnya masalah?
Tulisan itu mengatakan, “Dari sudut pandang Datomic, pelanggaran invariant pada beban kerja grant adalah kesalahan pengguna. Fungsi transaksi tidak dijalankan secara atomik dalam urutan. Jika operasi lain di dalam transaksi dapat membatalkan prasyaratnya, tidak aman memeriksa prasyarat di fungsi transaksi”
Untuk melihat apa artinya dari sudut pandang pengguna, kita bisa membayangkan pseudo-data transaksi seperti berikut
[ [Stu favorite-number 41] ;; maybe more stuff [Stu favorite-number 42] ]Jika dibaca secara operasional, di awal transaksi tampak seolah saya menyukai 41, lalu kemudian menjadi menyukai 42
Setelah transaksi selesai, pengamat akan berharap melihat bahwa saya hanya menyukai 42, dan harus memikirkan dalam kondisi apa 41 bisa terlihat
Penafsiran operasional atas semantik internal transaksi seperti ini umum di banyak basis data, tetapi mengasumsikan ada beberapa titik waktu di dalam transaksi
Di Datomic, titik waktu semacam itu tidak ada dan memang tidak diinginkan, dan saya lebih suka tidak perlu mengkhawatirkan apa yang terjadi “di tengah transaksi”
Di Datomic, semua fakta dalam sebuah transaksi terjadi pada titik waktu yang sama, jadi transaksi ini mengatakan bahwa saya mulai menyukai dua angka itu secara bersamaan
Jika transaksi Datomic keliru dibaca sebagai gabungan beberapa operasi, tentu saja berbagai macam “anomali invariant” bisa ditemukan
Sebaliknya, jika model Datomic keliru ditempelkan pada transaksi SQL, “anomali invariant” juga bisa ditemukan
Karena ada kemungkinan salah paham seperti ini, dokumentasi yang baik memang diperlukan, dan bersama Jepsen kami memperbaiki dokumentasi [1], merapikan ungkapan yang kurang hati-hati, dan berupaya mengurangi salah paham
Kami juga menambahkan catatan teknis yang secara langsung membahas salah paham khusus ini [2]
[1] https://docs.datomic.com/transactions/transactions.html#tran...
[2] https://docs.datomic.com/tech-notes/comparison-with-updating...
Apakah ini benar-benar penting bergantung pada apakah pengguna menulis fungsi transaksi untuk mempertahankan invariant tertentu, dan fungsi itu hanya menjaga invariant jika dijalankan secara berurutan, bukan secara simultan
Posisi Datomic, atau setidaknya akan bagus jika pihak Datomic ikut menjelaskan, adalah bahwa pengguna tidak terlalu sering menulis fungsi transaksi seperti itu
Posisi ini bisa dipertahankan. Sebab dokumentasi memang menyatakan bahwa fungsi transaksi tidak saling mengamati, melainkan mengamati keadaan awal transaksi
Di sisi lain, dokumentasi juga memiliki ungkapan yang mengisyaratkan bahwa fungsi transaksi bisa dipakai untuk mempertahankan invariant: “[txn fns] can atomically analyze and transform database values. You can use them to ensure atomic read-modify-update processing, and integrity constraints...”
Karena ungkapan ini, serta fakta bahwa hampir semua basis data serializable lain memakai semantik berurutan di dalam transaksi, laporan tersebut memberi banyak ruang untuk isu ini
Ini pertanyaan yang kompleks dan tidak ada jawaban yang jelas; saya ingin mendengar bagaimana komunitas basis data umum, dan khususnya pengguna Datomic, menerima semantik ini
Jika disebut “situasi yang berujung pada pelanggaran invariant”, itu terdengar seperti bug Datomic, tetapi bukan itu masalahnya
Kita perlu memahami cara Datomic memproses transaksi dan menulis kode yang sesuai dengannya
Saya tidak terkait dengan Nubank, tetapi selama memakai Datomic sebagai basis data serbaguna, saya belum pernah mengalami situasi di mana hal ini menjadi masalah
Sebagai tambahan bagi yang belum tahu, nama Jepsen adalah permainan kata dari Carly Rae Jepsen, penyanyi “call me maybe”
Menurut saya itu nama yang sempurna untuk proyek riset sistem terdistribusi
Commit pertamanya pada 2013
https://github.com/jepsen-io/jepsen/tree/4b112e7046a20efa80a...
Lagunya keluar pada 2011; waktu benar-benar cepat berlalu
Saya belum lama memakai Datomic di produksi, tetapi karena memang sangat unik, saya bertanya-tanya apakah ada yang benar-benar mengejutkan di sini
Transaksi Datomic pada dasarnya lebih mirip batch, dan karena saya selalu menganggapnya single-threaded, wajar jika tidak banyak race condition
Secara desain, arahnya lambat dan aman
Sepertinya perlu sangat berhati-hati
Terima kasih, Kyle
Jelas bahwa dokumentasi kami tidak memadai
Bersama Rich, saya mencoba menulis dokumentasi yang lebih jelas dan menyeluruh tentang model transaksi Datomic
Semoga ini bisa mencegah salah paham umum sejak awal, dan semua masukan sangat kami terima
https://docs.datomic.com/transactions/model.html
Model data Datomic cukup intuitif jika Anda familier dengan triple store atau RDF
Namun kemiripan seperti ini jarang disebutkan dalam dokumentasi atau diskusi online
Saya penasaran apakah itu karena orang-orang tidak familier dengan konsep tersebut, atau karena asosiasi dengan semantic web dianggap sebagai distraksi, atau mungkin ada perbedaan mendasar yang saya lewatkan
Saya benar-benar menunggu analisis ini
Belakangan ini saya sedang membuat sendiri penyimpanan data mirip Datomic, jadi sepertinya akan berguna, dan sekarang sedang membacanya
Analisis MongoDB juga menarik, dan analisis lain seperti Redis, RethinkDB, dan sebagainya juga sangat layak dibaca
Semoga suatu hari ada analisis tentang rqlite/dqlite atau turso/libsql juga
Dua tahun lalu ada analisis bergaya Jepsen tentang rqlite [1]
https://www.philipotoole.com/testing-rqlite-read-consistency...
Laporan itu sendiri ada di sini: https://github.com/wildarch/jepsen.rqlite/blob/main/doc/blog...
[1] https://www.rqlite.io