负载均衡

PolarDB支持基于连接数负载均衡基于活跃请求数负载均衡两种负载均衡策略,来保证多个只读节点间的负载均衡。

负载均衡策略

说明

PolarDB只读模式的集群地址支持基于连接数负载均衡基于活跃请求数负载均衡两种负载均衡策略;可读可写(自动读写分离)模式的集群地址仅支持基于活跃请求数负载均衡的策略。

负载均衡策略名称

差异点

相同点

基于连接数负载均衡

说明

读请求将在集群地址内的多个只读节点中按照连接数自动调度,来保证多个只读节点间的负载均衡。

  • 一个应用程序的一个连接只会和集群地址内的一个只读节点建立连接,应用可建立的总连接数为集群地址内所有只读节点的最大连接数之和。

  • 当从对应的地址删除一个只读节点时,该节点对应的用户连接也会闪断。

  • 不支持一致性级别、事务拆分、连接保持、行存/列存自动引流等高级功能。

  • 由于只进行连接的建立,不需要过度参与负载,性能好。

对于只读模式的集群地址,无论采用哪种负载均衡策略,任何请求都不会被转发到主节点。

基于活跃请求数负载均衡

说明

读请求将在集群地址内的多个只读节点中按照活跃请求数自动调度,来保证多个只读节点间的负载均衡。

  • 一个应用程序的一个连接会和集群地址内所有的节点建立连接,应用可建立的总连接数为集群地址内所有节点中最大连接数的最小值。

  • 支持一致性级别、事务拆分、连接保持、行存/列存自动引流等高级功能。

  • 由于需要进行每个请求的路由解析和判断,性能有所下降。

  • 能够提供更好的负载均衡能力,即使数据库节点的规格不一致,也能根据数据库节点实时的负载进行均衡。

主库是否接受读

主库是否接受读选择后,普通的读请求将不再发往主节点。而事务内,一致性要求的读请求仍会被发往主节点,以保证业务需求。另外,当所有只读节点出现故障后,读请求也会发往主节点。如果业务对一致性的要求较低,可以通过设置一致性级别为最终一致性来减少读请求到主节点,也可以通过事务拆分功能来减少真正事务前的读请求发往主节点。广播的请求(例如SET或PREPARE)仍会被发往主节点。

说明
  • 仅当读写模式可读可写(自动读写分离)时,支持设置主库是否接受读。关于如何修改主库是否接受读设置,具体操作请参见配置数据库代理

  • 如果您的数据库代理版本为1.x.x或为2.5.1及以上,主库是否接受读配置更改后会立即生效。

  • 如果您的数据库代理版本为2.x.x且为2.5.1之前的版本,主库是否接受读配置更改后,如果业务侧使用的是长连接,需要重新建立连接才能生效;如果业务侧使用的是短连接,会立即生效。

事务拆分

当使用PolarDB可读可写模式集群地址时,读写请求会由数据库代理(Proxy)分发到主节点和只读节点。为了保证一个会话连接中事务读写一致性,代理会将这个会话中所有在事务中的请求都发送到主节点。例如,某些数据库客户端驱动(如JDBC)默认将请求封装在事务中,因此应用的请求都会被发送到主节点,导致主节点压力大,而只读节点几乎没有压力,如下图所示:

image

为了解决上述问题,PolarDB在读已提交(Read Committed)的事务隔离级别下提供了事务拆分功能,旨在保证业务中读写一致性的前提下,将事务中读请求发送到只读节点,以减轻主节点的压力。您不需要改动应用的代码或配置就可以将事务中的读压力从主节点转移到只读节点,从而提高主节点的稳定性。开启事务拆分能力的详细操作步骤请参见配置数据库代理

PolarDB MySQL版提供了事务写前读拆分(默认值,即原来的事务拆分功能)和事务全(写前读、写后读)拆分两个级别的事务拆分能力:

  • 事务写前读拆分

    Proxy会将事务中第一个写请求前的读请求发送到只读节点,从而减轻主节点的负载。

    image
  • 全(写前读、写后读)拆分

    写前读拆分对于事务中写之后的读仍然会路由到主节点,这种情况下负载仍然不太均衡,为彻底解决事务带来的负载均衡问题,PolarDB MySQL版推出事务全拆分能力,可以使得事务中的读操作都路由到只读节点且获得正确的结果。进一步减轻主节点的压力。

    image

    事务写后读被路由到只读节点的前提是当前的只读节点已同步事务之前的写操作的数据,如果用户配置了会话一致性,那么在路由写后读时会先判断当前Session的只读节点是否已经同步之前的写,如果已同步就会路由过去,否则会直接路由到主节点。同样地,如果用户配置了全局一致性,那么在路由写后读时会先判断当前所有Session的事务是否都已经同步到只读节点,如果已同步就会路由过去,否则会直接路由到主节点。事务全拆分不支持配置为最终一致性。

    版本和使用限制

    如需使用事务全拆分能力,则PolarDB MySQL版集群需要满足:

    • PolarDB MySQL版5.6版本,且修订版本为5.6.1.0.29及以上。

    • PolarDB MySQL版5.7版本,且修订版本为5.7.1.0.9及以上。

    • PolarDB MySQL版8.0.1版本,且修订版本为8.0.1.1.18及以上。

    • PolarDB MySQL版8.0.2版本,无修订版本限制。

    • 需要让内核参数loose_query_cache_type设置为OFF(PolarDB MySQL版5.6、5.7和8.0.1版本参数默认值为OFF,8.0.2版本默认为ON,该参数设置变更需要重启PolarDB)。

说明
  • 仅对读已提交(Read Committed)事务隔离级别的会话支持事务拆分功能,并且该功能默认开启。

  • 受读写一致性的约束,如果只读节点的一致性不满足要求,则读请求不会路由至只读节点。

  • 若您的数据库代理版本为2.4.14之前的版本,则只支持事务写前读拆分不支持事务全拆分能力。

  • 若您的数据库代理版本为2.4.14及之后的版本,且事务拆分配置为事务全拆分,如果业务侧使用的是长连接,则需要重新建立连接才能生效。如果业务侧使用的是短连接,会立即生效。

  • 关闭事务拆分

    当事务拆分关闭后,事务内的所有请求都路由到主节点。

基于权重的动态负载均衡

当前PolarDB MySQL版代理默认的负载均衡策略是优先选择最小活跃(并发)请求数的节点去路由请求。该策略基本可以使得流量根据后端节点的负载均衡的路由到不同的后端节点上,即使后端节点的规格不一致,也能较好的进行负载均衡。但是线上客户的业务负载多种多样,用户对于流量的分发需求也不尽相同。

为了更好地满足客户的需求,PolarDB MySQL版引入了基于权重的动态负载均衡功能,您可以为每个节点配置不同的权重,在后续的路由过程中,权重和并发请求数会同时作为参考标准去动态的调整最终的路由决策。目前仅支持基于以下2个维度配置权重:

  • 全局DB维度

    该配置会对所有的地址生效;

  • 地址(endpoint)维度

    地址维度的权重仅会对该地址的负载均衡生效,并覆盖DB维度。即用户先配置了一个DB维度的权重,又为某个地址单独配置了权重,则这个地址的负载均衡以配置到该地址维度为准;

注意事项

  • 该功能要求数据库代理的版本为2.8.3或以上。

  • 由于同时考虑当前节点负载和用户自定义权重,所以整体的比例可能和用户自定义比例有一些偏差,随着时间推移,会逐步地向自定义比例靠近。

  • Serverless实例不支持地址(endpoint)维度权重设置。

实现原理

在路由请求过程中,各个节点最终的权重是根据用户配置的权重和节点当前的并发请求数进行动态调整。所采用的公式简化后如下:

动态权重=自定义配置的权重/并发请求数

动态权重越大,节点的优先级越高。动态权重负载策略提供了一个比较灵活的路由方式。在实际使用时,业务流量会根据用户所配置的权重逐步变化(相比完全按照权重轮询会需要更多的时间)。

操作步骤

说明
  • 初始时每个后端节点的权重默认相同,即均为1。

  • 权重的可配置范围为0~100。

  • 当权重为0时,正常情况下请求不会再路由到该节点,只会在其他节点都不可用时才会选择该节点。

  • 如果集群中只存在一个只读列存节点,则其权重可以忽略。如果集群中存在多个只读列存节点,则列存请求会根据列存节点的权重进行负载均衡。

配置全局DB维度权重

  1. 登录PolarDB控制台

  2. 在左上角,选择集群所在地域。

  3. 找到目标集群,单击集群ID。

  4. 基本信息页面的数据库代理企业通用版数据库代理企业独享版区域,单击数据库代理服务配置

  5. 数据库代理服务配置对话框中,根据业务需求为每个节点配置不同的权重。

    image.png

  6. 配置完成后,单击确定

配置地址维度权重

  1. 登录PolarDB控制台

  2. 在左上角,选择集群所在地域。

  3. 找到目标集群,单击集群ID。

  4. 基本信息页面的数据库代理企业通用版数据库代理企业独享版区域,单击集群地址或自定义地址右上角的配置

  5. 编辑地址配置页面的服务节点区域,将自定义节点权重选择开启,并为节点设置权重。

    image.png

  6. 设置完成后,单击确定

测试数据

以下展示了配置节点权重后的实际测试数据。

测试使用的三个节点的权重配置比例为1:2:3(RW节点为1),可以看到压测结果符合预期(使用Sysbench oltp_read_only测试集)。

456789

说明

pi-bp1d1mtcobuzv****pcbp14vvpolardbma23957****两个节点为内部节点,不参与路由,指标无需考虑。

按需建连

背景信息

对于基于活跃请求数负载均衡的Endpoint,默认的建联方式为全建联。即一个客户端会话通过代理建连后,代理会与该地址内的所有数据库节点都建立一个会话(连接),即1:N的连接关系。并且这个会话的普通读请求会按照当前数据库的活跃负载而路由到各个数据库执行,广播请求(SET语句等)会路由到所有的数据库。在数据库数目较多时,整体效率会因为建联和广播明显降低。

实现原理

按需建立连接,即代理根据需要与后端数据库建立连接。在保证一致性和RW负载的情况下,尽量少地与数据库建联,从而节省数据库因为与代理建联和执行广播导致的开销。大部分情况下,一个会话至多与一个RW节点和一个RO节点建联(在不考虑一致性,即最终一致性)。在短连接或者广播语句比较多的场景下,性能提升比较明显。

image

如上图所示,假设PolarDB集群中只存在一个RW节点和三个RO节点,在不考虑一致性的前提下,三种场景下的请求路由和数据读取效率如下:

  • 非按需建连

    用户的一个会话通过数据库代理会与四个数据库都建立连接,并且广播语句会路由到四个数据库节点。

  • 按需建连,只读会话

    用户的一个会话通过数据库代理会只与一个RO节点建立连接,只读请求(包括广播)只会路由到这一个RO节点上,数据读取效率明显提升。

  • 按需建连,读写会话

    用户的一个会话通过数据库代理只会与一个RO节点,以及一个RW节点建立连接,广播请求只会路由到两个数据库节点,数据读取效率也会明显提升。

适用场景

  • RO节点较多;

  • 短连接;

  • 广播语句较多(例如PHP短连接场景下,会话的第一个语句一般似于set names utf8mb4语句);

  • 使用短prepare进行查询比较多的场景。

使用限制

  • 数据库代理版本需为2.8.34及以上。查看集群的数据库代理版本的具体操作步骤请参见查询版本号

  • 使用SHOW PROCESSLISTS查看连接的数据库数量时,可能不会显示所有的数据库连接数。

  • 使用KILL命令终止指定连接时,可能不会终止所有数据库中的指定连接。

性能测试

测试环境

  • 数据库节点:1个读写(RW)节点、7个只读(RO)节点

  • 测试使用的SQL:SET NAMES utf8mb4SELECT 1

  • 测试工具:Sysbench,且每次的并发数量一样

  • 测试场景:不打开连接池、打开会话级连接池和打开事务级连接池三种场景,每种场景测试分为两个部分,前半部分为不打开按需建连,后半部分为打开按需建连。

测试结果

  • 不打开连接池场景下的性能测试结果:

    • 数据库节点的CPU消耗如下图所示,打开按需建连后,数据库的CPU消耗下降60%以上:

      不打开连接池.png

    • 数据库节点的总连接数变化如下图所示,打开按需建连后,数据库的总连接数下降80%以上:

      总连接数.png

    • 总体的QPS变化如下图所示,打开按需建连后,总体的QPS提升了35%:

      QPS.png

  • 打开会话级连接池场景下的性能测试结果:

    • 数据库节点的CPU消耗如下图所示,打开按需建连后,数据库的CPU消耗下降50%~60%以上:

      会话级_CPU消耗.png

    • 数据库节点的总连接数变化如下图所示,打开按需建连后,数据库的总连接数下降60%:

      会话级_总连接数.png

    • 总体的QPS变化如下图所示,打开按需建连后,QPS提升了30%:

      会话级_QPS.png

  • 打开事务级连接池场景下的性能测试结果:

    • 数据库节点的CPU消耗如下图所示,打开按需建连后,数据库的CPU下降了60%:

      事务级_CPU.png

    • 数据库节点的总连接数变化如下图所示,打开按需建连后,总连接数下降了50%:

      事务级_CPU.png

    • 总体的QPS变化如下图所示,打开按需建连后,QPS提升了260%:

      事务级_QPS.png