PolarDB MySQL集群自带读写分离功能。应用程序只需连接一个集群地址,写请求会自动发往主节点,读请求会自动根据各节点的负载(当前未完成的请求数)发往主节点或只读节点。

功能优势

  • 读一致性

    在PolarDB的链路中间层进行读写分离时,中间层会追踪(track)各个节点已经应用(apply)的重做日志(redolog)位点,即日志序号(LSN);同时,每次数据更新时将此次更新的位点记录为Session LSN。当PolarDB收到新的请求时,将Session LSN与各个节点的LSN进行比较,仅将请求发往LSN早于Session LSN的节点,从而保证会话的一致性。表面上看该方案可能导致主节点压力大,但是因为PolarDB是物理复制,速度极快,在上述场景中,当更新完成后,返回客户端结果时复制就同步在进行,而当下一个读请求到来时,主节点和只读节点之间的数据复制极有可能已经完成,然后大多数应用场景都是读多写少,所以经验证在该机制下既保证了会话一致性,也保证了读写分离负载均衡的效果。

    示意图
  • 原生支持读写分离,提升性能

    如果您在云上通过自己搭建代理层实现读写分离,在数据到达数据库之前需要经历多个组件的语句解析和转发,对响应延迟有较大的影响。而PolarDB读写分离在已有的高安全链路中直接内置,没有任何额外的组件来消耗时间,能够有效降低延迟,提升处理速度。

  • 维护方便

    在传统模式下,您需要在应用程序中配置主节点和每个只读节点的连接地址,并且对业务逻辑进行拆分,才能实现将写请求发往主节点而将读请求发往各个节点。

    PolarDB提供集群地址,应用程序连接该地址后即可对主节点和只读节点进行读写操作,读写请求会被自动转发,转发逻辑完全对使用者透明,可降低维护成本。

    同时,您只需添加只读节点的个数,即可不断扩展系统的处理能力,应用程序无需做任何修改。

  • 节点健康检查,提升数据库系统的可用性

    读写分离模块自动对集群内的所有节点进行健康检查,当发现某个节点宕机或者延迟超过阈值后,将不再分配读请求给该节点,读写请求在剩余的健康节点间进行分配。以此确保单个只读节点发生故障时,不会影响应用的正常访问。当节点被修复后,PolarDB会自动将该节点纳回请求分配体系内。

  • 免费使用,降低资源及维护成本

    免费提供读写分离功能,无需支付任何额外费用。

转发逻辑

  • 可读可写模式转发逻辑:
    • 只发往主节点
      • 所有DML操作(INSERT、UPDATE、DELETE、SELECT FOR UPDATE)。
      • 所有DDL操作(建表/库、删表/库、变更表结构、权限等)。
      • 所有事务中的请求。
      • 用户自定义函数。
      • 存储过程。
      • EXECUTE语句。
      • Multi Statements
      • 使用到临时表的请求。
      • SELECT last_insert_id()。
      • 所有对用户变量的查询和更改。
      • SHOW PROCESSLIST。
      • KILL(SQL语句中的KILL,非命令KILL)。
    • 发往只读节点或主节点
      • 非事务中的读请求。
      • COM_STMT_EXECUTE命令。
    • 总是发往所有节点
      • 所有系统变量的更改。
      • USE命令。
      • COM_STMT_PREPARE命令。
      • COM_CHANGE_USER/COM_QUIT/COM_SET_OPTION等命令。
  • 只读模式转发逻辑:
    • 不允许执行DDL、DML操作。
    • 所有请求按照负载均衡的方式转发到各只读节点。
    • 所有请求不会转发到可读可写节点。

使用限制

  • 若执行了Multi Statements或存储过程,当前连接的后续请求会全部路由到主节点,需断开当前连接并重新连接才能恢复读写分离。
  • 集群地址在只读模式下,不支持设置环境变量, 例如set @endtime=now(); select * from tab where dt < @endtime, 可能导致查询无法获得正确的环境变量。
  • 使用视图时无法保证会话一致性,例如CREATE VIEW tab2 AS SELECT * FROM tab1; INSERT INTO tab1(key, value) (1, 1); SELECT * FROM tab2 where key=1;可能会因为延迟而查不到结果。

创建或修改集群地址

创建或修改集群地址具体操作方式请参见设置/释放自定义集群地址

高级选项-事务拆分

在默认的Read Commited隔离级别下,当PolarDB接收到开启事务的语句(例如begin或set autocommit=0)时,不会立即开启事务,而是在发生写操作时才正式开启事务。

默认情况下,PolarDB会将事务内的所有请求都发送到主节点以保障事务的正确性,但是某些框架会将所有请求封装到事务中,导致主节点负载过大。此时您可以开启事务拆分功能,开启后PolarDB会识别当前事务的状态,将正式开启事务前的读请求通过负载均衡模块分流至只读节点。

事务拆分
说明 某些业务对全局一致有要求,开启事务拆分后将不满足全局一致,因此在事务拆分前请充分评估事务拆分功能是否适用于您的业务。
  1. 单击修改配置
  2. 在弹出的对话框,选择事务拆分开启开启事务拆分
    说明 开启事务拆分后将对新的连接生效,现有的连接需重新连接才生效。
  3. 单击确定

高级选项-一致性级别

详情请参见PolarDB一致性级别

FAQ

  1. 为什么刚插入的语句,立即查的时候查不到?

    答:读写分离的架构下,主节点和只读节点之间复制会有延迟,但PolarDB支持会话一致性,即同一个会话内保证能读到之前的更新。

  2. 为什么只读节点没有压力?

    答:默认情况下事务中的请求都会路由到主节点,若是用sysbench做压测,0.5版本的sysbench可以加上--oltp-skip-trx=on,1.0版本的sysbench可以加上--skip-trx=on去掉事务,若业务上因为事务较多导致只读库负载过低,可以提交工单开启读写分离下的分布式事务。

  3. 为什么某个节点的请求数比别的节点多?

    答:当前是根据负载来分发请求的,负载小的节点接收的请求数会更多。

  4. 是否支持0毫秒延迟的读取?

    答:PolarDB集群的主节点和只读节点在正常负载情况下,具有毫秒级的延迟,读写分离连接地址暂时不支持在数据写入后0毫秒的读取。如果要求0毫秒延迟的读取,可使用主地址(动态指向PolarDB主节点)将读写请求发给主节点。

  5. 新增的只读节点会自动加入到读写分离吗?

    新增只读节点之后新建的读写分离连接会转发请求到该只读节点。新增只读节点之前建立的读写分离连接不会转发请求到新增的只读节点,需要断开该连接并重新建立连接,例如,重启应用。

相关API

API 描述
CreateDBEndpointAddress 创建PolarDB集群的公网地址。
CreateDBClusterEndpoint 创建PolarDB自定义集群地址。
DescribeDBClusterEndpoints 查询PolarDB集群的地址信息。
ModifyDBClusterEndpoint 修改PolarDB集群地址属性。
ModifyDBEndpointAddress 修改PolarDB集群默认访问地址前缀。
DeleteDBEndpointAddress 释放PolarDB集群地址(除了自定义集群地址的私网地址)。
DeleteDBClusterEndpoint 释放PolarDB自定义集群地址。