谈谈PolarDB-X在读写分离场景的实践
简介: 针对写少读多的业务可以考虑通过添加数据库节点来使其达到提升性能的目的,但添加节点,往往涉及到数据的搬迁,扩容周期比较长,很难应对徒增的业务流量,这个时候可以考虑采用读写分离的方式,将读写流量做分流,减轻主实例的压力,同时利用只读库横向的扩展能力,快速提升读性能。
在数据库使用过程中经常会遇到一些场景:
- 业务写流量一直相对比较稳定,但随着时间,数据不断增加,数据库的压力也会越来越大,写操作会影响到读请求的性能,做任何优化可能都达不到最终的效果;
- 在应用的用户访问量比较低的时候,一个数据库的读写能力是完全能够胜任的。但是在用户访问量增大的时候,数据库很快会成为瓶颈;
针对这种写少读多的业务可以考虑通过添加数据库节点来使其达到提升性能的目的,但添加节点,往往涉及到数据的搬迁,扩容周期比较长,很难应对徒增的业务流量。这个时候可以考虑采用读写分离的方式,将读写流量做分流,减轻主实例的压力,同时利用只读库横向的扩展能力,快速提升读性能。

其基本原理是让主数据库处理事务性查询,而从数据库处理select查询。当业务量非常大时,一台服务器的性能无法满足需求,就可以读写分离方式分摊负载,避免因负载太高而造成无法及时响应请求。目前业界实现读写分离的方案主要有两种:
基于程序代码内部实现
在代码中根据select,insert进行路由分类,这类方法也是目前生产环境应用最广泛的,优点是性能好,因为在程序代码中已经将读写的数据源拆分至两个,所以不需要额外的MySQL proxy解析SQL报文,在进行路由至不同数据库节点。缺点是通常该架构较复杂,运维成本相对较高。
基于中间Proxy(odp/mycat等)实现
Proxy一般位于客户端和服务器之间,代理服务器接到客户端请求后通过解析SQL文本再将SQL路由至可用的数据库节点中。优点是程序不需要改造可以实现无缝迁移,可移植性较好。缺点是性能相对前者略微逊色一些,并且并不是所有的读操作都能够被路由至从节点中。
上述方案都不能算是透明的,要不需要对业务代码进行改造,要不需要业务系统依然第三方组件;除此之外,业界主流的读写方案都无法做到一致性读,应用在使用弱一致性读时,要充分考虑主备副本的数据同步延时,并根据具体业务场景考虑延时的业务影响(脏读)是否能够接受。读写分离业务都还需要做额外的改造,以应对只读库异常或者延迟过大的时候下,对业务做降级处理。
为此,PolarDB-X内核侧提出一种提供了透明的强一致的读写分离能力,支持多种读写分离策略满足各类业务需求。
PolarDB-X Native 读写分离
PolarDB-X配置了多种读写策略,提供了透明的强一致的读写分离能力。简单的说其特点有:
- 无论什么状况都不用担心误写了“备副本或只读副本”,因为它不支持写,写操作会被路由到主副本;
- 无论什么时候不用担心“备副本或只读副本”故障,因为它会自动路由给其他正常的副本或者切回主副本;
- 无论什么场景不用担心 “备副本或只读副本”读不到最新的数据,因为它提供的是强一致的读写能力;
- 大查询不用担心打爆“主副本”,因为它支持将大查询路由给”备副本或只读副本“,避免对主副本造成压力。
其整体的方案设计如下:

PolarDB-X存储节点基于X-Paxos复制协议,整合了binary log,实现了统一的consensus log。consensus log不仅扮演了binary log的角色,同时还维护了LogIndex(全局一致性日志位点)。LogIndex中记录了主库了最新修改consensus log位点信息,当只读库做一致性复制的时候,也会不断更新自身的LogIndex信息。通过LogIndex我们可以确保在只读库上读到最新的数据,结合TSO可以确保读到已提交的一致性数据。路由到只读节点的强一致性读查询过程如下:
- 客户端把请求发送到CN;
- CN识别到请求会发送给只读实例,首先会从主实例DN节点获取当前最大LogIndex;
- CN把LogIndex +TSO 请求一起发送给只读节点;
- 只读节点根据接收到的LogIndex判断是否等到只读节点事务状态回放到相应位点;根据TSO判断数据可见性,给CN返回结果。
同时为了降低每次一次只读查询都会分别与主库交互获取LogIndex,我们为此做了异步Grouping Fetch Logindex优化,在高并发下尽可能将多次Fetch Logindex整合成一次请求,大大降低对主库的压力。
读写分离的操作管理
业务上不需要做任何改造,在需要的时候购买只读实例,默认情况下主实例就具备了读写分离的能力。如果要开启,需要在阿里控制台点击主实例上的集群地址-》配置管理。

会进入下只读分离的配置管理页面

|
操作 |
解释 |
|
资源配置 |
选择购买的只读实例加入到读写分离集群,只有在读写分离集群的实例才可以分担主实例的流量 |
|
智能读写分离 |
基于统计信息做代价估算,将偏AP的复杂查询路由给只读实例做MPP加速。非混合负载场景,可以选择关闭 |
|
只读流量占比 |
将只读流量设置按一定的比例路由给只读实例 |
|
数据一致性 |
强一致性: 路由到只读实例的请求可以读到已提交最新鲜的数据,但如果只读实例延迟大的话,路由到只读实例 弱一致性: 路由到只读实例的请求只是读到实例上可见的最新数据。 |
|
只读实例延迟阀值 |
只读实例延迟超过阈值,那么流量会打到其他延迟正常的只读实例上或者切回主实例。 |
|
只读可用性 |
当只读实例延迟超过阈值或者只读实例 HA时,则认为当前只读实例处于不可用的状态,流量自动切回主实例或者其他正常的只读实例上去。 |
用户真正在使用的时候,业务上完全不需要改造任何代码,一般只需要调整只读流量占比,调整为0意味着流量全部路由给主库;调整成>0,只读流量将按照设置的比例自动分流给只读实例。在这个基础上结合只读实例延迟阀值和只读可用性,可以做到在只读实例异常状态下,流量自动切回主实例或者其他正常的只读实例上去。除了数据库级别的配置,PolarDB-X也支持session级别和query级别的读写配置,可灵活控制某个session下只读查询或者某个具体query的路由分发。
读写分离的可用性测试
为了衡量PolarDB-X 读写分离能力的可用性,我们利用sysbench 从正确性 性能角度设计了三种实验场景来验证。
测试环境
- 测试所用实例规格
主实例规格2*16C128G (CN)+2*4C32G(DN), 2个只读实例规格 2*4C32G(CN) + 2*4C 32G(DN)
- 测试所用压力机规格
ecs.g7ne.8xlarge(24 vCPU,48 GB内存)
测试参数配置
- 修改参数ENABLE_COROUTINE的值为true,XPROTO_MAX_DN_CONCURRENT的值为4000,详细操作步骤请参见参数设置。
- 通过命令行连接到PolarDB-X实例,在同一会话内执行如下SQL语句,关闭日志记录与CPU采样统计:
set ENABLE_SET_GLOBAL = true;
set global RECORD_SQL = false;
set global MPP_METRIC_LEVEL = 0;
set global ENABLE_CPU_PROFILE = false;
测试数据准备
nohup sysbench --config-file='sysb.conf' --create-table-options='partition by key(id)' --tables='16' --threads='16' --table-size='10000000' oltp_point_select prepare &
实验一:一致性读的正确性
从附件中下载这次测试的oltp_insert_read_verify.lua脚本,该脚本逻辑比较简单,就是在主实例插入一条数据,测试在不同并发下在一致性读开启和关闭条件下,是否可以正确读到。一次实验的执行流程如下:
#准备表
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='8' --threads={并发度} --time=60 oltp_insert_read_verify prepare
#运行
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='8' --threads={并发度} --time=60 oltp_insert_read_verify run
#清理
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='8' --threads={并发度} --time=60 oltp_insert_read_verify cleanup
测试结果
|
并发 |
不一致性次数(弱一致性读) |
不一致性次数(强一致性读) |
|
4 |
2 |
0 |
|
8 |
5 |
0 |
|
16 |
16 |
0 |
|
32 |
33 |
0 |
|
64 |
57 |
0 |
从测试结果看,强一致性读下,可以保证路由到只读实例的流量读到最新的数据;而非强一致性读下,无法保证。
实验二:高并发下吞吐表现
我们分别利用oltp_point_select和oltp_read_only两个脚本,测试了下在当前规格下高并发下的性能数据。
- 点查场景
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='16' --table-size='10000000' --threads=512 oltp_point_select run
测试了在不同只读实例个数,不同配置下的性能数据,其QPS表现如下
|
只读实例查询占比 |
主实例+一个只读实例(强一致性) |
主实例+一个只读实例(弱一致性) |
主实例+两个只读实例(强一致性) |
主实例+两个只读实例(弱一致性) |
|
0% |
88201.17 |
88201.17 |
88201.17 |
88201.17 |
|
50% |
124269.63 |
171935.56 |
171783.84 |
208648.34 |
|
100% |
62891.86 |
89213.13 |
117133.83 |
169352.07 |
- oltp_read场景
sysbench --config-file='sysb.conf' --db-ps-mode='disable' --skip-trx='on' --mysql-ignore-errors='all' --tables='16' --table-size='10000000' --range-size=5 --threads=512 oltp_read_only run
测试了在不同只读实例个数,不同配置下的性能数据,其QPS表现如下
|
只读实例查询占比 |
主实例+一个只读实例(强一致) |
主实例+一个只读实例(弱一致) |
主实例+两个只读实例(强一致) |
主实例+两个只读实例(弱一致) |
|
0% |
29145.43 |
29145.43 |
29145.43 |
29145.43 |
|
50% |
44084.40 |
55399.80 |
61698.85 |
73161.11 |
|
100% |
23115.23 |
29235.73 |
42160.54 |
56393.54 |
从测试结果看:
1. 在强一致性读下,在TP读场景下流量从主实例切换到只读实例上吞吐的性能衰减20~30%,但是通过添加只读实例个数,性能可以做到一定的线性增加;
2.在弱一致性读下,在TP读场景下流量从主实例切换到只读实例上吞吐的性能未衰减,且通过添加只读实例的个数,性能可以做到线性增加;
实验三:低并发下RT表现
同样的我们分别利用oltp_point_select和oltp_read_only两个脚本,测试了下在(一个主实例+只读实例)下在强一致性读条件下,不同并发的RT表现。
- 点查场景(ms)
|
并发 |
只读查询比例0% |
只读查询比例100% |
只读查询比例50% |
|
4 |
0.61 |
0.89 |
0.87 |
|
8 |
0.62 |
0.91 |
0.89 |
|
16 |
0.64 |
0.94 |
0.90 |
|
32 |
0.71 |
1.04 |
0.99 |
|
64 |
1.18 |
1.27 |
1.27 |
- oltp_read场景(ms)
|
并发 |
只读查询比例0% |
只读查询比例100% |
只读查询比例50% |
|
4 |
11.65 |
21.89 |
17.63 |
|
8 |
12.21 |
22.69 |
17.29 |
|
16 |
14.21 |
23.95 |
18.23 |
|
32 |
20 |
27.17 |
21.50 |
|
64 |
40.5 |
50.7 |
31.37 |
从测试结果看:
- 低并发场景下,只读实例和主实例压力都不大,流量从主实例切换到只读实例上,RT衰减近30%~40%, 但都是在业务可以接受的RT范围内抖动;
- 随着并发增加,流量从主实例切换到只读实例上RT衰减会变得不明显,主实例的资源会成为影响RT的主要因素。
本文的读写分离路由的是非事务下的只读流量,这里给大家提一个问题:事务下的读查询是否可以做读写分离?
谈谈PolarDB-X在读写分离场景的实践的更多相关文章
- Oceanbase读写分离方案探索与优化
[作者] 许金柱,携程资深DBA,专注于分布式数据库研究及运维. 台枫,携程高级DBA,主要负责MySQL和OceanBase的运维. [前言] 读写分离,是一种将数据库的查询操作和写入操作分离 ...
- sql server几种读写分离方案的比较
在生产环境中我们经常会遇到这种情况: 前端的oltp业务很繁忙,但是需要对这些运营数据进行olap,为了不影响前端正常业务,所以需要将数据库进行读写分离. 这里我将几种可以用来进行读写分离的方案总结一 ...
- MySQL主从复制与读写分离
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中, ...
- MySQL主从复制与读写分离 --非原创
原文出处:http://www.cnblogs.com/luckcs/articles/2543607.html MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 ...
- MySql的主从复制以及读写分离详解
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中, ...
- mysql读写分离 主从同步
MySQL主从复制与读写分离的实现 转载 2013年01月17日 18:20:12 MySQL主从复制与读写分离 MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy) ...
- [转]MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践
转自:http://heylinux.com/archives/1004.html Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中,由单 ...
- PHP CodeIgniter框架实现读写分离
一.目标 当前服务器只做了主从,未配置读写分离,读写分离的功能就只有交给程序来实现,本文主要谈谈Codeigniter怎么实现读写分离,并且需要满足以下两点: 1.读写分离对开发应该透明. 网上有方案 ...
- MySQL的读写分离的几种选择
MySQL的读写分离的几种选择 MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 原址如下: http://heylinux.com/archives/1004. ...
- MySQL主从复制与读写分离(非原创,谢绝膜拜)
MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践 Mysql作为目前世界上使用最广泛的免费数据库,相信所有从事系统运维的工程师都一定接触过.但在实际的生产环境中, ...
随机推荐
- PlayBook 详解
4)Playbook 4.1)Playbook 介绍 PlayBook 与 ad-hoc 相比,是一种完全不同的运用 Ansible 的方式,类似与 Saltstack 的 state 状态文件.ad ...
- day03-自己实现Mybatis底层机制-02
自己实现Mybatis底层机制-02 7.任务阶段4&5 阶段4任务:开发Mapper接口和Mapper.xml 阶段5任务:开发和Mapper接口相映射的MapperBean (1)Mapp ...
- day18--Java集合01
Java集合01 1.什么是集合? 前面我们保存数据使用的是数组,数组有不足的地方,我们来分析一下: 长度开始时必须指定,而且一但指定不能更改 保存的必须是同一类型的元素 使用数组进行增加/删除元素的 ...
- CSS(相对定位relative、绝对定位absolute、固定定位fixed、定位应用、元素的显示和隐藏)
一. 定位(position) 介绍 1.1 为什么使用定位 我们先来看一个效果,同时思考一下用标准流或浮动能否实现类似的效果? 场景1: 某个元素可以自由的在一个盒子内移动位置,并且压住其他盒子. ...
- 超高并发下,Redis热点数据风险破解
★ Redis24篇集合 1 介绍 作者是互联网一线研发负责人,所在业务也是业内核心流量来源,经常参与 业务预定.积分竞拍.商品秒杀等工作. 近期参与多场新员工的面试工作,经常就 『超高并发场景下热点 ...
- CDC报错:invalid value null used for required field "null"
原因:数据库ceate_time时间字段设置为not null ,但是没有设置default值解决办法:1.修改ceate_time字段可以为null,即去掉 `create_time` dateti ...
- 实例演示如何使用CCE XGPU虚拟化
本文分享自华为云社区<CCE XGPU虚拟化的使用>,作者: 可以交个朋友. 一 背景 在互联网场景中,用户的AI训练和推理任务对GPU虚拟化有着强烈的诉求.GPU卡作为重要的计算资源不管 ...
- DNS的各种记录类型的应用解析
可能很多人平时工作中不会遇到DNS配置相关的问题, 但如果偶尔遇到不同类型DNS记录的配置, 在没有搞清楚它们都是干啥的情况下, 会眼花缭乱, 还记得很多年前实验室配置DNS不太对导致只能访问www. ...
- requests进阶
requests进阶 三.requests模块处理cookie相关的请求 1 爬虫中使用cookie 为了能够通过爬虫获取到登录后的页面,或者是解决通过cookie的反扒,需要使用request来处理 ...
- #最大公约数#CF346A Alice and Bob
题目传送门 CF346A 分析 可以发现其所能表示的数就是能被最大公约数整除的数,且这些数不能超过最大值, 于是判断一下取数的奇偶性即可 代码 #include <cstdio> #inc ...