读副本

当你的项目涉及一组读副本实例,并且你需要一种便捷的方法来管理来自读副本的 SELECT 查询,同时在主实例上执行创建、删除和更新操作时,你可以在 Drizzle 中使用 withReplicas() 函数

import { drizzle } from "drizzle-orm/node-mssql";
import { ConnectionPool } from "mssql";
import { bit, int, mssqlTable, text, withReplicas } from 'drizzle-orm/mssql-core';

const usersTable = mssqlTable('users', {
	id: int('id').primaryKey().identity(),
	name: text('name').notNull(),
	verified: bit('verified').notNull().default(false),
});

const createClient = async (database: string) => {
  const pool = new ConnectionPool({
    server: "host",
    user: "user",
    password: "password",
    database,
    options: { encrypt: true },
  });

  await pool.connect();
  return pool;
};

const primaryDb = drizzle({ client: await createClient("primary_db") });
const read1 = drizzle({ client: await createClient("read_1") });
const read2 = drizzle({ client: await createClient("read_2") });

const db = withReplicas(primaryDb, [read1, read2]);

现在你可以像之前一样使用 db 实例。Drizzle 将自动处理读副本和主实例之间的选择

// 从 read1 连接或 read2 连接中读取
await db.select().from(usersTable)

// 删除操作使用主数据库
await db.delete(usersTable).where(eq(usersTable.id, 1))

你可以使用 $primary 键来强制即使是读操作也使用主实例

// 从主库读取
await db.$primary.select().from(usersTable);

使用 Drizzle,你还可以为选择读副本指定自定义逻辑。 你可以进行加权决策,或者使用任何其他自定义选择方法来随机选择读副本。 下面是一个用于选择读副本的自定义逻辑实现示例, 其中第一个副本有 70% 的概率被选中,第二个副本有 30% 的概率被选中。

请记住,你可以为读副本实现任何类型的随机选择方法

const db = withReplicas(primaryDb, [read1, read2], (replicas) => {
    const weight = [0.7, 0.3];
    let cumulativeProbability = 0;
    const rand = Math.random();

    for (const [i, replica] of replicas.entries()) {
      cumulativeProbability += weight[i]!;
      if (rand < cumulativeProbability) return replica;
    }
    return replicas[0]!
});

await db.select().from(usersTable)