MongoDB Academy · Oppitunti

Tapahtumien suorituskykyyn liittyvät näkökohdat

Oppijat mittaavat usean dokumentin tapahtumien aiheuttamaa kuormaa ja suunnittelevat skeemoja, jotka vähentävät niiden tarvetta kuormitetuilla suorituspoluilla.

Oppitunti 4/413 vaihetta

Tapahtumien suorituskykyyn liittyvät näkökohdat on ilmainen MongoDB Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu MongoDB Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. MongoDB Academy-kurssilla on yhteensä 4 oppituntia.

Transaktioilla on todellinen kuormitus

MongoDB:n usean dokumentin transaktiot tarjoavat tehokkaat ACID-takuut, mutta aiheuttavat mitattavaa suorituskykykuormaa. Ne edellyttävät ylimääräisiä verkkokierroksia istunnon hallintaan, varaavat samanaikaisia kirjoittajia estäviä lukituksia, kuluttavat oplog-tilaa ja edellyttävät koordinointia replikaasarjan jäsenten välillä enemmistön kirjoitushuomiointia varten. Tämän kuormituksen ymmärtäminen auttaa suunnittelemaan järjestelmiä, joissa transaktioita käytetään vain silloin, kun niitä tarvitaan.

Lukituskilpailu ja kirjoitusristiriidat

MongoDB:n transaktiot käyttävät dokumenttitason lukitusta ja optimistista samanaikaisuuden hallintaa. Kun transaktio lukee dokumentin, se ottaa tilannevedoksen mutta ei lukitse dokumenttia. Vahvistushetkellä MongoDB tarkistaa, onko jokin toinen kirjoittaja muokannut näitä dokumentteja. Jos näin on, transaktio keskeytetään kirjoitusristiriidan vuoksi. Toistuvat ristiriidat osoittavat, että useat transaktiot kilpailevat samoista kuormitetuista dokumenteista, mikä aiheuttaa uudelleenyrityksiä ja heikentää suorituskykyä.

// A 'hot document' that many transactions modify simultaneously
// causes frequent WriteConflict errors and retry storms:
db.counters.updateOne({ _id: 'globalOrderCount' }, { $inc: { value: 1 } }, { session });
// Better: use $inc on individual order documents (sharded by orderId),
// or use a dedicated sequence generator outside the transaction.

Tilannevedoseristyksen kustannus

Transaktiot lukevat johdonmukaisesta tilannevedoksesta, joka otetaan transaktion alussa. Kun muut kirjoittajat vahvistavat muutoksia transaktion keston aikana, MongoDB:n on säilytettävä muokattujen dokumenttien vanhat versiot (WiredTigerin MVCC-mekanismin avulla), jotta transaktio voi edelleen nähdä saman tilannevedoksen. Pitkään kestävät transaktiot saavat WiredTigerin säilyttämään enemmän versiohistoriaa muistissa ja levyllä, mikä voi aiheuttaa välimuistipainetta ja hidastaa koko klusteria.

60 sekunnin rajoitukselle on hyvä syy

MongoDB keskeyttää yli 60 sekuntia kestävät transaktiot (raja on määritettävissä, mutta sitä pitäisi harvoin suurentaa). Minuutteja kestävä transaktio säilyttää tilannevedostietoja ja estää oplogin lyhentämisen. Siksi pitkäkestoiset toiminnot, kuten eräkäsittely, monimutkaiset koostekyselyt tai ulkoisten API-vastausten odottaminen, eivät saa koskaan olla transaktion sisällä. Pidä transaktiot millisekuntien, älä sekuntien, mittaisina.

// WRONG: calling an external API inside a transaction
await session.withTransaction(async () => {
  const order = await db.collection('orders').findOne({ _id: orderId }, { session });
  const result = await externalPaymentAPI.charge(order.amount); // Could take seconds!
  await db.collection('orders').updateOne({ _id: orderId }, { $set: { paid: true } }, { session });
});

// RIGHT: call external API outside the transaction
const result = await externalPaymentAPI.charge(amount); // Do this FIRST
if (result.success) {
  await db.collection('orders').updateOne({ _id: orderId }, { $set: { paid: true, txnId: result.id } });
}

Oplogin kokorajoitus: 16 Mt transaktiota kohden

Jokainen transaktion kirjoitus tallennetaan oplogiin. MongoDB rajoittaa yksittäisen transaktion käyttämän oplog-tilan kokonaismäärän noin 16 Mt:uun. Jos transaktio käsittelee suuren määrän dokumentteja tai suuria dokumentteja, se voi ylittää tämän rajan ja keskeytyä virheellä TransactionTooLarge. Jos sinun on käsiteltävä suuria eriä, jaa ne pienemmiksi transaktioiksi, joissa on esimerkiksi muutama sata dokumenttia kussakin.

// WRONG: inserting 100,000 documents in one transaction
await session.withTransaction(async () => {
  for (const doc of largeArray) { // 100k docs = way over 16MB
    await db.collection('logs').insertOne(doc, { session });
  }
});

// RIGHT: batch into smaller transactions of ~500 docs
const BATCH_SIZE = 500;
for (let i = 0; i < largeArray.length; i += BATCH_SIZE) {
  const batch = largeArray.slice(i, i + BATCH_SIZE);
  await session.withTransaction(async () => {
    await db.collection('logs').insertMany(batch, { session });
  });
}

Skeeman suunnittelu transaktioiden vähentämiseksi

Paras suorituskykyoptimointi transaktioille on käyttää niitä vähemmän. MongoDB:n yhden dokumentin atomisuus tarkoittaa, että yhden dokumentin toiminnot ovat aina ACID-yhteensopivia. Suunnittele skeemasi niin, että atomisesti suoritettavissa toimintokokonaisuuksissa käsitellään mahdollisimman vähän dokumentteja. Tehokkain lähestymistapa on upottaa toisiinsa liittyvät tiedot, jotka päivitetään aina yhdessä, samaan dokumenttiin.

// Without embedding: two documents to update atomically (needs transaction)
await accounts.updateOne({ _id: userId }, { $set: { name: 'Alice' } }, { session });
await profiles.updateOne({ userId: userId }, { $set: { displayName: 'Alice' } }, { session });

// With embedding: one document — no transaction needed
await users.updateOne(
  { _id: userId },
  { $set: { name: 'Alice', 'profile.displayName': 'Alice' } }
  // No session needed — single-document update is atomic

Transaktioiden aiheuttaman kuormituksen mittaaminen

Käyttäkää explain('executionStats')-komentoa ja tietokantaprofiloijaa mitataksenne tapahtumienne todellisen yleiskustannuksen. Tapahtumat näkyvät hitaiden kyselyiden lokissa ja system.profile-kokoelmassa, ja niiden transaction-kenttä on täytetty. Seuratkaa esimerkiksi tapahtumien keskimääräistä kestoa, kirjoitusristiriitojen määrää ja yritysten määrää tapahtumatyypeittäin. Näistä mittareista näette, vaikuttaako tapahtumien yleiskustannus sovelluksen viivebudjettiin.

// Enable the profiler to capture slow transactions (threshold: 100ms)
db.setProfilingLevel(1, { slowms: 100 });

// Query the profile for recent slow transactions
db.system.profile.find(
  { 'transaction': { $exists: true } },
  { millis: 1, 'transaction.timingStats': 1, op: 1 }
).sort({ ts: -1 }).limit(10);

Pitkään pidettävien lukitusten välttäminen findOneAndUpdate-toiminnolla

Kun tarvitsette yhden dokumentin atomista tarkistamista ja muokkaamista, findOneAndUpdate tarjoaa ACID-atomisuuden ilman tapahtumaa. Se etsii suodattimen täyttävän dokumentin, toteuttaa päivityksen ja palauttaa joko vanhan tai uuden dokumentin yhtenä palvelinpuolen operaationa. Tämä on suositeltu toimintamalli esimerkiksi test-and-set-operaatioille, atomisille laskureille ja jonoalkioiden varaamiselle.

// Atomically claim a pending task — no transaction needed
const task = await db.collection('taskQueue').findOneAndUpdate(
  { status: 'pending' },
  { $set: { status: 'processing', claimedAt: new Date(), workerId: workerId } },
  { returnDocument: 'after', sort: { priority: -1 } }
);

if (!task) {
  console.log('No pending tasks');
}

Kaksivaiheinen vahvistus vaihtoehtona

Ennen kuin MongoDB 4.0 toi natiivit tapahtumat, kehittäjät toteuttivat kaksivaiheisen vahvistuksen manuaalisesti saavuttaakseen usean dokumentin atomisuuden. Tässä toimintamallissa keskitetty ”transaction document” seuraa operaation tilaa (pending, applied, done, rollback). Vaikka natiivit tapahtumat ovat nykyään suositeltavia, kaksivaiheisen vahvistuksen ymmärtäminen havainnollistaa, miksi tapahtumien yleiskustannusta syntyy, ja auttaa tilanteissa, joissa tapahtumia ei voida käyttää (esimerkiksi vanhempien MongoDB-versioiden shardoituissa klustereissa).

// Two-phase commit concept (legacy pattern, prefer native transactions):
// 1. Insert a 'pending' transaction document
// 2. Apply to each document, recording txn ID
// 3. Update transaction to 'committed'
// 4. On failure, query for pending transactions and roll back

Read Concern ja sen suorituskykyvaikutukset

Tapahtumien oletusarvo on readConcern: 'snapshot', joka tarjoaa täyden eristyksen mutta saattaa joutua odottamaan, että replikasetin enemmistö on vahvistanut vastaanottaneensa uusimmat tiedot. readConcern: 'local' on nopeampi, mutta sen avulla voidaan lukea tietoja, jotka palautetaan failoverin yhteydessä. Useimmissa sovellusten tapahtumissa 'snapshot' on oikea valinta. Käyttäkää 'local'-asetusta vain, jos olette harkinneet johdonmukaisuuteen liittyvät vaikutukset huolellisesti.

// 'snapshot' — full isolation, may be slightly slower
session.startTransaction({ readConcern: { level: 'snapshot' }, writeConcern: { w: 'majority' } });

// 'local' — faster reads, weaker consistency guarantee
session.startTransaction({ readConcern: { level: 'local' }, writeConcern: { w: 'majority' } });

Yhteenveto: tapahtumien suorituskykysäännöt

Viisi sääntöä suorituskykyiseen tapahtumien käyttöön: (1) Pitäkää tapahtumat lyhyinä – millisekunteja, ei sekunteja. (2) Älkää koskaan suorittako tietokannan ulkopuolista I/O:ta tapahtuman sisällä. (3) Minimoikaa tapahtumassa käsiteltävien dokumenttien määrä pienentääksenne ristiriitojen mahdollisuutta. (4) Käyttäkää yhden dokumentin operaatioita tai upotusta aina kun mahdollista, jotta voitte välttää tapahtumat kokonaan. (5) Seuratkaa kirjoitusristiriitojen määrää ja suunnitelkaa usein ristiriitoja aiheuttavat dokumentit uudelleen.

Pikatarkistus

Testatkaa, miten hyvin ymmärrätte tämän oppitunnin MongoDB- ja NoSQL Databases -käsitteet.

Oppitunnin kertaus

Tässä oppitunnissa opitte, että tapahtumat lisäävät yleiskustannusta snapshot-eristyksen, lukituskilpailun ja oplog-tilan kulutuksen kautta, tapahtumat tulee pitää lyhyinä (millisekunteina) eikä niiden sisällä saa koskaan suorittaa hidasta I/O:ta ja paras optimointi on usein skeemojen uudelleensuunnittelu siten, että yhden dokumentin atomisuus poistaa usean dokumentin tapahtumien tarpeen. Seuraavaksi tutustumme change streams -toimintoon, joka tarjoaa reaaliaikaisia tapahtumasyötteitä MongoDB-kokoelmista.

Aloita maksutta

Opi JavaScript tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Tapahtumien suorituskykyyn liittyvät näkökohdat” ilmainen?

Kyllä – oppitunnin ”Tapahtumien suorituskykyyn liittyvät näkökohdat” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko MongoDB Academy-kurssin, päivitä CoddyKit PROhon. MongoDB Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Tapahtumien suorituskykyyn liittyvät näkökohdat”?

Oppijat mittaavat usean dokumentin tapahtumien aiheuttamaa kuormaa ja suunnittelevat skeemoja, jotka vähentävät niiden tarvetta kuormitetuilla suorituspoluilla. Harjoittelet MongoDB Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni MongoDB Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin MongoDB Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Tapahtumien suorituskykyyn liittyvät näkökohdat”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä MongoDB Academy-oppitunnilla?

Kyllä. Jokainen MongoDB Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. ACID-takuut hajautetussa dokumenttivarastossa
  2. Istunnon ja usean dokumentin tapahtuman aloittaminen
  3. Virheenkäsittely ja uudelleenyrityslogiikka
  4. Tapahtumien suorituskykyyn liittyvät näkökohdat
← Takaisin: MongoDB Academy