Prefer the nearest data center
Below are code examples for setting the "prefer nearest data center" balancing algorithm option in different YDB SDKs.
The YDB C++ SDK uses the prefer_local_dc (prefer nearest data center) algorithm by default.
#include <ydb-cpp-sdk/client/driver/driver.h>
int main() {
auto connectionString = std::string(std::getenv("YDB_CONNECTION_STRING"));
auto driverConfig = NYdb::TDriverConfig(connectionString)
.SetBalancingPolicy(NYdb::TBalancingPolicy::UsePreferableLocation());
NYdb::TDriver driver(driverConfig);
// ...
driver.Stop(true);
return 0;
}
static config
ydb:
databases:
db:
endpoint: grpc://localhost:2136
database: /local
prefer_local_dc: true
Initialization code ydb::YdbComponent, obtaining ydb::TableClient and starting components::MinimalServerComponentList — as in the example from init.md.
package main
import (
"context"
"os"
"github.com/ydb-platform/ydb-go-sdk/v3"
"github.com/ydb-platform/ydb-go-sdk/v3/balancers"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
db, err := ydb.Open(ctx,
os.Getenv("YDB_CONNECTION_STRING"),
ydb.WithBalancer(
balancers.PreferLocalDC(
balancers.RandomChoice(),
),
),
)
if err != nil {
panic(err)
}
defer db.Close(ctx)
// ...
}
Client-side balancing in the database/sql driver for YDB occurs only when establishing a new connection (in terms of database/sql), which represents a YDB session on a specific node. After the session is created, all queries on that session are sent to the node where the session was created. Balancing queries on the same YDB session across different nodes YDB does not happen.
Code example for setting the "prefer nearest data center" balancing algorithm:
package main
import (
"context"
"database/sql"
"os"
"github.com/ydb-platform/ydb-go-sdk/v3"
"github.com/ydb-platform/ydb-go-sdk/v3/balancers"
)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
nativeDriver, err := ydb.Open(ctx,
os.Getenv("YDB_CONNECTION_STRING"),
ydb.WithBalancer(
balancers.PreferLocalDC(
balancers.RandomChoice(),
),
),
)
if err != nil {
panic(err)
}
defer nativeDriver.Close(ctx)
connector, err := ydb.Connector(nativeDriver)
if err != nil {
panic(err)
}
db := sql.OpenDB(connector)
defer db.Close()
// ...
}
import os
import ydb
driver_config = ydb.DriverConfig(
endpoint=os.environ["YDB_ENDPOINT"],
database=os.environ["YDB_DATABASE"],
credentials=ydb.credentials_from_env_variables(),
use_all_nodes=False, # предпочитать ближайший дата-центр
)
with ydb.Driver(driver_config) as driver:
driver.wait(timeout=5)
# ...
import os
import ydb
import asyncio
async def ydb_init():
driver_config = ydb.DriverConfig(
endpoint=os.environ["YDB_ENDPOINT"],
database=os.environ["YDB_DATABASE"],
credentials=ydb.credentials_from_env_variables(),
use_all_nodes=False, # предпочитать ближайший дата-центр
)
async with ydb.aio.Driver(driver_config) as driver:
await driver.wait()
# ...
asyncio.run(ydb_init())
import os
import sqlalchemy as sa
engine = sa.create_engine(
os.environ["YDB_SQLALCHEMY_URL"],
connect_args={
"driver_config_kwargs": {
"use_all_nodes": False, # предпочитать ближайший дата-центр
}
},
)
This functionality is not currently supported.
This functionality is not currently supported.
import tech.ydb.common.transaction.TxMode;
import tech.ydb.core.grpc.BalancingSettings;
import tech.ydb.core.grpc.GrpcTransport;
import tech.ydb.query.QueryClient;
import tech.ydb.query.result.ResultSetReader;
import tech.ydb.query.tools.QueryReader;
import tech.ydb.query.tools.SessionRetryContext;
import tech.ydb.table.query.Params;
public class PreferLocalExample {
public static void main(String[] args) {
String connectionString = System.getenv().getOrDefault(
"YDB_CONNECTION_STRING", "grpc://localhost:2136/local");
try (GrpcTransport transport = GrpcTransport.forConnectionString(connectionString)
// Auto-detection of the nearest data center based on latency to nodes
.withBalancingSettings(BalancingSettings.detectLocalDs())
.build();
QueryClient queryClient = QueryClient.newClient(transport).build()) {
SessionRetryContext retryCtx = SessionRetryContext.create(queryClient).build();
QueryReader reader = retryCtx.supplyResult(session -> QueryReader.readFrom(
session.createQuery("SELECT 1 AS value", TxMode.NONE, Params.empty())
)).join().getValue();
ResultSetReader rs = reader.getResultSet(0);
if (rs.next()) {
System.out.println("SELECT 1 = " + rs.getColumn("value").getInt32());
}
}
}
}
Specify the local data center via localDatacenter in the JDBC URL — see the JDBC driver properties.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcPreferLocalExample {
public static void main(String[] args) throws SQLException {
// JDBC driver does not support automatic detection of the nearest DC.
// Explicitly specify the availability zone via the localDatacenter parameter —
// see the recipe [Load balancing — Prefer availability zone](./balancing-prefer-location.md).
try (Connection connection = DriverManager.getConnection(
"jdbc:ydb:grpc://localhost:2136/local?localDatacenter=VLA");
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery("SELECT 1 AS value")) {
if (rs.next()) {
System.out.println("SELECT 1 = " + rs.getInt("value"));
}
}
}
}
In Spring Boot, ORM, and other third‑party frameworks around JDBC, specify the same JDBC connection string and balancing parameters as when using the driver directly (for example, spring.datasource.url or the DataSource properties).
This functionality is not currently supported.
Track progress or vote for support in the Rust SDK: ydb-rs-sdk#239
This functionality is not currently supported.