← Cloudflare D1 / d1 / best-practices
Globální replikace pro čtení
Replikace pro čtení D1 dokáže snížit latenci čtecích dotazů a zvýšit propustnost čtení přidáním kopií databáze pouze pro čtení, nazývaných čtecí repliky, do regionů po celém světě blíže klientům.
Pro použití replikace pro čtení musíte použít D1 Sessions API, jinak budou všechny dotazy nadále zpracovávány pouze primární databází.
Relace zapouzdřuje všechny dotazy jedné logické relace vaší aplikace. Relace může například odpovídat všem dotazům pocházejícím z konkrétní relace webového prohlížeče. Všechny dotazy v rámci relace čtou z instance databáze, která je tak aktuální, jak to váš dotaz vyžaduje. Sessions API zajišťuje sekvenční konzistence pro všechny dotazy v rámci relace.
Chcete-li vyzkoušet replikaci pro čtení D1, nasaďte následující kód Workeru pomocí Sessions API, který vás vyzve k vytvoření databáze D1 a povolení replikace pro čtení na této databázi.
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// A. Create the Session.
// When we create a D1 Session, we can continue where we left off from a previous
// Session if we have that Session's last bookmark or use a constraint.
const bookmark =
request.headers.get("x-d1-bookmark") ?? "first-unconstrained";
const session = env.DB01.withSession(bookmark);
try {
// Use this Session for all our Workers' routes.
const response = await withTablesInitialized(
request,
session,
handleRequest,
);
// B. Return the bookmark so we can continue the Session in another request.
response.headers.set("x-d1-bookmark", session.getBookmark() ?? "");
return response;
} catch (e) {
console.error({
message: "Failed to handle request",
error: String(e),
errorProps: e,
url,
bookmark,
});
return Response.json(
{ error: String(e), errorDetails: e },
{ status: 500 },
);
}
},
};export default {
async fetch(request, env, ctx): Promise<Response> {
const url = new URL(request.url);
// A. Create the Session.
// When we create a D1 Session, we can continue where we left off from a previous
// Session if we have that Session's last bookmark or use a constraint.
const bookmark =
request.headers.get("x-d1-bookmark") ?? "first-unconstrained";
const session = env.DB01.withSession(bookmark);
try {
// Use this Session for all our Workers' routes.
const response = await withTablesInitialized(
request,
session,
handleRequest,
);
// B. Return the bookmark so we can continue the Session in another request.
response.headers.set("x-d1-bookmark", session.getBookmark() ?? "");
return response;
} catch (e) {
console.error({
message: "Failed to handle request",
error: String(e),
errorProps: e,
url,
bookmark,
});
return Response.json(
{ error: String(e), errorDetails: e },
{ status: 500 },
);
}
},
} satisfies ExportedHandler<Env>;Primární instance databáze oproti replikám pro čtení
Při použití D1 bez replikace pro čtení směruje D1 všechny dotazy (čtení i zápis) na konkrétní instanci databáze v jedno místo na světě, označovaný jako primární instance databáze . Latence požadavků D1 závisí na fyzické vzdálenosti uživatele od primární instance databáze. Uživatelé nacházející se dále od primární instance databáze zaznamenávají vyšší latenci požadavků kvůli čas síťové zpáteční cesty ↗.
Při použití replikace pro čtení vytváří D1 několik asynchronně replikovaných kopií primární instance databáze, které obsluhují pouze požadavky na čtení a nazývají se repliky pro čtení . D1 vytváří tyto repliky pro čtení v více regionů po celém světě v rámci sítě Cloudflare.
I když se uživatel může nacházet daleko od primární instance databáze, může být blízko repliky pro čtení. Když D1 směruje čtecí požadavky na repliku pro čtení místo na primární instanci databáze, uživatel díky tomu získává rychlejší odpovědi na své čtecí dotazy.
D1 asynchronně replikuje změny z instance primární databáze do všech čtecích replik. To znamená, že čtecí replika může být kdykoli libovolně zastaralá. Doba, za kterou se nejnovější potvrzená data z primární databáze replikují do čtecí repliky, se označuje jako zpoždění replik . Zpoždění replik a nedeterministické směrování na jednotlivé repliky může vést k problémům s konzistencí dat aplikace. D1 Sessions API tento problém řeší tím, že zajišťuje sekvenční konzistenci. Další informace naleznete v zpoždění replik a model konzistence.
| Typ instance databáze | Popis | Jak zpracovává zápisové dotazy | Jak zpracovává dotazy na čtení |
|---|---|---|---|
| Primární instance databáze | Instance databáze obsahující „originální“ kopii databáze | Dokáže obsluhovat zápisové dotazy | Dokáže obsluhovat čtecí dotazy |
| Instance databáze čtecí repliky | Instance databáze obsahující kopii původní databáze, která asynchronně přijímá aktualizace z primární instance databáze | Přeposílá všechny zápisové dotazy do primární instance databáze | Dokáže obsluhovat čtecí dotazy pomocí vlastní kopie databáze |
Výhody replikace pro čtení
Systém s více replikami pro čtení rozmístěnými po celém světě zlepšuje výkon databází:
- Latence dotazů klesá u uživatelů nacházejících se blízko replik pro čtení. Zkrácením fyzické vzdálenosti mezi instancí databáze a uživatelem klesá latence čtecích dotazů, což vede k rychlejší aplikaci.
- Propustnost čtení se zvyšuje rozložením zátěže mezi více replik. Protože více instancí databáze dokáže obsluhovat požadavky pouze pro čtení, vaše aplikace může v daném okamžiku obsloužit větší počet dotazů.
Použití Sessions API
Použitím Sessions API pro čtecí replikaci, všechny vaše dotazy z jedné čtení relace z verze databáze, která zajišťuje sekvenční konzistenci. To zajišťuje, že verze databáze, kterou čtete, je logicky konzistentní i v případě, že jsou dotazy zpracovávány různými čtecími replikami.
Replikace pro čtení D1 toho dosahuje připojením bookmark ke každému dotazu v rámci relace. Další informace najdete na Bookmarky.
Povolit replikaci pro čtení
Replikaci pro čtení lze povolit na úrovni databáze v Cloudflare dashboardu. Zkontrolujte Nastavení pro vaši databázi D1, abyste zjistili, zda je čtecí replikace povolena.
-
V dashboardu Cloudflare přejděte na D1 stránce.
Přejděte na SQL databáze D1 ↗ -
Vyberte existující databázi > Nastavení > Enable Read Replication.
Spusťte relaci bez omezení
Chcete-li vytvořit relaci z libovolné dostupné verze databáze, použijte withSession() bez jakýchkoli parametrů, což první dotaz nasměruje na libovolnou instanci databáze, ať už na primární instanci databáze, nebo na read repliku.
const session = env.DB.withSession() // synchronous
// query executes on either primary database or a read replica
const result = await session
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
.run()withSession()je stejný jakowithSession("first-unconstrained")- Tento přístup je nejvhodnější, pokud vaše aplikace nepotřebuje nejnovější verzi databáze. Všechny dotazy v rámci relace zajišťují sekvenční konzistenci.
- Viz Dokumentace D1 Workers Binding API.
Spusťte relaci se všemi nejnovějšími daty
Chcete-li vytvořit relaci z nejnovější verze databáze, použijte withSession("first-primary"), který první dotaz přesměruje na primární instanci databáze.
const session = env.DB.withSession(`first-primary`) // synchronous
// query executes on primary database
const result = await session
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
.run()- Tento přístup je nejvhodnější, pokud vaše aplikace potřebuje nejnovější verzi databáze. Všechny dotazy v rámci relace zajišťují sekvenční konzistenci.
- Viz Dokumentace D1 Workers Binding API.
Spusťte relaci z předchozího kontextu (bookmark)
Chcete-li vytvořit novou relaci v kontextu předchozí relace, předejte bookmark parametr, který zaručuje, že relace začíná s verzí databáze přinejmenším stejně aktuální, jako je uvedená bookmark.
// retrieve bookmark from previous session stored in HTTP header
const bookmark = request.headers.get('x-d1-bookmark') ?? 'first-unconstrained';
const session = env.DB.withSession(bookmark)
const result = await session
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
.run()
// store bookmark for a future session
response.headers.set('x-d1-bookmark', session.getBookmark() ?? "")- Zahájení relace s
bookmarkzajišťuje, že nová relace bude minimálně stejně aktuální jako předchozí relace, která vygenerovala danýbookmark. - Viz Dokumentace D1 Workers Binding API.
Zkontrolujte, kde byl požadavek D1 zpracován
Jak jsou požadavky D1 zpracovávány díky přidání replik pro čtení, zjistíte served_by_region a served_by_primary pole se vrací v meta objekt D1 Result.
const result = await env.DB.withSession()
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
.run();
console.log({
servedByRegion: result.meta.served_by_region ?? "",
servedByPrimary: result.meta.served_by_primary ?? "",
});served_by_regionaserved_by_primaryjsou přítomna u všech vzdálených požadavků D1 bez ohledu na to, zda je povolena replikace pro čtení nebo zda se používá Sessions API. Při lokálním vývojinpx wrangler dev, tato pole jsouundefined.
Povolení replikace pro čtení prostřednictvím REST API
V REST API nastavte read_replication.mode: auto k zapnutí replikace pro čtení u databáze D1.
Pro tento koncový bod REST potřebujete API token s D1:Edit oprávnění. Pokud nemáte API token, postupujte podle návodu: Vytvoření API tokenu.
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"read_replication": {"mode": "auto"}}'const headers = new Headers({
"Authorization": `Bearer ${TOKEN}`
});
await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
method: "PUT",
headers: headers,
body: JSON.stringify(
{ "read_replication": { "mode": "auto" } }
)
}
)Zakázání replikace pro čtení prostřednictvím REST API
V REST API nastavte read_replication.mode: disabled k vypnutí replikace pro čtení u databáze D1.
Pro tento koncový bod REST potřebujete API token s D1:Edit oprávnění. Pokud nemáte API token, postupujte podle návodu: Vytvoření API tokenu.
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"read_replication": {"mode": "disabled"}}'const headers = new Headers({
"Authorization": `Bearer ${TOKEN}`
});
await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
method: "PUT",
headers: headers,
body: JSON.stringify(
{ "read_replication": { "mode": "disabled" } }
)
}
)Zkontrolujte, zda je povolena replikace pro čtení
Na dashboardu Cloudflare zkontrolujte Nastavení pro vaši databázi D1, abyste zjistili, zda je čtecí replikace povolena.
Alternativně, GET REST koncový bod databáze D1 vrací informaci o tom, zda je replikace pro čtení povolena, nebo zakázána.
Pro tento koncový bod REST potřebujete API token s D1:Read oprávnění. Pokud nemáte API token, postupujte podle návodu: Vytvoření API tokenu.
curl -X GET "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
-H "Authorization: Bearer $TOKEN"const headers = new Headers({
"Authorization": `Bearer ${TOKEN}`
});
const response = await fetch("/v4/accounts/{account_id}/d1/database/{database_id}", {
method: "GET",
headers: headers
});
const data = await response.json();
console.log(data.read_replication.mode);- Zkontrolujte
read_replicationvlastnost objekturesultobjekt"mode": "auto"znamená, že čtecí replikace je povolena"mode": "disabled"znamená, že čtecí replikace je zakázána
Umístění čtecích replik
V současnosti D1 automaticky vytváří repliku pro čtení v každý podporovaný region, včetně regionu, ve kterém se nachází primární instance databáze. Těmito regiony jsou:
- ENAM
- WNAM
- WEUR
- EEUR
- APAC
- OC
Observabilita
Pro zjištění dopadu replikace pro čtení a kontrolu, jak jsou požadavky D1 zpracovávány dalšími instancemi databáze, můžete použít:
-
metaobjekt v rámciD1Resultnávratový objekt, který obsahuje nová pole:served_by_regionserved_by_primary
- Cloudflare dashboard, kde můžete zobrazit rozdělení metrik vaší databáze podle regionu, který zpracovával požadavky D1.
Ceny
Replikace pro čtení je součástí D1, takže za čtecí repliky neplatíte žádné dodatečné náklady na úložiště ani výpočetní výkon. Vznikají vám naprosto stejné náklady na D1 účtování podle využití s replikami nebo bez nich, na základě rows_read a rows_written vašimi dotazy.
Známá omezení
Replikace pro čtení v D1 má některá známá omezení.
- Sessions API je dostupné pouze prostřednictvím D1 Worker Binding a zatím není dostupné prostřednictvím REST API.
Základní informace
Zpoždění replik a model konzistence
S ohledem na zpoždění replik, je důležité zohlednit model konzistence pro D1. Model konzistence je logický rámec, který určuje, jak databázový systém obsluhuje uživatelské dotazy (jak jsou data aktualizována a jak se k nim přistupuje), pokud existuje více instancí databáze. Různé modely se hodí pro různé případy použití. Většina databázových systémů poskytuje čtení potvrzených dat ↗, izolace snímku ↗, nebo serializovatelný ↗ modely konzistence v závislosti na jejich konfiguraci.
Bez rámce modelu konzistence
Zvažte, co by se mohlo stát v distribuovaném databázovém systému bez explicitního rámce pro vynucení modelu konzistence.
- Váš zápisový SQL dotaz zpracovává primární instance databáze.
- Obdržíte odpověď potvrzující zápisový dotaz.
- Váš následný čtecí SQL dotaz jde na čtecí repliku.
- Replika pro čtení ještě nebyla aktualizována, takže neobsahuje změny z vašeho zápisového SQL dotazu. Vrácené výsledky jsou z vašeho pohledu nekonzistentní.
S Sessions API
Při použití D1 Sessions API vaše dotazy získávají bookmarky, které replice pro čtení umožňují poskytovat pouze sekvenčně konzistentní data.
- SQL zápisový dotaz zpracovává primární instance databáze.
- Obdržíte odpověď potvrzující zápisový dotaz. Zároveň obdržíte bookmark (100), který identifikuje stav databáze po zápisovém dotazu.
- Váš následný čtecí SQL dotaz jde na čtecí repliku a zároveň poskytuje bookmark (100).
- Replika pro čtení počká, dokud nebude aktualizována alespoň na úroveň zadaného bookmarku (100).
- Jakmile se replika pro čtení aktualizuje (bookmark 104), obslouží váš dotaz na čtení, který je nyní sekvenčně konzistentní.
Na diagramu je vrácený bookmark s číslem 104, což se liší od bookmarku uvedeného ve vašem dotazu na čtení (bookmark 100). Může se to stát, pokud mezi vámi provedenými zápisovým a čtecím dotazem proběhly i jiné zápisy z jiných klientských požadavků, které se replikovaly do repliky pro čtení.
Sessions API poskytuje sekvenční konzistenci
Replikace pro čtení D1 nabízí sekvenční konzistence ↗. D1 vytváří globální pořadí všech operací provedených v databázi a dokáže určit nejnovější verzi databáze, kterou dotaz viděl, pomocí bookmarky. Poté dotaz obslouží instance databáze, která je minimálně stejně aktuální jako bookmark předaný spolu s dotazem ke spuštění.
Sekvenční konzistence má například tyto vlastnosti:
- Monotónní čtení: Pokud provedete dvě čtení za sebou (read-1, poté read-2), read-2 nemůže načíst verzi databáze starší než read-1.
- Monotónní zápisy: Pokud provedete write-1 a poté write-2, všechny procesy uvidí write-1 dříve než write-2.
- Zápisy navazují na čtení: Pokud přečtete hodnotu a poté provedete zápis, musí tento zápis vycházet z právě přečtené hodnoty.
- Čtení vlastních zápisů: Pokud zapíšete do databáze, všechna následující čtení tento zápis uvidí.
Doplňující informace
Mohou se vám hodit následující zdroje: