You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将数据库读请求智能路由至Azure只读副本实例

基于Azure SQL只读副本的读请求分流方案

一、创建只读数据库上下文(以EF Core为例)

实现一个只读专用的DbContext,既防止误写入,又绑定只读副本的连接配置:

public class ReadOnlyAppDbContext : AppDbContext
{
    public ReadOnlyAppDbContext(DbContextOptions<ReadOnlyAppDbContext> options)
        : base(options)
    {
        // 关闭实体跟踪,提升读性能同时避免误修改
        ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
        ChangeTracker.AutoDetectChangesEnabled = false;
    }

    // 直接禁用写操作,彻底杜绝意外写入只读副本
    public override int SaveChanges(bool acceptAllChangesOnSuccess)
        => throw new InvalidOperationException("只读上下文不支持写操作");

    public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
        => throw new InvalidOperationException("只读上下文不支持写操作");
}

在配置文件中添加只读副本的连接字符串,然后注册上下文:

// 主库上下文注册
builder.Services.AddDbContext<AppDbContext>(opt => 
    opt.UseSqlServer(builder.Configuration.GetConnectionString("PrimaryDb")));

// 只读副本上下文注册
builder.Services.AddDbContext<ReadOnlyAppDbContext>(opt => 
    opt.UseSqlServer(builder.Configuration.GetConnectionString("ReadOnlyReplicaDb")));

二、智能路由读请求到就近实例

方案1:Azure内置只读路由(最简实现)

Azure SQL原生支持只读路由,只需在连接字符串中添加 ApplicationIntent=ReadOnly,Azure会自动将读请求路由到就近的健康只读副本,无需应用层额外逻辑:

# 只读副本连接字符串示例
ReadOnlyReplicaDb="Server=tcp:your-replica-server.database.windows.net,1433;Initial Catalog=your-db;User ID=xxx;Password=xxx;Encrypt=True;ApplicationIntent=ReadOnly"

该方案自带故障转移能力,当当前只读副本不可用时,Azure会自动切换到其他可用副本。

方案2:应用层基于地理位置路由(精准控制)

如果需要根据用户所在区域做更精细的路由,可以在应用层实现区域判断逻辑:

public class DbContextRouter
{
    private readonly AppDbContext _primaryDb;
    private readonly ReadOnlyAppDbContext _euReplica;
    private readonly ReadOnlyAppDbContext _asiaReplica;

    public DbContextRouter(AppDbContext primaryDb, ReadOnlyAppDbContext euReplica, ReadOnlyAppDbContext asiaReplica)
    {
        _primaryDb = primaryDb;
        _euReplica = euReplica;
        _asiaReplica = asiaReplica;
    }

    public DbContext GetContext(bool isReadOp, string clientRegion)
    {
        // 写操作强制走主库
        if (!isReadOp) return _primaryDb;

        // 根据用户区域选择就近只读副本
        return clientRegion switch
        {
            "Asia" => _asiaReplica,
            "Europe" => _euReplica,
            _ => _euReplica // 默认 fallback 到主区域副本
        };
    }
}

业务层调用时直接通过路由获取对应上下文:

public async Task<List<Product>> GetProducts(string userRegion)
{
    var db = _router.GetContext(isReadOp: true, userRegion);
    return await db.Products.ToListAsync();
}

三、成本与扩缩容优化

  • 解耦主从扩缩容:只读实例的规格调整无需跟随主库,根据只读请求的实际负载独立调整,比如低峰期降配、高峰期临时升配。
  • 改用弹性池:将主库和只读副本加入弹性池,共享计算资源,避免单个实例的资源浪费,弹性池还支持自动扩缩容,进一步降低成本。
  • 监控驱动优化:使用Azure Monitor跟踪只读实例的CPU、IO、内存使用率,根据监控数据调整实例规格,避免过度配置。

内容的提问来源于stack exchange,提问作者Zapnologica

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 10:52:17