二、 读写分离
如果数据库没有设置读写分离,在少写多读的应用场景下,大量读操作会对主实例造成巨大的读取压力,进而影响业务。因此,启用读写分离功能,可以使查询请求自动转发到只读实例上,写请求转发到主实例上,各司其职,实现了读写分离、自动分流,减轻主实例的压力,能够为数据库带来非常大的优势。
• 读写分离提供了统一的读写分离地址,便于维护。如果不开通读写分离,配置读与写操作时需要在应用程序里分别配置主实例与每个只读实例的连接地址,维护地址的工作非常繁杂,容易出错。RDS读写分离功能能够提供代理地址,连接代理地址以后,可对主实例与只读实例进行读写操作。请求自动转发,写请求转发到主实例,读请求转发到只读实例,降低了维护成本。
• 原生链路支持可以提高数据库性能,减少维护成本。
• 可以设置只读实例的权重与阈值,可在多场景下使用。
• 可以进行实例健康检查,提升数据库性能的可用性。
在设置读写分离为主实例创建只读实例时,建议客户至少创建两个只读实例,可以避免只读实例单点故障。
高可用实例有主实例与备实例,在同一可用区、同一region下。当主实例意外宕机或卡住时会进行 HA 切换,备实例会立即切换为主实例继续为客户提供业务。
只读实例可以与主实例在同一地域,可以在不同可用区。只读实例主要承担只读请求,只读实例也有高可用架构,也可以有只读实例的备实例。
灾备实例一般用于要求高可靠或高可用性的客户场景。比如客户希望在极端情况下,主region所有数据库都无法提供服务时,备region可以继续提供服务,灾备实例往往建在备region。
RDS里的数据库代理分为独享代理与共享代理,它是位于数据库服务端与应用服务端之间的网络代理服务,用于代理应用服务端访问数据时的所有请求,具有高可用、高性能、可运维、简单易用等特点。独享代理还提供了自动读写分离、事务拆分、连接池等高级功能。
数据库代理适用于以下几类场景:
• 事务内有大量请求导致主实例负载过高。此时可能需要将只读请求进行拆分。
• 接数过多导致主实例负载过高。
• 短连接为主的业务。
• 纯只读或有隔离需求的业务。
数据库代理支持事务拆分,默认情况下,RDS数据库独享代理会将事务内所有请求发送到主实例,保证事务的正确性,但是某些框架会导致主实例负载过大。此时可以使用事务拆分功能,将事务里的只读请求发送到只读实例上,提升性能。需要注意,显示事务当前不支持拆分,对于全局一致性有要求的事务也不支持拆分。
客户在业务端可以通过设置连接池进行读写分离。当前RDS支持事务级连接池(默认)和会话级连接池。
事务级连接池主要用于减少直接连接到数据库业务的连接,减少短连接的频繁建立连接带来的负担。开启事务级连接池以后,客户端与独享代理之间可能会存在上千个连接,但是代理与数据库后端可能仅存在几十、几百个连接。
独享代理本身并没有最大连接数的限制,主要由后端数据库节点的规格决定。没有开启事务级连接池时,每条由客户端发起的连接都会在后端主节点与所有只读节点创建对应连接。
开启了事务级连接后,客户端发送请求时,会先与独享代理建立连接判断是否存在可用连接,如果不存在,代理会与数据库创建新连接;如果存在,则直接从连接池里取出并使用,能够减少频繁建立连接的过程。
会话级接池主要用于减少短连接业务频繁建立新连接带来的实例负载。某个客户端断开时,系统会判断当前连接是否为闲置连接。如果是,系统会将其保留一段时间。重新建立连接时,如果连接池中有可用连接,则直接使用;如果没有,则通过正常流程再次建立连接。
会话级连接池并没有减少数据库的并发连接数,而是通过降低应用与数据库建立连接的速率来减少MySQL开销,从而更好地处理业务请求。但是闲置连接会短暂地占用客户端连接数,而且会话级连接池无法解决由于大量慢SQL 导致的堆积问题。
如何选择事务级连接池与会话级连接池?
如果业务连接数较多(比如有上万)或使用Serverless服务导致连接数随着业务端服务器的扩容而线性增加,则建议使用事务级连接池。
如果短连接占比较大,则建议使用会话级连接池。
如果业务使用多维长连接且连接数比较少,或业务本身已经具备较好的连接池,则不建议再使用RDS连接池。
阿里云RDS支持使用SQL hint语法,执行SQL时可以在前面加上hint操作,将SQL语句发往不同的数据库节点。具体例子如上图。