Fencing Token Menghentikan Write dari Pemegang Lease yang Sudah Stale

Distributed lease dapat menentukan client yang saat ini memiliki sebuah resource, tetapi lease yang kedaluwarsa tidak langsung menghentikan pemegang sebelumnya. Sebuah process dapat pause, kehilangan akses network, atau macet cukup lama sampai lease-nya habis. Client lain kemudian memperoleh lease. Jika process lama kembali berjalan dan masih memiliki akses ke storage atau service yang dilindungi, kedua client dapat mengirim write.

Lease manager sudah memindahkan ownership, tetapi resource yang dilindungi tidak memiliki dasar untuk membedakan holder saat ini dari holder yang stale. Fencing token menutup celah tersebut dengan menyertakan nomor generation yang terurut pada setiap acquisition yang berhasil. Resource hanya menerima operasi ketika token-nya setidaknya sama baru dengan token terbesar yang pernah diterima.

client A memperoleh lease -> token 41
A pause
lease kedaluwarsa
client B memperoleh lease -> token 42
B write dengan 42         -> diterima
A kembali dan write 41    -> ditolak

Pemeriksaan yang menentukan berada pada resource penerima write, bukan hanya di dalam lease service.

Lease kedaluwarsa bukan revocation process

Lease adalah authority yang dibatasi waktu. Setelah masa berlakunya selesai, coordination service dapat memberikan authority kepada client lain. Perpindahan tersebut tidak berarti holder lama sudah berhenti mengeksekusi code.

Garbage-collection pause yang panjang, VM suspension, scheduler starvation, network partition, dan message yang tertunda dapat menciptakan actor yang stale. Actor tersebut mungkin masih menyimpan connection dan local state dari periode ketika lease-nya valid.

Pemeriksaan lokal seperti lease_expiry > now tidak cukup ketika process clock atau cached state sudah stale. Renewal sebelum setiap operasi mempersempit sebagian window, tetapi tetap tidak dapat menarik kembali request yang dikirim sebelum expiry lalu tertahan di network.

Fencing memindahkan keputusan ke komponen yang dapat menegakkan ordering pada side effect.

Token harus maju bersama ownership

Fencing token umumnya berupa integer monotonik yang diterbitkan ketika ownership lease diberikan:

acquisition 1 -> token 101
acquisition 2 -> token 102
acquisition 3 -> token 103

Token tidak perlu menyimpan waktu. Properti yang dibutuhkan adalah urutan: acquisition sukses yang lebih baru memperoleh nilai lebih besar daripada acquisition sebelumnya untuk scope resource yang sama.

Resource yang dilindungi menyimpan token terbesar yang sudah diterima, baik secara langsung maupun sebagai bagian dari version state:

if request.token < highest_token:
    reject_stale_request()
else:
    highest_token = request.token
    apply_write()

Perbandingan dan write memerlukan hubungan atomic yang sesuai dengan resource tersebut. Memeriksa token dalam satu transaction lalu menerapkan mutation kemudian tanpa jaminan ordering yang sama dapat membuka race kembali.

Resource harus ikut menegakkan fence

Menerbitkan token pada lock atau lease service saja tidak cukup. Jika downstream storage mengabaikannya, holder lama masih dapat mengubah state setelah holder baru mengambil alih.

Syarat ini menentukan tempat fencing dapat diterapkan. Database dapat menyimpan token bersama row dan menolak generation yang lebih rendah melalui conditional update. Custom service dapat menyimpan generation terbesar untuk sebuah resource dan memvalidasi setiap mutating request. Storage API tanpa conditional write, version check, atau enforcement point setara mungkin tidak dapat menerapkan fencing secara langsung.

Scope enforcement juga harus sesuai dengan scope lease. Token untuk satu shard tidak semestinya mem-fence shard lain kecuali desain memang memakai global generation.

Fencing berbeda dari random lock identifier

Random lease ID dapat membuktikan identity, tetapi tidak menunjukkan recency. Misalnya client A memiliki ID a7f2 dan client B kemudian memperoleh ID 91cd. Resource yang menerima kedua nilai tersebut tidak dapat menentukan acquisition mana yang lebih baru.

Ordered token membawa informasi itu:

41 < 42 < 43

Random ID tetap berguna untuk safe release. Client tidak semestinya menghapus lock hanya karena key masih ada; client perlu memastikan stored lock identity masih miliknya. Mekanisme itu melindungi coordination record dari cleanup milik client lama. Fencing menangani masalah berbeda: operasi stale yang mencapai protected resource.

Keduanya dapat dipakai bersama. Identity melindungi lease management, sedangkan generation ordering melindungi side effect.

Renewal biasanya mempertahankan generation

Renewal yang berhasil memperpanjang masa ownership saat ini; renewal bukan transfer ke owner baru. Mempertahankan fencing token yang sama selama renewal biasa membuat generation mewakili ownership epoch, bukan jumlah heartbeat.

Token baru diperlukan ketika ownership diberikan setelah term sebelumnya tidak lagi authoritative. Jika acquisition semantics mengizinkan owner baru, owner tersebut harus menerima generation yang berada setelah generation sebelumnya.

Karena itu, token allocator memerlukan durability dan ordering yang sesuai dengan failure model lease service. Penggunaan ulang generation lama setelah coordinator recovery dapat membuat request stale tidak dapat dibedakan dari request saat ini.

Delayed request adalah kasus utama

Fencing tetap bernilai meskipun process segera berhenti setelah kehilangan lease. Network dan queue dapat mempertahankan request lama secara independen dari process pembuatnya.

Perhatikan urutan berikut:

t0  A memegang token 7
t1  A mengirim write(7), packet tertunda
t2  lease A kedaluwarsa
t3  B memperoleh token 8
t4  B mengirim write(8), resource menerimanya
t5  write(7) yang tertunda tiba

Tanpa fencing, request dari t1 dapat menimpa state yang dihasilkan pada t4. Dengan validasi generation, arrival order tidak lagi memberi authority kepada request stale. Resource menolak token 7 setelah melihat token 8.

Ini juga membuat client-side lease check tepat sebelum request dikirim bukan pengganti yang lengkap. Request dapat menjadi stale setelah pemeriksaan tersebut.

Token tidak memberi full transaction ordering

Fencing token mengurutkan ownership epoch. Token tidak otomatis men-serialize setiap operasi di dalam satu epoch, menyediakan exactly-once delivery, atau menyelesaikan application-level conflict antara write dengan token yang sama.

Jika satu holder mengirim dua mutation concurrent dengan token 12, token itu sendiri tidak menentukan mutation mana yang harus menang. Sequence number, database transaction, compare-and-swap version, idempotency key, atau ordering khusus aplikasi mungkin tetap diperlukan.

Fencing juga tidak memperbaiki lease algorithm yang memberikan authority overlap di luar model yang dinyatakan. Fencing memberi downstream guard terhadap generation lama; coordinator tetap memerlukan aturan yang koheren untuk menerbitkan generation dan ownership.

Failure handling perlu mempertahankan fence

Client yang menerima stale-token rejection harus menganggap authority-nya sudah hilang. Retry mutation yang sama dengan token yang sama tidak dapat membuat generation tersebut menjadi current kembali.

Recovery yang aman biasanya kembali ke coordination: hentikan work yang terikat pada lease lama, lepaskan local resource, lalu lakukan reacquisition hanya ketika aplikasi memang hendak memulai ownership epoch baru. Meminta token lebih baru hanya untuk memaksa operasi lama masuk akan merusak ownership protocol.

Observability sebaiknya menampilkan lease transition dan stale operation yang ditolak. Field yang berguna mencakup resource key, presented token, highest accepted token, lease owner identity, acquisition generation, dan rejection count. Record ini membuat race akibat pause lalu resume dapat terlihat tanpa menganggap setiap lease timeout sebagai data corruption event.

Fence berada dekat side effect

Distributed coordination tidak dapat secara paksa menghapus execution yang sudah berjalan di machine lain. Lease dapat menyatakan bahwa authority sudah berakhir, tetapi stale code dan delayed packet dapat tetap hidup setelah deklarasi tersebut.

Fencing token mengubah setiap ownership transfer menjadi ordered generation yang ikut dibawa oleh mutating operation. Setelah protected resource menerima generation yang lebih baru, holder sebelumnya tidak lagi dapat menulis melewati boundary tersebut. Lease menentukan ownership saat ini; resource menegakkan keputusan itu di tempat state benar-benar berubah.