sql随机抽取数据50条_厉害!苏宁通过citus打造分布式数据库抗住DB高负载

2018-07-16 23:59

e73b3109142db6cd4dd784efc47c3b7f.png

内容来源:2017 年 10 月 20 日,苏宁云商IT总部资深技术经理陈华军在“PostgreSQL 2017中国技术大会”进行《苏宁citus分布式数据库应用实践》演讲分享。IT 大咖说(微信id:itdakashuo)作为独家视频合作方,经主办方和讲者审阅授权发布。

摘要

本次分享主要介绍了如何通过Citus打造分布式数据库,对具体的部署情况进行了讲解。

嘉宾演讲视频回放及 PPT,请复制链接:http://t.cn/RdmlKXd,粘贴至浏览器地址栏即可。

业务场景

40b10f1ad3906aa6490993c40a7e3998.png

上图的系统架构主要是做订单的分析,它会定时的从其他的业务系统中抽取订单以及订单的更新信息。每5分钟进行一次批量的处理,更新10张左右的明细表。在数据库中同样也是5分钟做一次处理,首先会对明细表进行计算,之后的计算结果会被放到报表中。架构外层还有一些其他系统,比如 cognos、智能分析 等,它们主要是用来从数据中查报表或明细表。

这套系统中我们采用的数据库是 DB2,平时的 CPU 负载都达到了 50% 左右,大促期间更是超过了 80%,可以算是不堪重负。
DB负载在哪?
如此高的负载,到底问题是出在那些地方?其实主要是在明细更新、报表计算、报表查询/明细查询上明细更新时是5分钟更新10张明细表,这其中最宽的表有400字段,大概每行2.5kB。每次更新最宽的表约10w记录,总体上是30w。我们还要保持最近数天的数据。这样看下来其实主要的压力是在随机更新,换算一下大概每秒要做5k条记录的更新,关键是这 5K条记录还都是宽表。报表计算也是每5分钟计算30多张报表,要求2分钟完成,每个报表平均执行14次明细表集合查询。估算下来大概是每分钟200次明细表的聚合运算。报表查询/明细查询中要求的并发度是大于30,但正常情况下没有这么高,大概只有10个左右。同时要求的响应时间要小于3秒。
由于我们的系统接入的业务需要扩张,预计年内负载还会增加10倍,也就是说原先的每秒5k的明细表随机更新和3000w明细表数据,将提升为每秒5k的明细表随机更新和3亿明细表数据。
这样的背景下基于单机的DB 2肯定是搞不定的,我们需要的应该是一种分布式方案。
方案选型

cb2ca049f44ff1f09a43128267cdced2.png


上图列出的就是我们当时所考察的各种方案,因为PG在分析上还是比较有优势,所以这些方案都和PG相关。第一个Greenplum由于已经比较成熟了,所以我们一开始就比较看好,但是它更新慢、并发低的缺陷,不符合明细更新的性能要求,因此被排除在外。第二个postgres_fdw由于不支持聚合下推和并行查询,所以不符合明细表查询性能要求。第三个PG_XL方案我们并没有做深入的评估,但是GMT对性能是有影响的,估计很难满足我们对随机更新的需求。最后的citus的优势在于它是一个扩展,稳定性和可维护性都比较好,同时分片表的管理也很方便,最终我们选择的就是这个方案。Citus介绍
Citus架构与原理

af0d47cb3e1ed0838e3212da56442072.png


这张是Citus的架构图,可以看到它由1个maste多个worker组成,数据表通过hash或者append分片的方式分散到每个worker上。这里的表被分为分片表和参考表,参考表只有一个分片,并且每个worker上都有一份。
在应用访问的时候master接收应用的查询SQL,然后对查询SQL进行解析生成分布式执行计划,再将子执行路径分发到worker上执行,最后汇总执行结果返回给应用。
Citus主要适用于两种环境,一种是实时数据分析,一种是多租户应用。
案例演示

cf097755b2b28f692df42b6d5166ef1b.png


这里演示的是Citus的使用过程。分片表的创建和普通表是一样的,只不过完成之后需要设置分片数,最后执行create_distributed_table函数,参数为需要分片的表以及分片字段,还可以指定分片方法,默认是hash方式。参考表的不同在于函数换成了create_reference_table。这两个函数主要做了两件事,首先是在每个worker上创建分片,其次是更新元数据。元数据定义了分片信息。

9e1672806687aad9cf8b39ac95eca7aa.png


元数据pg_dist_partition中存放的是分片表和分片规则,可以从图中看到,h代表的hash分片,n表示的是参考表。分片表中有一个partkey,它用来指定哪个字段做分片以及分片类型。

cda3c1c9fc39b0d3c032be56972b62f6.png


元数据- pg_dist_shard定义了每个分片以及分片对应的hash范围,不过参考表由于只有一个分片,所以没有hash范围。

19d691ba86b9066aa3ce38872872d7a5.png


元数据-pg_dist_shard_placement定义了每个分片存放的位置,第一列是分片的ID号,后面是所在的worker节点位置和端口号。

4a9359fc124312c20591acc4d93525ed.png


基于元数据master可以生成分布式执行计划,比如聚合查询就会生成如上图所示的执行计划。上半部分是在每个worker上预聚合,每个分片并行执行,下面则是master对worker的结果做最终的聚合。
SQL限制—查询
Citus最大的缺陷在于有着SQL限制,并不是所有SQL都支持。最典型的就是对Join的限制,它不支持2个非亲和分片表的outer join,仅task-tracker执行器支持2个非亲和分片表的inner join,对分片表和参考表的outer join,参考表只能出现在left join的右边或right join的左边。对子查询也有着限制,子查询不能参与join,不能出现order by,limit和offset。一些SQL特性Citus同样不支持,比如CTE、Window函数、集合操作、非分片列的count(distinct)。最后还有一点需要注意,即本地表不能和分片表(参考表)混用。
这些限制其实都可以使用某些方法绕过,比如通过Hll(HyperLogLog)插件支持count(distinct),对于其他的一些操作也可以通过临时表或dblink中转。不过临时表的问题在于会将一个SQL拆成多个SQL。
SQL限制—更新
在更新上也存在一些限制,它不支持跨分片的更新SQL和事务,‘insert into ... select ... from ...’的支持存在部分限制,插入源表和目的表必须是具有亲和性的分片表,不允许出现Stable and volatile函数,不支持LIMIT,OFFSET,窗口函数,集合操作,Grouping sets,DISTINCT。
当然这些限制也存在对应的回避方法,首先是使用copy代替insert,其次是用SELECT master_modify_multiple_shards(‘…’)实现扩分片更新。
SQL限制—DDL

f205e7a925acb868cb54711c7eb0b304.png


上图展示的是对DDL的支持情况,这里面大部分都是支持的,对于不支持的可以通过创建对等的唯一索引代替变更主键,或者使用`run_command_on_placements`函数,直接在所有分片位置上执行DDL的方式来进行回避。
两种执行器
Citus有两种执行器,通过set citus.task_executor_type='task-tracker'|'real-time'进行切换。
默认的real-time又分为router和非router方式。router适用于只需在一个shard上执行的SQL,1个master后端进程对每个worker只创建一个连接,并缓存连接。非route下master后端进程会对所有worker上的所有shard同时发起连接,并执行SQL,SQL完成后断开连接。
如果使用task-tracker执行器。Master是只和worker上的task-tracker进程交互,task-tracker进程负责worker上的任务调度,任务结束后master从worker上取回结果。worker上总的并发任务数可以通过参数控制。

eb8e13d60a6ca2bc2c84be1ceb39527e.png


这里对这两种执行器进行了比较。real-time的优势主要在于响应时间小。task-tracker则是支持数据重分布,SQL支持也比real-time略好,同时并发数,资源消耗可控。部署方案
痛点

61de01242c2d6d1c81b4c5f78ec2c08d.png


我们的系统中首先面临的痛点就是对随机更新速度要求高。上图左边是Citus官方展示的性能数据,看似接近所需的性能要求,实际上远远不够,因为这里记录的是普通的窄表,而我们的是宽表而且还有其他的负载。
图中右边是我这边做的性能测试。单机状态下插入速度是每秒13万条,使用Citus后下降到了5w多,这主要是由于master要对SQL进行解析和分发。在尝试对Citus进行优化后,使Citus不解析SQL,提升也不是很明显。最后一种方式是不使用master,将每个worker作为master,这次的效果达到了每秒30万条。
第二个痛点就是前面提到的SQL限制问题,虽然这些限制都有方法回避,但是对应用的改造量比较大。
解决方案

22db446b75caff28e2bf0bafb05a90bf.png


这是我们最终的解决方案。首先对于插入和更新数据慢的问题,不在走master,直接在worker上更新。在更新之前会现在worker上查询分片的元数据,然后再进行更新。
另外为了尽量减少SQL限制对应用的影响,我们采用的策略是尽量少做分片,只对明细表进行分片。应用在查询的时候会将报表和维表做join,也会将明细表和维表做join,那么这里就会出现问题,因为本地表和参考表不能出现在同一个SQL里。所以我们做了N份参考表,每个worker放一份,同时再将一份本地维表放在master上,由报表做join用,最后在更新的时候通过触发器同步本地维表和参考表。
辅助工具函数开发
为了支撑前面提到的两个策略,我们实现了两个函数。pg_get_dist_shard_placement()函数用来批量获取记录所在分片位置函数。create_sync_trigger_for_table()函数用来自动生成本地维表和参考维表同步触发器的函数。
连接池

db85ef167f9f53b76959b5fdd35d0d12.png


因为业务对SQL的响应时间要求较高,所以我们使用的是real time执行器。但是由于real time存在的缺陷,因此我们在master上部署了两套pgbounce连接池。一个在PostgreSQL前面,应用在连接PostgreSQL前先连接到pgbouncer。另一个在master和worker之间。
实际的使用的时候由于pgbounce不支持prepare语句,所以有些应用还是要直连到master。
效果

3b538fdbd4e8ae8ada236cdd8810dfee.png


上图是POC压测的结果,基本上明细更新和报表结算满足了性能要求。测试的时候我们使用的是8个worker,而在部署的时候其实是先部署4台,然后再扩容到8台。
日常维护
Citus的维护和普通的PG维护在大部分情况下区别不大,不过有些有时候DDL执行会无法分发,这时可以用它的一些公有函数来完成。
另外更新多副本分片表的途中worker发生故障,可能导致该worker上的副本没有被正确更新。此时citus会在系统表pg_dist_shard_placement 中将其标识为“失效”状态。使用master_copy_shard_placement() 函数就能够进行恢复。
Citus对DDL、copy等跨库操作采用2PC保障事务一致,2PC中途发生故障会产生未决事务。对每个2PC事务中的操作都记录到系统表pg_dist_transaction,通过该表就能够判断哪些事务该回滚或提交。踩过的坑
在实际的应用中我们并没有碰到什么大坑,主要是一些小问题。第一个是由于master(real-time)到worker用的短连接,pgbouncer默认记录连接和断连接事件,导致日志文件增长太快。后来我们将其关闭了。第二个是master(real-time)会瞬间创建大量到worker 的并发连接,而默认的unix套接字的 backlog连接数偏低, master节点的 PostgreSQL日志中经常发现大量连接出错的告警。对此的解决办法是修改修改pgbouncer的listen_backlog,然后硬重启pgbouncer。

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

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

相关文章

java中Debug调试、异常的概念、异常体系、处理异常的关键字try/catch/finally/throw/throws、多个异常使用捕获并处理的方式、继承关系中处理异常、自定义异常类

Debug调试: bug指程序当中遇到的一些错误异常,Debug指调试bug,找到bug对其解决;debug可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug或异常。 public class DebugClass {public static void main(Strin…

densenet网络结构_FC-DENSENET用于图像分割学习笔记

近日使用FC Dense Net 做分割,记录学习使用过程。FC-DenseNet 原文链接:https://arxiv.org/abs/1611.09326 《The One Hundred Layers Tiramisu: Fully Convolutional DenseNets for Semantic Segmentation》初次使用此网络,第一眼是被这个名…

mongodb mysql资源占用_如何限制mongodb启动时占用过多内存

默认情况下,mongodb占用的内存大小为:Starting in 3.4, the WiredTiger internal cache, by default, will use the larger of either:50% of RAM minus 1 GB, or256 MB.下面我们来看一下限制mongodb启动时占用内存的方法:新增配置文件 /etc/…

js ...运算符_「 giao-js 」用js写一个js解释器

前言在这篇文章中,我们将通过 JS 构建我们自己的 JS 解释器,用 JS 写 JS,这听起来很奇怪,尽管如此,这样做我们将更熟悉 JS,也可以学习 JS 引擎是如何工作的!什么是解释器 (Interpreter) ?解释器是在运行时运行的语言求值器,它动态地执行程序的源代码。 解释器解析源代码,从源代…

地区json文件_【小例子】使用jQuery实现省市区三级联动显示,附源码json文件

开发工具-intellij IDEA需求1.实现对json文件的读取。2.可以在省级选择所有省名和直辖市名3.选择一级省名后自动刷新市名4.选择二级市名后自动刷新区名逻辑分析第一步:读取json文件第二步:遍历出所有一级的省名第三步:把遍历出来的省名动态追…

qt 状态栏

有段时间没有写过博客了。假期去上海旅游,所以一直没有能够上网。现在又来到这里,开始新的篇章吧!今天的内容主要还是继续完善前面的那个程序。我们要为我们的程序加上一个状态栏。状态栏位于主窗口的最下方,提供一个显示工具提示…

动态获取textarea后面的p标签_HTML简单标签连起实现的小玩意:

《今天不发知识点,刚被误封了,所有没有太多时间去给整理哈,请谅解》(谢谢欣赏)前面发了那么多HTML标签,今天来玩个小视频,小白也能几分钟就会的,代码没有写好,时间急了点…

elipse+pydev+python开发arcgis脚本程序

环境配置参考:http://www.cnblogs.com/halfacre/archive/2012/07/22/2603848.html 添加arcpy类库、arctoolbox、arcgis-bin如下所示。 windos——preference——pydev 完成环境配置。 二、获取文件路径Python方法 os.getcwd()返回的是当前文件的目录。假如我的代码…

BZOJ3427 Poi2013 Bytecomputer

可以YY一下嘛 最后一定是-1, -1, ..., -1, 0, 0, ... 0, 1, 1, ..., 1的一个数列 于是f[i][j]表示到了第i个数,新数列的第j项为-1 or 0 or 1的的最小代价 然后就没有然后了 1 /**************************************************************2 Problem: 3427…

mysql timdir_MYSQL学习笔记——数据类型

mysql的数据类型可以分为三大类,分别是数值数据类型、字符串数据类型以及日期时间数据类型。数值数据类型数值类型又可以分为整型、浮点类型、Decimal。整型mysql的整型可以分为TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,下表给出了每个类型的存储空间…

python编写网页游戏脚本_[大数据]用Python脚本做一些网页游戏中力所能及的自动化任务 - 码姐姐找文...

下面是一段自动登录360传奇霸业游戏的脚本: from pymouse importPyMouseimporttimeimportwebbrowserfrom pykeyboard importPyKeyboard url "http://cqby.wan.360.cn/game_login.php?server_idS577&&srcloginhistory"webbrowser.open_new_tab(ur…

flutter怎么添加ios网络权限_使用Flutter控制蓝牙通讯

背景知识视频教程Dart和Flutter:完整的开发人员指南 - 国外课栈​viadean.comFlutter使用Firestore构建复杂的Android和ios应用 - 国外课栈​viadean.comFlutter的实际项目 - 国外课栈​viadean.com您想使用蓝牙玩物联网设备,但不能在其中放置任何软件吗…

python网页结构分析_Python爬虫基础之网页组成解析

当我们用浏览器访问网站时,每个网页的大不相同,你是否想过它为什么会呈现多种不同的样式呢?就让我们一起了解一下网页的基本组成、结构和节点等内容吧!网页的组成 网页可以分为三大部分——HTML、CSS和JavaScript。如果把网页比作…

完全开源im框架_【行业资讯】移动端开源 IM 框架 MobileIMSDK v5.0 发布!

一、更新内容简介本次更新为主要版本更新,强势升级,可同时支持TCP、UDP两种协议,精心封装之下,实现一套API、两种协议同时并存。可能是市面上唯一同时支持UDPTCP两种协议的同类IM框架。二、MobileIMSDK简介MobileIMSDK是一套专为移…

python使用函数目的_Python函数的概念和使用

Python Python开发 Python语言 Python函数的概念和使用函数 为了便于程序的维护和更好的实现模块化,好的程序都会分解为很多函数。 可以这么说,对于任何的编程语言,函数都是一个非常重要的概念。 python 不仅简化了函数的定义过程&#xff0c…

feign直接走熔断_SpringCloud微服务面试必问:Hystrix 服务降级、熔断

本文作者:JLSong 本文链接:https://www.cnblogs.com/songjilong/p/12770999.html1、Hystrix是什么?Hystrix 是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比…

python里面print是什么意思_python里print是什么意思

python里print是什么意思,多个,是一个,对象,默认值,一个函数 python里print是什么意思 易采站长站,站长之家为您整理了python里print是什么意思的相关内容。 Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。Python由Guido van Rossum于1989年底发明…

mysql 用户管理系统_mysql 用户管理

MySQL账户管理在我们之前登录MySQL的时候我们都是直接使用的root用户,root用户属于数据库系统中的超级管理员,有权限对mysql进行任何想要做的操作。如果在生产环境下操作数据库时也是全部直接使用root账户连接,这就和悬崖边跳舞差不多。所以 …

执行一次怎么会写入两次数据_浅谈 Redis 数据持久化之 AOF 模式

我们知道 Redis 之所以读写快、性能高,得益于它是一种基于内存的数据库,毫无疑问它的操作都几乎都是基于内存。但是内存型数据库也有一个很大的弊端:如果进程崩溃或者服务重启的时候内存数据得不到保存,就会造成数据丢失。为了解决…

数字化转型方法论_双中台:企业数字化转型的核心战略与方法论

当下,绝大部分企业的组织形态、经营模式基本都是垂直闭环型,即围绕一种业务或者管理,其计划、执行、检查、优化的闭环都是独立于企业生态之中。在过去的“局部竞争”、“渠道为王”、“终端为王”的时代,这种组织与经营形式很好地…