Kem Intensif Pembangunan Backend Node.js · Pelajaran

Kunci Teragih dan Algoritma Redlock

Selaraskan akses eksklusif merentas tika dengan selamat dan fahami had penguncian teragih.

Pelajaran 2 daripada 413 langkah

Kunci Teragih dan Algoritma Redlock ialah pelajaran Kem Intensif Pembangunan Backend Node.js percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Anda boleh membaca keseluruhan pelajaran di bawah secara percuma — kemudian berlatih secara praktikal dalam pelayar menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kem Intensif Pembangunan Backend Node.js, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kem Intensif Pembangunan Backend Node.js merangkumi sejumlah 4 pelajaran.

Mengapa Kunci Teragih?

Apabila API Node.js anda berjalan sebagai satu proses, mutex dalam memori yang ringkas sudah memadai untuk menyerikan akses kepada bahagian kritikal. Namun, bahagian belakang dalam persekitaran pengeluaran berjalan pada banyak tika di belakang pengimbang beban, lazimnya merentasi beberapa mesin.

  • Dua pod mungkin cuba mengecaj invois yang sama.
  • Dua pekerja mungkin mengambil kerja yang sama daripada baris gilir.
  • Dua permintaan mungkin menjana semula entri cache mahal yang sama (cache stampede).

Kunci dalam memori hanya wujud dalam satu proses — tika lain tidak mengetahuinya. Untuk menyelaraskan akses eksklusif merentasi tika, anda memerlukan kunci yang berada dalam storan luaran dikongsi, dan Redis ialah tempat popular untuk menyimpannya.

Kunci Redis Pertama (Naif)

Primitif terasnya ialah perintah atomik SET key value NX PX ttl. NX bermaksud "tetapkan hanya jika kunci itu tidak wujud", manakala PX menetapkan luput dalam milisaat supaya kunci dilepaskan secara automatik jika pemegangnya terhenti.

  • Jika SET mengembalikan OK, anda telah memperoleh kunci.
  • Jika ia mengembalikan null, orang lain sedang memegangnya.

Nilainya mestilah token rawak unik bagi setiap pemerolehan — anda memerlukannya kemudian untuk melepaskan kunci dengan selamat.

const { createClient } = require('redis');
const crypto = require('crypto');

async function acquire(redis, key, ttlMs) {
  const token = crypto.randomUUID();
  // NX = set only if absent, PX = expiry in ms
  const ok = await redis.set(key, token, { NX: true, PX: ttlMs });
  return ok === 'OK' ? token : null;
}

// Usage sketch (needs a running Redis):
// const redis = createClient(); await redis.connect();
// const token = await acquire(redis, 'lock:invoice:42', 10000);
// if (token) { /* do exclusive work */ }

Melepaskan dengan Selamat: Periksa dan Padam

Pelepasan ialah bahagian yang berbahaya. DEL key yang naif boleh memadam kunci milik orang lain: jika kerja anda melebihi TTL, kunci itu luput, tika lain memperolehnya, kemudian DEL lewat anda memadam kunci mereka.

Penyelesaiannya: padam hanya jika nilai yang disimpan masih sama dengan token anda. Pemeriksaan kemudian pemadaman mestilah atomik, jadi kita menjalankannya sebagai skrip Lua — Redis melaksanakan skrip tanpa mencelah perintah lain.

const RELEASE_LUA = `
if redis.call('get', KEYS[1]) == ARGV[1] then
  return redis.call('del', KEYS[1])
else
  return 0
end`;

async function release(redis, key, token) {
  // Returns 1 if we owned and removed it, 0 otherwise
  return redis.eval(RELEASE_LUA, { keys: [key], arguments: [token] });
}

TTL: Keputusan Penalaan Paling Sukar

TTL ialah anggaran tentang tempoh bahagian kritikal anda berjalan.

  • Terlalu singkat dan kunci luput semasa kerja masih berjalan, lalu membenarkan pekerja kedua masuk — pengasingan bersama anda rosak.
  • Terlalu lama dan jika pemegang terhenti, semua orang perlu menunggu TTL penuh sebelum sesiapa boleh meneruskan.

Peraturan umum: tetapkan TTL kepada beberapa kali tempoh bahagian kritikal p99 anda, pastikan kerja yang dilindungi singkat, dan untuk tugas panjang gunakan pengawas yang memanjangkan kunci secara berkala berbanding satu TTL yang sangat besar.

Memanjangkan Kunci (Corak Pengawas)

Untuk kerja yang tempohnya tidak menentu, peroleh TTL sederhana dan perbaharuinya menggunakan pemasa selagi anda masih memegang kunci. Seperti pelepasan, peluasan mesti dilindungi oleh token anda supaya anda tidak memanjangkan kunci yang telah bertukar pemilik.

Pengawas berjalan kira-kira pada satu pertiga daripada TTL, memberikan ruang terhadap turun naik jam dan jeda GC.

const EXTEND_LUA = `
if redis.call('get', KEYS[1]) == ARGV[1] then
  return redis.call('pexpire', KEYS[1], ARGV[2])
else
  return 0
end`;

function startWatchdog(redis, key, token, ttlMs) {
  const timer = setInterval(async () => {
    const ok = await redis.eval(EXTEND_LUA, {
      keys: [key], arguments: [token, String(ttlMs)],
    });
    if (ok !== 1) clearInterval(timer); // lost the lock; stop renewing
  }, Math.floor(ttlMs / 3));
  return () => clearInterval(timer);
}

Redis Satu Nod ialah SPOF

Setakat ini, semuanya mengandaikan satu nod Redis. Nod itu ialah titik kegagalan tunggal, jadi pasukan menambah replika dengan failover. Namun, replikasi Redis adalah tak segerak, dan keadaan ini secara senyap memecahkan pengecualian bersama:

  • Client A memperoleh kunci pada induk.
  • Induk ranap sebelum meniru penulisan itu ke replika.
  • Replika dinaikkan taraf; ia tidak mempunyai rekod kunci tersebut.
  • Client B memperoleh "kunci yang sama" pada induk baharu.

Kini dua klien memegang kunci itu secara serentak. Algoritma Redlock direka untuk menangani jangka masa failover ini.

Algoritma Redlock

Redlock menggunakan N induk Redis bebas (biasanya 5), dengan tiada replikasi antara satu sama lain. Untuk memperoleh kunci, klien:

  • Merekod masa mula, kemudian cuba SET NX PX kunci+token yang sama pada semua N nod, menggunakan had masa singkat bagi setiap nod.
  • Mengira kejayaan. Kunci hanya dianggap diperoleh jika mendapat kuorum (N/2 + 1, iaitu 3 daripada 5) dan jumlah masa berlalu kurang daripada TTL.
  • Kesahan berkesan = TTL ditolak masa berlalu ditolak elaun hanyutan jam.

Jika gagal mencapai kuorum (atau kehabisan masa), ia membuka kunci semua nod dan mencuba semula selepas kelewatan rawak yang singkat.

Menggunakan Pustaka redlock

Anda jarang melaksanakan Redlock secara manual. Pakej npm redlock menerima tatasusunan klien Redis bebas dan menyediakan using(), yang memperoleh, melanjutkan secara automatik dan melepaskan kunci di sekeliling panggilan balik anda.

  • retryCount / retryDelay mengawal sejauh mana percubaan dibuat sebelum berputus asa.
  • using() memberikan anda satu isyarat — semak signal.aborted untuk mengesan bahawa kunci telah hilang semasa kerja sedang berjalan.
const Client = require('ioredis');
const Redlock = require('redlock').default;

const nodes = [
  new Client({ host: 'redis-a' }),
  new Client({ host: 'redis-b' }),
  new Client({ host: 'redis-c' }),
];

const redlock = new Redlock(nodes, {
  retryCount: 10,
  retryDelay: 200,   // ms between attempts
  driftFactor: 0.01, // clock-drift allowance
});

async function chargeInvoice(id) {
  await redlock.using([`lock:invoice:${id}`], 5000, async (signal) => {
    await doCharge(id);
    if (signal.aborted) throw signal.error; // lost the lock
  });
}

Token Pagar: Jaring Keselamatan Sebenar

Kritikan Martin Kleppmann yang terkenal: tiada kunci berasaskan had masa dapat menjamin keselamatan jika pemegangnya dijeda (kutipan sampah, tersekatnya VM) melepasi TTL. Kunci luput, klien lain meneruskan kerja, dan klien yang dijeda terjaga semula dengan kepercayaan bahawa ia masih memegang kunci.

Pertahanan yang teguh ialah token pagar: nombor yang sentiasa meningkat dan dikeluarkan bersama setiap pemberian kunci. Sumber itu sendiri menolak sebarang penulisan yang membawa token lebih rendah daripada token tertinggi yang telah dilihatnya — maka penulis lama yang dijeda dihalang di destinasi.

// Resource-side guard: reject writes with a stale fencing token.
function makeFencedStore() {
  let highestSeen = 0;
  const data = {};
  return {
    write(key, value, token) {
      if (token <= highestSeen) {
        throw new Error(`fenced: token ${token} <= ${highestSeen}`);
      }
      highestSeen = token;
      data[key] = value;
      return token;
    },
  };
}

const store = makeFencedStore();
store.write('balance', 100, 33);     // ok, token 33
try {
  store.write('balance', 999, 32);   // stale writer, fenced out
} catch (e) {
  console.log(e.message);            // fenced: token 32 <= 33
}
console.log('stored:', store.write('balance', 200, 34)); // 34

Kunci berbanding Keidempotenan

Kunci mengurangkan kemungkinan pelaksanaan serentak, tetapi had masa dan failover bermakna anda tidak boleh menjadikannya jaminan mutlak. Anggap kunci sebagai pengoptimuman, bukan pertahanan terakhir.

  • Jadikan operasi yang dilindungi keidempoten — menjalankannya dua kali menghasilkan keputusan yang sama.
  • Gunakan kekangan unik pangkalan data atau kemas kini bersyarat (bandingkan-dan-tetapkan) supaya penulisan pendua gagal dengan jelas.
  • Gunakan token pagar apabila sumber menyokongnya.

Amalan terbaik: gunakan kunci untuk mengelakkan kerja yang terbuang dan perebutan sumber, tetapi reka bentuk sistem supaya pelaksanaan berganda yang jarang berlaku masih betul.

Adakah Anda Benar-Benar Memerlukan Redlock?

Redlock menambah kos operasi: lima penggunaan Redis bebas, pengurusan jam yang teliti dan pelarasan percubaan semula. Penyelenggara redis sendiri menyatakan bahawa untuk kes penggunaan kecekapan (mengelakkan kerja yang sama dilakukan dua kali), kunci satu nod sudah memadai — pelaksanaan berganda sekali-sekala hanya membazirkan sedikit kerja.

  • Kunci kecekapan (pembinaan semula cache, penyahduplikatan): satu Redis SET NX PX sudah mencukupi.
  • Kunci ketepatan (wang, inventori): jangan bergantung pada mana-mana kunci had masa sahaja — tambahkan keidempotenan dan pemagaran, tanpa mengira Redlock.

Gunakan Redlock hanya apabila failover HA satu nod benar-benar tidak boleh diterima dan anda tidak dapat memagar pada sumber.

Semakan Pantas

Uji pemahaman anda tentang keselamatan penguncian teragih.

Ringkasan

Anda telah mempelajari cara menyelaras akses eksklusif merentas tika Node.js — serta batasannya.

  • Peroleh dengan SET key token NX PX ttl atomik; token mestilah unik bagi setiap pemerolehan.
  • Lepaskan dan lanjutkan hanya melalui skrip Lua yang menyemak token supaya anda tidak menyentuh kunci orang lain; perbaharui tugas yang panjang dengan pemantau.
  • TTL ialah pertukaran: terlalu pendek memecahkan pengecualian, terlalu panjang melambatkan pemulihan selepas ranap.
  • Redlock menggunakan kuorum merentas N induk bebas untuk bertahan daripada failover satu nod, tetapi ia masih berasaskan had masa.
  • Tiada kunci had masa yang selamat daripada jeda panjang — tambahkan token pagar dan keidempotenan untuk kerja yang kritikal kepada ketepatan.
  • Gunakan kunci satu nod untuk kecekapan; simpan Redlock untuk keperluan HA yang sebenar.
Percuma untuk bermula

Pelajari JavaScript dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
22
Pelajaran
92

Soalan Lazim

Adakah pelajaran “Kunci Teragih dan Algoritma Redlock” percuma?

Ya — teks penuh “Kunci Teragih dan Algoritma Redlock” boleh dibaca secara percuma di web ini. Untuk berlatih secara interaktif menggunakan penyunting kod terbina dalam dan tutor kecerdasan buatan 24/7, serta membuka kunci baki kursus Kem Intensif Pembangunan Backend Node.js, tingkat taraf kepada CoddyKit PRO. Kursus Kem Intensif Pembangunan Backend Node.js merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Kunci Teragih dan Algoritma Redlock”?

Selaraskan akses eksklusif merentas tika dengan selamat dan fahami had penguncian teragih. Anda berlatih Kem Intensif Pembangunan Backend Node.js menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Kem Intensif Pembangunan Backend Node.js?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Kem Intensif Pembangunan Backend Node.js di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Kunci Teragih dan Algoritma Redlock” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kem Intensif Pembangunan Backend Node.js ini?

Ya. Setiap pelajaran Kem Intensif Pembangunan Backend Node.js menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Strategi Cache-Aside, Write-Through dan TTL
  2. Kunci Teragih dan Algoritma Redlock
  3. Pub/Sub, Stream dan Pengehadan Kadar dengan Redis
  4. Mencegah Serbuan Cache dan Gerombolan Bergemuruh
← Kembali ke Kem Intensif Pembangunan Backend Node.js