Skip to content

Commit d752ce0

Browse files
committed
Merge branch 'jun/d1/rr-v2' into rr-tutorial
2 parents 862128a + 6007ebc commit d752ce0

File tree

2 files changed

+43
-46
lines changed

2 files changed

+43
-46
lines changed
-690 Bytes
Loading

src/content/docs/d1/best-practices/read-replication.mdx

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@ sidebar:
88

99
import { GlossaryTooltip, Details, GitHubCode, APIRequest, Tabs, TabItem, TypeScriptExample } from "~/components"
1010

11-
D1 read replication can lower latency for read queries and scale read throughput by adding read-only database copies, called read replicas, across global regions closer to clients.
11+
D1 read replication can lower latency for read queries and scale read throughput by adding read-only database copies, called read replicas, across regions globally closer to clients.
1212

13-
Your application uses read replicas with D1 [Sessions API](/d1/worker-api/d1-database/#withsession). A Session encapsulates all the queries from one logical session for your application. For example, a Session may correspond to all queries coming from a particular web browser session. All queries within a Session read from a database instance which is as up-to-date as your query needs it to be. Sessions API ensures [sequential consistency](/d1/best-practices/read-replication/#replica-lag-and-consistency-model) for all queries in a Session.
13+
Your application can use read replicas with D1 [Sessions API](/d1/worker-api/d1-database/#withsession). A Session encapsulates all the queries from one logical session for your application. For example, a Session may correspond to all queries coming from a particular web browser session. All queries within a Session read from a database instance which is as up-to-date as your query needs it to be. Sessions API ensures [sequential consistency](/d1/best-practices/read-replication/#replica-lag-and-consistency-model) for all queries in a Session.
1414

1515
To use read replication with the following Worker code and Sessions API:
1616

17-
1. Enable read replication on a D1 database
17+
1. Enable read replication on a D1 database:
1818

1919
```curl
2020
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
2121
-H "Authorization: Bearer $TOKEN" \
2222
-H "Content-Type: application/json" \
2323
-d "{"read_replication": {"mode": "auto"}}"
2424
```
25-
2. Select `Deploy to Workers`.
25+
2. Deploy the following Worker using the `Deploy to Workers` button.
2626

2727
{/* Deploy to Workers button */}
2828

@@ -163,34 +163,36 @@ async function resetTables(session: D1DatabaseSession) {
163163

164164
![D1 read replication concept](/images/d1/d1-read-replication-concept.png)
165165

166-
When using D1 without read replication, D1 routes all queries (both read and write) to a specific database instance in [one location in the world](/d1/configuration/data-location/), known as the <GlossaryTooltip term="primary database instance"> primary database instance </GlossaryTooltip>. D1 request latency is dependent on the physical closeness of a user to the primary database instance. Users located further away from the primary database instance experience longer request latency due to [network round-trip time](https://www.cloudflare.com/learning/cdn/glossary/round-trip-time-rtt/).
166+
When using D1 without read replication, D1 routes all queries (both read and write) to a specific database instance in [one location in the world](/d1/configuration/data-location/), known as the <GlossaryTooltip term="primary database instance"> primary database instance </GlossaryTooltip>. D1 request latency is dependent on the physical proximity of a user to the primary database instance. Users located further away from the primary database instance experience longer request latency due to [network round-trip time](https://www.cloudflare.com/learning/cdn/glossary/round-trip-time-rtt/).
167167

168-
When using read replication, D1 introduces multiple, asynchronously replicated copies of the primary database instance which only serve read requests, called <GlossaryTooltip term="read replica"> read replicas </GlossaryTooltip>. D1 creates the read replicas in multiple regions throughout the world [across the Cloudflare network](/d1/best-practices/read-replication/#read-replica-locations).
168+
When using read replication, D1 creates multiple asynchronously replicated copies of the primary database instance, which only serve read requests, called <GlossaryTooltip term="read replica"> read replicas </GlossaryTooltip>. D1 creates the read replicas in multiple regions throughout the world [across the Cloudflare network](/d1/best-practices/read-replication/#read-replica-locations).
169169

170-
A user may be located far away from the primary database instance but close to a read replica. When D1 routes read requests to the read replica instead of the primary database instance, the user enjoys shorter read request response times.
171-
172-
D1 asynchronously replicates changes from the primary database instance to all read replicas. This means that at any given time, a read replica may be arbitrarily out of date. The time it takes for the latest committed data in the primary database instance to be replicated to the read replica is known as the <GlossaryTooltip term="replica lag"> replica lag </GlossaryTooltip>. It is replica lag and non-deterministic routing to individual replicas that can lead to application data consistency issues, which Sessions API helps handle by ensuring sequential consistency. For more information, refer to [replica lag and consistency model](/d1/best-practices/read-replication/#replica-lag-and-consistency-model).
170+
Even though a user may be located far away from the primary database instance, they could be close to a read replica. When D1 routes read requests to the read replica instead of the primary database instance, the user enjoys faster responses for their read queries.
173171

172+
D1 asynchronously replicates changes from the primary database instance to all read replicas. This means that at any given time, a read replica may be arbitrarily out of date. The time it takes for the latest committed data in the primary database instance to be replicated to the read replica is known as the <GlossaryTooltip term="replica lag"> replica lag </GlossaryTooltip>. Replica lag and non-deterministic routing to individual replicas can lead to application data consistency issues.
173+
The D1 Sessions API solves this by ensuring sequential consistency.
174+
For more information, refer to [replica lag and consistency model](/d1/best-practices/read-replication/#replica-lag-and-consistency-model).
175+
All write queries are still forwarded to the primary database instance. Read replication only improves the response time for read query requests.
174176
:::note
175-
All write queries are still forwarded to the primary database instance. Read replication only improves the query response time for read requests.
177+
All write queries are still forwarded to the primary database instance. Read replication only improves the response time for read query requests.
176178
:::
177179

178180
| Type of database instance | Description | How it handles write queries | How it handles read queries |
179181
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------- |
180182
| Primary database instance | The database instance containing the “original” copy of the database | Can serve write queries | Can serve read queries |
181-
| Read replica | A database instance containing an “almost up-to-date” copy of the original database, asynchronously updated against the primary database instance | Forwards any write queries to the primary database instance | Can serve read queries using its own copy of the database |
183+
| Read replica database instance | A database instance containing a copy of the original database which asynchronously receives updates from the primary database instance | Forwards any write queries to the primary database instance | Can serve read queries using its own copy of the database |
182184

183185
## Sessions API examples
184186

185-
By using Sessions API for read replication, all of your queries from a single <GlossaryTooltip term="session">Session</GlossaryTooltip> read from a version of the database which ensures sequential consistency. This ensures that the version of the database you are reading is logically consistent with your queries when using read replicas.
187+
By using Sessions API for read replication, all of your queries from a single <GlossaryTooltip term="session">Session</GlossaryTooltip> read from a version of the database which ensures sequential consistency. This ensures that the version of the database you are reading is logically consistent even if the queries are handled by different read replicas.
186188

187-
D1 read replication achieves this by attaching a <GlossaryTooltip term="bookmark">bookmark</GlossaryTooltip> to each write query within a Session. For more information, refer to [Bookmarks](/d1/reference/time-travel/#bookmarks).
189+
D1 read replication achieves this by attaching a <GlossaryTooltip term="bookmark">bookmark</GlossaryTooltip> to each query within a Session. For more information, refer to [Bookmarks](/d1/reference/time-travel/#bookmarks).
188190

189191
### Enable read replication
190192

191-
With REST API, set `"read_replication": "mode":"auto"` to enable read replication on a D1 database.
193+
With the REST API, set `read_replication.mode: auto` to enable read replication on a D1 database.
192194

193-
For REST API, use a [API token](/fundamentals/api/get-started/create-token/) with `D1:Edit` [permission](/fundamentals/api/reference/permissions/#account-permissions).
195+
For the REST API, use an [API token](/fundamentals/api/get-started/create-token/) with `D1:Edit` [permission](/fundamentals/api/reference/permissions/#account-permissions).
194196

195197
<Tabs>
196198
<TabItem label="cURL">
@@ -220,17 +222,17 @@ await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
220222

221223
### Disable read replication
222224

223-
With REST API, set `"read_replication": "mode":"disable"` to disable read replication on a D1 database.
225+
With the REST API, set `read_replication.mode: disabled` to disable read replication on a D1 database.
224226

225-
For REST API, use a [API token](/fundamentals/api/get-started/create-token/) with `D1:Edit` [permission](/fundamentals/api/reference/permissions/#account-permissions).
227+
For the REST API, use an [API token](/fundamentals/api/get-started/create-token/) with `D1:Edit` [permission](/fundamentals/api/reference/permissions/#account-permissions).
226228

227229
<Tabs>
228230
<TabItem label="cURL">
229231
```curl
230232
curl -X PUT "https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{database_id}" \
231233
-H "Authorization: Bearer $TOKEN" \
232234
-H "Content-Type: application/json" \
233-
-d "{"read_replication": {"mode": "disable"}}"
235+
-d "{"read_replication": {"mode": "disabled"}}"
234236
```
235237
</TabItem><TabItem label="TypeScript">
236238
```ts
@@ -242,7 +244,7 @@ await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
242244
method: "PUT",
243245
headers: headers,
244246
body: JSON.stringify(
245-
{ "read_replication": { "mode": "disable" } }
247+
{ "read_replication": { "mode": "disabled" } }
246248
)
247249
}
248250
)
@@ -254,7 +256,7 @@ await fetch ("/v4/accounts/{account_id}/d1/database/{database_id}", {
254256

255257
`GET` D1 database REST endpoint returns if read replication is enabled or disabled.
256258

257-
For REST API, use a [API token](/fundamentals/api/get-started/create-token/) with `D1:Read` [permission](/fundamentals/api/reference/permissions/#account-permissions).
259+
For the REST API, use an [API token](/fundamentals/api/get-started/create-token/) with `D1:Read` [permission](/fundamentals/api/reference/permissions/#account-permissions).
258260

259261
<Tabs>
260262
<TabItem label="cURL">
@@ -282,15 +284,16 @@ console.log(data.read_replication.mode);
282284

283285
- Check the `read_replication` property of the `result` object
284286
- `"mode": "auto"` indicates read replication is enabled
285-
- `"mode": "disable"` indicates read replication is disabled
287+
- `"mode": "disabled"` indicates read replication is disabled
286288

287289
### Start a Session without constraints
288290

289-
To create a Session from any database version, use `withSession()` without any parameters, which will route the first query to any database instance, either the primary database instance or a read replica.
291+
To create a Session from any available database version, use `withSession()` without any parameters, which will route the first query to any database instance, either the primary database instance or a read replica.
290292

291293
```ts
292-
const session = env.DB.withSession() // synchronous
293-
const result = await session // query executes on either primary database or a read replica
294+
const session = env.DB.withSession()
295+
// query executes on either primary database or a read replica
296+
const result = await session
294297
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
295298
.run()
296299
```
@@ -322,11 +325,11 @@ async function getLikes(postId: string, db: D1Database, bookmark: string | null)
322325

323326
### Start a Session with all latest data
324327

325-
To create a Session from the latest database version, use `withSession(first-primary)`, which will route the first query to the primary database instance.
328+
To create a Session from the latest database version, use `withSession("first-primary")`, which will route the first query to the primary database instance.
326329

327330
```ts
328331
// synchronous
329-
const session = env.DB.withSession('first-primary') // synchronous
332+
const session = env.DB.withSession(`first-primary`)
330333
const result = await session // query executes on primary database
331334
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
332335
.run()
@@ -366,7 +369,7 @@ async function getBillStatement(accountId: string, billId: string, bookmark: str
366369

367370
### Start a Session from previous context (bookmark)
368371

369-
To create a new Session from the context of a previous Session, pass a `bookmark` parameter to guarantee that the Session starts with database state as of or later than the provided `bookmark`. `bookmark` could be saved in HTTP header from previous Session.
372+
To create a new Session from the context of a previous Session, pass a `bookmark` parameter to guarantee that the Session starts with a database version that is at least as up-to-date as the provided `bookmark`.
370373

371374
```ts
372375
const bookmark = request.headers.get('x-d1-bookmark') ?? 'first-unconstrained';
@@ -379,7 +382,7 @@ const result = await session
379382
response.headers.set('x-d1-bookmark', session.getBookmark() ?? "")
380383
```
381384

382-
- Starting a Session with a `bookmark` ensures the new Session has all the same context as the previous Session.
385+
- Starting a Session with a `bookmark` ensures the new Session will be at least as up-to-date as the previous Session that generated the given `bookmark`.
383386
- Refer to the [D1 Workers Binding API documentation](/d1/worker-api/d1-database#withsession).
384387

385388
{/* #### Example of using `bookmark`
@@ -477,25 +480,19 @@ export default {
477480

478481
### Check where D1 request was processed
479482

480-
To see how D1 requests are processed by the addition of read replicas, `served_by_region` and `served_by_primary` fields are returned by the `meta` object in a [D1 Result](/d1/worker-api/return-object/#d1result).
483+
To see how D1 requests are processed by the addition of read replicas, `served_by_region` and `served_by_primary` fields are returned in the `meta` object of [D1 Result](/d1/worker-api/return-object/#d1result).
481484

482485
```ts
483-
function buildResponse(session: D1DatabaseSession, res: D1Result, startTimestamp: number) {
484-
return {
485-
d1Latency: Date.now() - startTimestamp,
486-
487-
results: res.results,
488-
servedByRegion: res.meta.served_by_region ?? "",
489-
servedByPrimary: res.meta.served_by_primary ?? "",
490-
491-
// Add the session bookmark inside the response body too.
492-
sessionBookmark: session.getBookmark(),
493-
};
494-
}
486+
const result = await env.DB.withSession()
487+
.prepare(`SELECT * FROM Customers WHERE CompanyName = 'Bs Beverages'`)
488+
.run();
489+
console.log({
490+
servedByRegion: result.meta.served_by_region ?? "",
491+
servedByPrimary: result.meta.served_by_primary ?? "",
492+
});
495493
```
496494

497-
- `served_by_region` and `served_by_primary` fields are present for all D1 remote requests, regardless of whether read replication is enabled. On local development, `npx wrangler dev`, these fields are `null`.
498-
- You can also manually calculate the query latency using `Date.now()` before and after your query.
495+
- `served_by_region` and `served_by_primary` fields are present for all D1 remote requests, regardless of whether read replication is enabled or if the Sessions API is used. On local development, `npx wrangler dev`, these fields are `undefined`.
499496

500497
## Read replica locations
501498

@@ -517,8 +514,8 @@ Read replica locations are subject to change at Cloudflare's discretion.
517514
To see the impact of read replication and check the how D1 requests are processed by additional database instances, you can use:
518515

519516
- The `meta` object within the [`D1Result`](/d1/worker-api/return-object/#d1result) return object, which includes new fields:
520-
- `served_By_Region`
521-
- `served_By_Primary`
517+
- `served_by_region`
518+
- `served_by_primary`
522519
- The [Cloudflare dashboard](https://dash.cloudflare.com/), where you can view your metrics breakdown by region that processed D1 requests.
523520

524521
## Known limitations
@@ -554,7 +551,7 @@ A system with multiple read replicas located around the world improves the perfo
554551

555552
You may wish to refer to the following resources:
556553

557-
- Blog: [Beta announcement & technical deep dive](https://blog.cloudflare.com/d1-read-replication-beta)
554+
- Blog: [Beta announcement & technical deep dive](https://blog.cloudflare.com/d1-read-replication-beta/)
558555
- Blog: [Building D1: a Global Database](https://blog.cloudflare.com/building-d1-a-global-database/)
559556
- [D1 Sessions API documentation](/d1/worker-api/d1-database#withsession)
560557
- [Demo application]

0 commit comments

Comments
 (0)