INTEGRITY Dokumentace

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.

Deploy to Cloudflare

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í

koncept replikace pro čtení D1

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í:

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.

  1. V dashboardu Cloudflare přejděte na D1 stránce.

    Přejděte na SQL databáze D1 ↗
  2. 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()

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()

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() ?? "")

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 ?? "",
});

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);

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:

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:

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í.

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.

Distribuované repliky mohou bez Sessions API způsobit nekonzistence
  1. Váš zápisový SQL dotaz zpracovává primární instance databáze.
  2. Obdržíte odpověď potvrzující zápisový dotaz.
  3. Váš následný čtecí SQL dotaz jde na čtecí repliku.
  4. 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.

D1 nabízí sekvenční konzistenci při použití Sessions API
  1. SQL zápisový dotaz zpracovává primární instance databáze.
  2. Obdržíte odpověď potvrzující zápisový dotaz. Zároveň obdržíte bookmark (100), který identifikuje stav databáze po zápisovém dotazu.
  3. Váš následný čtecí SQL dotaz jde na čtecí repliku a zároveň poskytuje bookmark (100).
  4. Replika pro čtení počká, dokud nebude aktualizována alespoň na úroveň zadaného bookmarku (100).
  5. 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:

Doplňující informace

Mohou se vám hodit následující zdroje: