谈谈 PolarDB-X 在读写分离场景的实践

在数据库使用过程中经常会遇到一些场景:

  1. 业务写流量一直相对比较稳定,但随着时间,数据不断增加,数据库的压力也会越来越大,写操作会影响到读请求的性能,做任何优化可能都达不到最终的效果;
  2. 在应用的用户访问量比较低的时候,一个数据库的读写能力是完全能够胜任的。但是在用户访问量增大的时候,数据库很快会成为瓶颈;

针对这种写少读多的业务可以考虑通过添加数据库节点来使其达到提升性能的目的,但添加节点,往往涉及到数据的搬迁,扩容周期比较长,很难应对徒增的业务流量。这个时候可以考虑采用读写分离的方式,将读写流量做分流,减轻主实例的压力,同时利用只读库横向的扩展能力,快速提升读性能。

其基本原理是让主数据库处理事务性查询,而从数据库处理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可以确保读到已提交的一致性数据。路由到只读节点的强一致性读查询过程如下:

  1. 客户端把请求发送到CN;
  2. CN识别到请求会发送给只读实例,首先会从主实例DN节点获取当前最大LogIndex;
  3. CN把LogIndex +TSO 请求一起发送给只读节点;
  4. 只读节点根据接收到的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

测试结果

并发不一致性次数(弱一致性读)不一致性次数(强一致性读)
420
850
16160
32330
64570

从测试结果看,强一致性读下,可以保证路由到只读实例的流量读到最新的数据;而非强一致性读下,无法保证。

实验二:高并发下吞吐表现

我们分别利用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.1788201.1788201.1788201.17
50%124269.63171935.56171783.84208648.34
100%62891.8689213.13117133.83169352.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.4329145.4329145.4329145.43
50%44084.4055399.8061698.8573161.11
100%23115.2329235.7342160.5456393.54

从测试结果看:

1. 在强一致性读下,在TP读场景下流量从主实例切换到只读实例上吞吐的性能衰减20~30%,但是通过添加只读实例个数,性能可以做到一定的线性增加;

2.在弱一致性读下,在TP读场景下流量从主实例切换到只读实例上吞吐的性能未衰减,且通过添加只读实例的个数,性能可以做到线性增加;

实验三:低并发下RT表现

同样的我们分别利用oltp_point_select和oltp_read_only两个脚本,测试了下在(一个主实例+只读实例)下在强一致性读条件下,不同并发的RT表现

  • 点查场景(ms)
并发只读查询比例0%只读查询比例100%只读查询比例50%
40.610.890.87
80.620.910.89
160.640.940.90
320.711.040.99
641.181.271.27
  • oltp_read场景(ms)
并发只读查询比例0%只读查询比例100%只读查询比例50%
411.6521.8917.63
812.2122.6917.29
1614.2123.9518.23
322027.1721.50
6440.550.731.37

从测试结果看:

  1. 低并发场景下,只读实例和主实例压力都不大,流量从主实例切换到只读实例上,RT衰减近30%~40%, 但都是在业务可以接受的RT范围内抖动;
  2. 随着并发增加,流量从主实例切换到只读实例上RT衰减会变得不明显,主实例的资源会成为影响RT的主要因素。

本文的读写分离路由的是非事务下的只读流量,这里给大家提一个问题:事务下的读查询是否可以做读写分离?

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/510384.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源数据库 PolarDB 为什么能捕获娃哈哈的心?

一、娃哈哈的需求 娃哈哈已经使用PostgreSQL多年,使用了大量逻辑复制,且备库仅提供一些业务的只读服务。同时,其重要业务的数据库运行在共享SAN存储上。因此,它存在主备库延迟较大、逻辑复制不稳定且延迟大的痛点。 二、使用Pola…

全排列算法解析(视频+详解+代码+STL)

全排列生成算法 刚开始自学的时候搜了两三个scdn中关于讲解全排列问题的博客,但是我理解能力比较差还是没有完全理解 ,后来就在网上搜索了视频才完全弄懂,现在把我理解的分享给你们。 学习视频:http://v.ku6.com/show/RP7r6vew4Qb…

数据库 PolarDB 开源之路该如何走?听听他们怎么说

阿里巴巴集团副总裁、阿里云数据库事业部负责人李飞飞出席了沙龙并致开场辞:PolarDB 是阿里云的明星产品,做出将PolarDB 开源的决策需要非常大的勇气。将最核心的数据库产品对外开源,且使用了最友好的协议,阿里云是全球头部云厂商…

通过定时 SQL 提取阿里云API 网关访问日志指标

背景 阿里云API网关服务提供API托管服务,提供了强大的适配和集成能力,可以将各种不同的业务系统API实现统一管理。API网关同时支持将API访问日志一键存储到日志服务,通过日志服务强大的查询分析能力,用户可以针对访问日志自定义计…

HDU 3573(详解+思路+代码)

Description Imyourgod need 3 kinds of sticks(树枝) which have different sizes: 20cm, 28cm and 32cm. However the shop only sell 75-centimeter-long sticks. So he have to cut off the long stick. How many sticks he must buy at least. Input The first line of…

2022云栖现场|体验阿里巴巴工作数字化实践

越来越多的企业主动拥抱数字化转型,借助数字化工具提高企业运营效率,实现企业目标落地、帮助员工成长。 2022云栖大会,阿里巴巴企业智能带来阿里数字化工作方法与企业IT解决方案,展示着阿里内部在办公协同与IT管理上的实际应用场…

K8s 场景下 Logtail 组件可观测方案升级-Logtail 事件监控发布

背景 随着K8s和云的普及,越来越多的公司将业务系统部署到云上,并且使用K8s来部署应用。Logtail是SLS提供的日志采集Agent,能够非常好的适应K8s下各种场景的日志采集,支持通过DaemonSet方式和Sidecar方式采集Kubernetes集群的容器…

一图看懂,阿里云飞天企业版如何支持政企数智创新

杭州,2022年11月5日 – 今日,在云栖大会专有云技术和应用实践论坛,阿里云重磅发布飞天企业版在建云、管云、用云方面的全面升级,并邀请行业专家、政企客户代表和合作伙伴面向未来十年共话新一代政企IT发展趋势,分享阿里…

hdu3579(中国剩余问题经典)

Description One day I was shopping in the supermarket. There was a cashier(收银员) counting coins seriously when a little kid running and singing "门前大桥下游过一群鸭,快来快来 数一数,二四六七八". And then the cashier put t…

关于HTTPDNS,你知道多少?

什么是HTTPDNS? HTTPDNS是面向多端应用(移动端APP,PC客户端应用)的域名解析服务,具有域名防劫持、精准调度、实时解析生效的特性。 HTTPDNS工作流程 客户端直接访问HTTPDNS接口,获取业务在域名配置管理系…

当大火的文图生成模型遇见知识图谱,AI画像趋近于真实世界

导读 用户生成内容(User Generated Content,UGC)是互联网上多模态内容的重要组成部分,UGC数据级的不断增长促进了各大多模态内容平台的繁荣。在海量多模态数据和深度学习大模型的加持下,AI生成内容(AI Gen…

最大最小距离算法(K-MEANS K-medoids )聚类算法的结合运用

聚类算法通常会得到一种分类,将n个点聚合成k类,同一聚类(即插槽簇)中的对象相似度较高;而不同类中的对象相似度较小。聚类算法的基本流程如下:(1)从n个节点中选择 k 个节点作为初始聚…

使用 EasyCV Mask2Former 轻松实现图像分割

导言 图像分割(Image Segmentation)是指对图片进行像素级的分类,根据分类粒度的不同可以分为语义分割(Semantic Segmentation)、实例分割(Instance Segmentation)、全景分割(Panoptic Segmentation)三类。图像分割是计算机视觉中的主要研究方向之一,在医…

八皇后问题详解(最短代码)

八皇后问题算法分析: 分析1:八皇后由一个64格的方块组成,那么把八个皇后放入不考虑其他情况利用穷举法,有8^64种 可能。 分析2:显然任意一行有且仅有1个皇后,使用数组queen[0->7]表示第i行的皇后位于哪一…

5个编写技巧,有效提高单元测试实践

1. 什么是单元测试 “在计算机编程中,单元测试又称为模块测试,是针对程序模块来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最…

谈谈我工作中的23个设计模式

序 从基础的角度看,设计模式是研究类本身或者类与类之间的协作模式,是进行抽象归纳的一个很好的速成思路。后面阅读设计模式后,为了加深理解,对相关图片进行了描绘和微调。 从技术的角度已经有很多好的总结,本文会换…

三种方法求最长子序列问题

#include<iostream> #include<algorithm> using namespace std; int maxsum(int a[],int x,int y) {int v,l,r;if(y-x1)//只有一个元素&#xff0c;直接返回 return a[x];int mx(y-x)/2;//分治法第一步&#xff0c;划分成[x,m)和[m,y)int maxsmax(maxsum(a,x,m),ma…

OpenSergo 流量路由:从场景到标准化的探索

流量路由&#xff0c;顾名思义就是将具有某些属性特征的流量&#xff0c;路由到指定的目标。流量路由是流量治理中重要的一环&#xff0c;多个路由如同流水线一样&#xff0c;形成一条路由链&#xff0c;从所有的地址表中筛选出最终目的地址集合&#xff0c;再通过负载均衡策略…

传统 Web 框架部署与迁移

与其说 Serverless 架构是一个新的概念&#xff0c;不如说它是一种全新的思路&#xff0c;一种新的编程范式。 但是原生的 Serverless 开发框架却非常少。以 Web 框架为例&#xff0c;目前主流的 Web 框架“均不支持 Serverless 模式部署”&#xff0c;因此我们一方面要尝试接…

归并排序(视频+详解+代码)

归并排序 概述&#xff1a;归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使…