分布式MySQL集群方案,看看京东是怎么做的

京东资深架构师深度解析《MySQL 实战》 张松然 本文为读《MySQL 实战》摘抄的读书笔记,原文更加精彩,推荐大家阅读,并表达对原作者的支持。 基础架构:一条 SQL 查询语句是如何执行的? MySQL 的基本架构示意图: MySQL 可以分为 Server 层和存储引擎层两部分。 Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。 存储引擎层负责数据的存 阅读详情


背景

数据库作为一个非常基础的系统,任何一家互联网公司都会使用,数据库产品也很多,有Oracle、SQL Server 、MySQL、PostgeSQL、MariaDB等,像SQLServer/Oracle 这类数据库在初期可以帮业务搞定很多棘手的事情,我们可以花更多的精力在业务本身的发展上,但众所周知也得交不少钱。

涉及到钱的事情在公司发展壮大以后总是会回来重新审视这个事情的,在京东早期发展的过程中确实有一些业务的数据就是直接存在oracle或者sqlserver中。

后来随着业务的发展以及数据量访问量的不断增加及成本等方面的考虑,从长远考虑需要把这些业务用免费的MySQL来存,但单机的MySQL往往无法直接抗住这些业务,自然而然的我们就需要考虑引入分布式的MySQL解决方案帮助业务去SQLServer/Oracle以及支撑未来的发展。

方案选型对比及京东实现方案

说到分布式MySQL的解决方案一般来说解决方案主要就两种,客户端的方案或者中间代理的方案,如下图所示。

这两种方案各有各的优缺点:客户端的方案是指会给业务提供一个专门的客户端的包,这种方案在实现上会更容易一点,如果公司需要快速出一个相对通用的解决方案,客户端的方案可以优先考虑。

客户端方案需要为不同的语言提供不同的客户端的包,这点有所局限。客户端方案只需要走一段网络,理论上性能会更好一点。

客户端方案对业务有侵入,有一些系统部署及实现方面的可能可以控制得更好,但对业务本身不友好,客户端包升级等方面比较麻烦。

中间代理的方案是指采用一个兼容MySQL协议的代理的方式,业务可以使用任何语言的MySQL客户端的包,对业务本身无侵入的,这种方案相对来说是最友好的。

中间代理方案开发难度上来说门槛会更高一点,需要考虑前后端的东西,尤其是与MySQL端交互时自己解析协议的情况下会更复杂一些。中间代理方案多走一段TCP,对性能理论上会有一些影响。

上述两种方案有一个非常重要的因素没有提及,在实际生产环境中面临一个非常现实的问题是MySQL能支持的连接数是有限的。以MySQL5.5来说假设一个MySQL实例配置1000个连接,业务应用实例部署了100个,每个应用实例的数据库连接池配置20个,采用客户端方案这个MySQL实例都没法正常工作了。

大多数情况下并不是每个应用实例的每条连接都是活跃的,中间代理的方案可以很好的解决这个问题,应用实例可以有很多连接打到代理上,代理只需要维护较少的与MySQL的连接即可满足需求,代理与MySQL之间的连接会被业务打过来的访问重复使用。

另外关于多走一次TCP对性能的影响,从我们的实际经验来看其实可以忽略不计,业务实例一多优先遇到的是MySQL连接数的问题,从这个角度来说中间代理的方案会更优。

我们采用的就是中间代理的方案,京东的分布式MySQL方案由很多部分组成,有JManager、 JProxy、 JTransfer、JMonitor、JConsole、MySQL,在实际部署的时候还涉及到LVS以及域名系统等。

JManager是中心管理节点,这个节点负责统一管理系统的元信息,元信息包括路由信息、权限管理信息、资源相关的信息等。

JProxy就是一个兼容MySQL协议的代理,负责把客户端发送过来的SQL按照路由规则发送到相应的数据库节点上,再把返回的结果进行合并并返回给客户端。JProxy在启动的时候会先去JManager中拉取相关的元信息,并在自己的内存中维护一份,平时使用的时候只用自身内存维护的这一份就可以了。

JProxy的内部实现原理如图所示。

JTransfer是在线迁移系统,我们针对业务的数据进行拆分以后,比如某个MySQL实例上有32个库,等到业务数据量继续增大以后在这个实例上就放不下了,我们就需要往整个集群中加MySQL实例,将之前的32个库中一部分迁移到这个新增加的实例上,如何在不停业务的情况完成数据的在线迁移就是JTransfer这个系统来保证的。

JConsole系统可以理解为将多个业务的中心管理节点整合起来的一个后台管理控制系统,这个系统可以与每个JManager交互。在具体使用的时候,业务方需要申请创建库表、拆分规则、什么权限、对哪些IP授权,我们会通过JConsole系统与JManager交互完成元数据的配置。

JMonitor系统会将各个业务的jproxy以及MySQL相关的信息采集起来,整合到一起形成一个统一的监控系统,完成对系统的全面详尽的监控。

网络模型

JProxy作为一个非常典型的代理服务,程序本身的性能非常关键,具体在实现的时候我们参考了Nginx的网络模型。

大家都知道Nginx的性能非常高,根据机器核数配置相应的worker数就可以,每个worker可以理解为围绕一个epoll把前后端的连接以完全基于事件驱动的方式串在一起,避免了上下文切换避免了锁等待等各种可能阻塞或者耗时的操作。

同样的网络模型也可以参考一下Redis的实现,redis虽然不像nginx需要考虑前后端连接的处理,但redis的模型也是一种非常类似的经典的实现方式。

JProxy整个网络模型如图所示,采用一个全局的nioacceptor以及多个nioreactor,由nioacceptor统一accept连接,之后把连接分给某个nioreactor。

nioreactor可以理解为底层就是一个epoll(java nio实现),前后端的连接都是注册在这个epoll上,我们只需要根据事件是读事件或写事件调用相应的回调函数即可。这种模型的特点是系统几乎没有太多的上下文切换,而且性能很高。

基于事件驱动的网络模型的好处是性能很高,但问题也很明显,编写时复杂度非常高,一条SQL发送过来到收到结果的上下文被切成很多片段,同一时刻有来自很多不同上下文的不同的片段要处理,全程只有一个进(线)程来处理这些片段(暂且假设NIOReactor只配置成一个),所以在实现的过程中要求把所有的细节都考虑非常周全,一旦某个片段的处理有阻塞或者耗时,整个程序都将阻塞,个人觉得这种编程方式有点反人类思维。

关于分布式事务的思考

另外关于分布式事务的支持也是一个大家可能比较感兴趣的点,基于MySQL的方式来做分布式数据库的时候分布式事务是不可能满足严格的分布式事务语义的。

数据库事务有ACID四个属性,分别是原子性、一致性、隔离性、持久性。

原子性(Atomicity)的意思是整个事务最终只能是要么成功要么失败,不能存在中间状态,如果发生错误了就需要回滚回去,就像这个事务从来没有执行过一样。

一致性(Consistency)是指系统要处于一个一致的状态,不能因为并发事务的多少影响到系统的一致性,举个典型的例子就是转帐的情况,假设有ABC三个帐号各有100元,那么不管这三个帐号之间怎么转账,整个系统总的额度是300元这一点是应该是不变的。其实ACID里的一致性更多的是应用程序需要考虑的问题,和分布式系统里的CAP里的一致性完全不是一个概念。

隔离性(Isolation),本质上是解决并发执行的事务如何保证数据库状态是正确的,抽象描述叫可串行化,就是并发的事务在执行的时候效果要求达到看起来像是一个个事务串行执行的效果。有冲突的事务之间的隔离性如果保证不了会引起前面的一致性(consistency)也无法满足。

每个事务包含多个动作,这些动作如果按照事务本身的顺序依次执行就是所谓的串行执行,这些动作也可以重新排列,排列完以后的动作如果效果可以等价于事务串行执行的效果我们就叫做可串行化调度。

实际实现的时候往往采用的是冲突可串行化,这个条件比可串行化要求会更高一点,规定了一些读写顺序规定了一些访问冲突的情况规定了哪些情况两个事物的动作可以调换哪些是不可以的,可以理解为冲突可串行化是可串行化的充分条件。

持久性(Durability),在事务完成以后所有的修改可以持久的保存在数据库中,一般会采用WAL的方式,会把操作提前记录到日志中来保证即使操作还没有刷到磁盘就宕机的情况下有日志可以恢复。介绍完事务的ACID属性以后,我们再来分析为什么基于MySQL无法提供严格的分布式事务语义的支持。

如果客户端发送的SQL只涉及到一个节点,那自然是可以保证事务的,但是如果客户端发送的SQL涉及到两个及以上节点的SQL,那就无法保证事务语义了。

原因主要是两个,一是原子性无法保证,另一个是隔离性无法保证。在一个节点commit成功以后,在另外的节点commit失败了,这个事务就处在一个中间状态,此时原子性被打破。

引起的另一个问题就是隔离性,这个事务的一部分提交了,另一部分未提交,此时该事务正常是不该被读取到的,但是提交成功的部分会被其他事务读到,此时就无法保证隔离性了。

另外就算是涉及多个节点的操作都是成功的,理论上来说也是无法保证隔离性的。因为假设A事务的一个节点先commit成功,其他的节点后commit成功,而此时B事务在读取的时候可能会读取到了A事务最早commit成功的那部分内容,却没有读到后来commit成功的内容,此时依然无法保证隔离性。

更本质一点的原因是MySQL的事务都是每个实例维护自身的事务ID,而基于MySQL集群的分布式方案没有一个全局的事务ID来标识每个MySQL实例上的事务以及全局事务的元信息的管理,所以无法做到严格的分布式事务语义。

但实际上绝大多数业务对这个需求未必那么强烈,因为绝大多数的业务逻辑都是可以拆分的,拆成一个个只落在一个分库里的操作在绝大多数场景下是完全可行的,而且拆分完以后也会更可控,所以这个问题在我们支撑业务的过程中也不是一个特别大的问题。

生产环境监控很关键

在实际生产环境中有很多方面都非常重要,高可用高可靠可扩展等,但是除了这些之外还有一个非常关键的是监控。

一个再健壮再牛x的系统都需要配备完善的监控系统,监控系统是生产环境中非常重要的一道防线,没有监控的系统就像是在裸奔,线上突发状况很多完善的监控系统可以做到第一时间发现问题及时定位以及解决问题。

物理机监控

我们在生产环境中会对系统所在物理机进行监控,京东有一个专门的物理机监控系统,可以监控包括CPU、内存、网卡、TCP连接数、磁盘使用情况、机器load等很多基础指标,针对这些指标可以设置相应的报警阈值,当超过一定阈值时会以邮件及短信的方式报警。

存活监控

但物理机的监控对于具体的系统的来说是远远不够的,我们还需要关注很多系统本身的信息,首先要有存活监控,这是最基本的。一个系统在线上运行的时候服务本身宕掉一定要求是可以第一时间监控到的。

但除了物理机监控以外,还有一个非常关键的是存活监控。系统的一切前提是可以活着,我们在每个模块都会提供相应的http接口,接入公司的统一监控平台,一旦有异常统一监控平台会及时通知相应的负责人。

系统内部状态可视化监控

除了活下来以后,如何活得更好也是很关键的,所以我们还有专门针对分布式MySQL集群的JMonitor系统,该系统会整合各个模块的内部详细状态信息,包括慢查询、用户访问情况以及数据分布情况等。

一句话一个稳定健壮的系统一定要配备相应的完善的监控系统。今天我的分享就是这些,主要就是介绍一些分布式MySQL的相关方案以及京东是怎么做的,讨论了一下分布式事务的问题,最后是一小部分生产实践经验,谢谢大家。

Q&A

Q1:请介绍下分布式事务保证数据最终一致性的具体方案例子。

主要看这条SQL具体是做什么的,如果是抽数据,就正常抽就可以了。如果有阻塞基本都是因为在MySQL端因为锁冲突等原因造成阻塞,最终可能是这个事务被abort掉或者最终抢到锁成功做完了这个事务。

Q2:分布式事务如何支持,现在可以支持多大规模的集群。

基于Mysql的分布式集群方案无法保证严格的分布式事务语义,但是在实际使用的时候看业务情况,如果事务之间不怎么冲突的情况下也是ok的,如果可以改成只涉及一个分库的情况下那就绕开分布式事务的问题了。另外支持的集群,我们其实是根据业务来划分资源的,目前整体资源不能说特别大,千台规模。

Q3:JProxy是否可以支持所有复杂sql查询,主要是夸库的关联查询,具体内部逻辑可否介绍下?

我们目前不支持夸库关联查询,从业务层面来解决。因为大表之间分库以后如果要支持跨库关联查询的话,作为一个OLTP系统在实际生产环境估计就没法用了。

Q4:请介绍下MySQL实际应用中主从复制的方案,以及主从的数据差异会在什么程度,谢谢!

这个其实更多的是主从之间关注的问题,一般会采用基于mix的模式。另外主从差异这个不同业务不一样,加上严格的监控,正常访问的情况下一般不会出现延迟,但是如果涉及到业务倒数据或者突增的访问量可能会引起延迟,所以这个不太好参考,如果有异常我们都会第一时间及时介入处理。

Q5:长时间SQL不会造成堵塞吗?

主要看这条SQL具体是做什么的,如果是抽数据,就正常抽就可以了。如果有阻塞基本都是因为在MySQL端因为锁冲突等原因造成阻塞,最终可能是这个事务被abort掉或者最终抢到锁成功做完了这个事务。

Q6:请介绍一下JTransfers的工作机制,以及实现过程中最难的部分。

迁移确实是比较刺手的一件事情,要考虑的细节很多。大体的步骤是:我们提交迁移计划,指定什么时间开始迁移,到时间点以后JTransfer就会自动迁移。JTransfer一开始是dump源分库的数据,然后将这些数据恢复到目标实例上,但是在这个期间业务是正常访问的,需要将增量数据迁移完,所以会有追增量过程。当增量追到一定程度,我们会阻塞这个库的访问,最后将剩余的少量数据迁移完。因为最后剩余数据量不多的时候,阻塞过程其实很短暂,所以对业务影响非常小。

最难的部分是:整个迁移过程中的路由变更,要保证路由变更的过程中数据不能写花,且变更以后的路由要准确的推送到JProxy中,由JManager和多个JProxy之间在变更路由的时候采用类似两阶段提交的协议,从而保证路由的变更是正确的。

Q7:可以分享一下JProxy的并发性能优化,以及JProxy中间状态的异常与恢复机制吗?谢谢!

并发性能优化我们主要是通过采用基于事件驱动的网络模型,这种方式的特点是避免上下文切换避免锁的开销,但是代价的话刚才也说了需要考虑得非常周全,把一个上下文切成很多片段,不太符合人类思维。

JProxy中间件状态的异常与恢复机制这个我不是太理解什么含义哈,我的理解是如果jproxy运行过程中访问出异常了怎么处理,如果是某个连接过来的sql出了问题我们的做法是将整个连接涉及到的资源都关闭,把该次查询涉及到的前后端资源清理干净,这样就不会影响到其他客户端的访问。正常来说不应该出现这种情况,所以也需要完善的日志信息以及监控信息。

背景

数据库作为一个非常基础的系统,任何一家互联网公司都会使用,数据库产品也很多,有Oracle、SQL Server 、MySQL、PostgeSQL、MariaDB等,像SQLServer/Oracle 这类数据库在初期可以帮业务搞定很多棘手的事情,我们可以花更多的精力在业务本身的发展上,但众所周知也得交不少钱。

涉及到钱的事情在公司发展壮大以后总是会回来重新审视这个事情的,在京东早期发展的过程中确实有一些业务的数据就是直接存在oracle或者sqlserver中。

后来随着业务的发展以及数据量访问量的不断增加及成本等方面的考虑,从长远考虑需要把这些业务用免费的MySQL来存,但单机的MySQL往往无法直接抗住这些业务,自然而然的我们就需要考虑引入分布式的MySQL解决方案帮助业务去SQLServer/Oracle以及支撑未来的发展。

方案选型对比及京东实现方案

说到分布式MySQL的解决方案一般来说解决方案主要就两种,客户端的方案或者中间代理的方案,如下图所示。

这两种方案各有各的优缺点:客户端的方案是指会给业务提供一个专门的客户端的包,这种方案在实现上会更容易一点,如果公司需要快速出一个相对通用的解决方案,客户端的方案可以优先考虑。

客户端方案需要为不同的语言提供不同的客户端的包,这点有所局限。客户端方案只需要走一段网络,理论上性能会更好一点。

客户端方案对业务有侵入,有一些系统部署及实现方面的可能可以控制得更好,但对业务本身不友好,客户端包升级等方面比较麻烦。

中间代理的方案是指采用一个兼容MySQL协议的代理的方式,业务可以使用任何语言的MySQL客户端的包,对业务本身无侵入的,这种方案相对来说是最友好的。

中间代理方案开发难度上来说门槛会更高一点,需要考虑前后端的东西,尤其是与MySQL端交互时自己解析协议的情况下会更复杂一些。中间代理方案多走一段TCP,对性能理论上会有一些影响。

上述两种方案有一个非常重要的因素没有提及,在实际生产环境中面临一个非常现实的问题是MySQL能支持的连接数是有限的。以MySQL5.5来说假设一个MySQL实例配置1000个连接,业务应用实例部署了100个,每个应用实例的数据库连接池配置20个,采用客户端方案这个MySQL实例都没法正常工作了。

大多数情况下并不是每个应用实例的每条连接都是活跃的,中间代理的方案可以很好的解决这个问题,应用实例可以有很多连接打到代理上,代理只需要维护较少的与MySQL的连接即可满足需求,代理与MySQL之间的连接会被业务打过来的访问重复使用。

另外关于多走一次TCP对性能的影响,从我们的实际经验来看其实可以忽略不计,业务实例一多优先遇到的是MySQL连接数的问题,从这个角度来说中间代理的方案会更优。

我们采用的就是中间代理的方案,京东的分布式MySQL方案由很多部分组成,有JManager、 JProxy、 JTransfer、JMonitor、JConsole、MySQL,在实际部署的时候还涉及到LVS以及域名系统等。

JManager是中心管理节点,这个节点负责统一管理系统的元信息,元信息包括路由信息、权限管理信息、资源相关的信息等。

JProxy就是一个兼容MySQL协议的代理,负责把客户端发送过来的SQL按照路由规则发送到相应的数据库节点上,再把返回的结果进行合并并返回给客户端。JProxy在启动的时候会先去JManager中拉取相关的元信息,并在自己的内存中维护一份,平时使用的时候只用自身内存维护的这一份就可以了。

JProxy的内部实现原理如图所示。

JTransfer是在线迁移系统,我们针对业务的数据进行拆分以后,比如某个MySQL实例上有32个库,等到业务数据量继续增大以后在这个实例上就放不下了,我们就需要往整个集群中加MySQL实例,将之前的32个库中一部分迁移到这个新增加的实例上,如何在不停业务的情况完成数据的在线迁移就是JTransfer这个系统来保证的。

JConsole系统可以理解为将多个业务的中心管理节点整合起来的一个后台管理控制系统,这个系统可以与每个JManager交互。在具体使用的时候,业务方需要申请创建库表、拆分规则、什么权限、对哪些IP授权,我们会通过JConsole系统与JManager交互完成元数据的配置。

JMonitor系统会将各个业务的jproxy以及MySQL相关的信息采集起来,整合到一起形成一个统一的监控系统,完成对系统的全面详尽的监控。

网络模型

JProxy作为一个非常典型的代理服务,程序本身的性能非常关键,具体在实现的时候我们参考了Nginx的网络模型。

大家都知道Nginx的性能非常高,根据机器核数配置相应的worker数就可以,每个worker可以理解为围绕一个epoll把前后端的连接以完全基于事件驱动的方式串在一起,避免了上下文切换避免了锁等待等各种可能阻塞或者耗时的操作。

同样的网络模型也可以参考一下Redis的实现,redis虽然不像nginx需要考虑前后端连接的处理,但redis的模型也是一种非常类似的经典的实现方式。

JProxy整个网络模型如图所示,采用一个全局的nioacceptor以及多个nioreactor,由nioacceptor统一accept连接,之后把连接分给某个nioreactor。

nioreactor可以理解为底层就是一个epoll(java nio实现),前后端的连接都是注册在这个epoll上,我们只需要根据事件是读事件或写事件调用相应的回调函数即可。这种模型的特点是系统几乎没有太多的上下文切换,而且性能很高。

基于事件驱动的网络模型的好处是性能很高,但问题也很明显,编写时复杂度非常高,一条SQL发送过来到收到结果的上下文被切成很多片段,同一时刻有来自很多不同上下文的不同的片段要处理,全程只有一个进(线)程来处理这些片段(暂且假设NIOReactor只配置成一个),所以在实现的过程中要求把所有的细节都考虑非常周全,一旦某个片段的处理有阻塞或者耗时,整个程序都将阻塞,个人觉得这种编程方式有点反人类思维。

关于分布式事务的思考

另外关于分布式事务的支持也是一个大家可能比较感兴趣的点,基于MySQL的方式来做分布式数据库的时候分布式事务是不可能满足严格的分布式事务语义的。

数据库事务有ACID四个属性,分别是原子性、一致性、隔离性、持久性。

原子性(Atomicity)的意思是整个事务最终只能是要么成功要么失败,不能存在中间状态,如果发生错误了就需要回滚回去,就像这个事务从来没有执行过一样。

一致性(Consistency)是指系统要处于一个一致的状态,不能因为并发事务的多少影响到系统的一致性,举个典型的例子就是转帐的情况,假设有ABC三个帐号各有100元,那么不管这三个帐号之间怎么转账,整个系统总的额度是300元这一点是应该是不变的。其实ACID里的一致性更多的是应用程序需要考虑的问题,和分布式系统里的CAP里的一致性完全不是一个概念。

隔离性(Isolation),本质上是解决并发执行的事务如何保证数据库状态是正确的,抽象描述叫可串行化,就是并发的事务在执行的时候效果要求达到看起来像是一个个事务串行执行的效果。有冲突的事务之间的隔离性如果保证不了会引起前面的一致性(consistency)也无法满足。

每个事务包含多个动作,这些动作如果按照事务本身的顺序依次执行就是所谓的串行执行,这些动作也可以重新排列,排列完以后的动作如果效果可以等价于事务串行执行的效果我们就叫做可串行化调度。

实际实现的时候往往采用的是冲突可串行化,这个条件比可串行化要求会更高一点,规定了一些读写顺序规定了一些访问冲突的情况规定了哪些情况两个事物的动作可以调换哪些是不可以的,可以理解为冲突可串行化是可串行化的充分条件。

持久性(Durability),在事务完成以后所有的修改可以持久的保存在数据库中,一般会采用WAL的方式,会把操作提前记录到日志中来保证即使操作还没有刷到磁盘就宕机的情况下有日志可以恢复。介绍完事务的ACID属性以后,我们再来分析为什么基于MySQL无法提供严格的分布式事务语义的支持。

如果客户端发送的SQL只涉及到一个节点,那自然是可以保证事务的,但是如果客户端发送的SQL涉及到两个及以上节点的SQL,那就无法保证事务语义了。

原因主要是两个,一是原子性无法保证,另一个是隔离性无法保证。在一个节点commit成功以后,在另外的节点commit失败了,这个事务就处在一个中间状态,此时原子性被打破。

引起的另一个问题就是隔离性,这个事务的一部分提交了,另一部分未提交,此时该事务正常是不该被读取到的,但是提交成功的部分会被其他事务读到,此时就无法保证隔离性了。

另外就算是涉及多个节点的操作都是成功的,理论上来说也是无法保证隔离性的。因为假设A事务的一个节点先commit成功,其他的节点后commit成功,而此时B事务在读取的时候可能会读取到了A事务最早commit成功的那部分内容,却没有读到后来commit成功的内容,此时依然无法保证隔离性。

更本质一点的原因是MySQL的事务都是每个实例维护自身的事务ID,而基于MySQL集群的分布式方案没有一个全局的事务ID来标识每个MySQL实例上的事务以及全局事务的元信息的管理,所以无法做到严格的分布式事务语义。

但实际上绝大多数业务对这个需求未必那么强烈,因为绝大多数的业务逻辑都是可以拆分的,拆成一个个只落在一个分库里的操作在绝大多数场景下是完全可行的,而且拆分完以后也会更可控,所以这个问题在我们支撑业务的过程中也不是一个特别大的问题。

生产环境监控很关键

在实际生产环境中有很多方面都非常重要,高可用高可靠可扩展等,但是除了这些之外还有一个非常关键的是监控。

一个再健壮再牛x的系统都需要配备完善的监控系统,监控系统是生产环境中非常重要的一道防线,没有监控的系统就像是在裸奔,线上突发状况很多完善的监控系统可以做到第一时间发现问题及时定位以及解决问题。

物理机监控

我们在生产环境中会对系统所在物理机进行监控,京东有一个专门的物理机监控系统,可以监控包括CPU、内存、网卡、TCP连接数、磁盘使用情况、机器load等很多基础指标,针对这些指标可以设置相应的报警阈值,当超过一定阈值时会以邮件及短信的方式报警。

存活监控

但物理机的监控对于具体的系统的来说是远远不够的,我们还需要关注很多系统本身的信息,首先要有存活监控,这是最基本的。一个系统在线上运行的时候服务本身宕掉一定要求是可以第一时间监控到的。

但除了物理机监控以外,还有一个非常关键的是存活监控。系统的一切前提是可以活着,我们在每个模块都会提供相应的http接口,接入公司的统一监控平台,一旦有异常统一监控平台会及时通知相应的负责人。

系统内部状态可视化监控

除了活下来以后,如何活得更好也是很关键的,所以我们还有专门针对分布式MySQL集群的JMonitor系统,该系统会整合各个模块的内部详细状态信息,包括慢查询、用户访问情况以及数据分布情况等。

一句话一个稳定健壮的系统一定要配备相应的完善的监控系统。今天我的分享就是这些,主要就是介绍一些分布式MySQL的相关方案以及京东是怎么做的,讨论了一下分布式事务的问题,最后是一小部分生产实践经验,谢谢大家。

Q&A

Q1:请介绍下分布式事务保证数据最终一致性的具体方案例子。

主要看这条SQL具体是做什么的,如果是抽数据,就正常抽就可以了。如果有阻塞基本都是因为在MySQL端因为锁冲突等原因造成阻塞,最终可能是这个事务被abort掉或者最终抢到锁成功做完了这个事务。

Q2:分布式事务如何支持,现在可以支持多大规模的集群。

基于Mysql的分布式集群方案无法保证严格的分布式事务语义,但是在实际使用的时候看业务情况,如果事务之间不怎么冲突的情况下也是ok的,如果可以改成只涉及一个分库的情况下那就绕开分布式事务的问题了。另外支持的集群,我们其实是根据业务来划分资源的,目前整体资源不能说特别大,千台规模。

Q3:JProxy是否可以支持所有复杂sql查询,主要是夸库的关联查询,具体内部逻辑可否介绍下?

我们目前不支持夸库关联查询,从业务层面来解决。因为大表之间分库以后如果要支持跨库关联查询的话,作为一个OLTP系统在实际生产环境估计就没法用了。

Q4:请介绍下MySQL实际应用中主从复制的方案,以及主从的数据差异会在什么程度,谢谢!

这个其实更多的是主从之间关注的问题,一般会采用基于mix的模式。另外主从差异这个不同业务不一样,加上严格的监控,正常访问的情况下一般不会出现延迟,但是如果涉及到业务倒数据或者突增的访问量可能会引起延迟,所以这个不太好参考,如果有异常我们都会第一时间及时介入处理。

Q5:长时间SQL不会造成堵塞吗?

主要看这条SQL具体是做什么的,如果是抽数据,就正常抽就可以了。如果有阻塞基本都是因为在MySQL端因为锁冲突等原因造成阻塞,最终可能是这个事务被abort掉或者最终抢到锁成功做完了这个事务。

Q6:请介绍一下JTransfers的工作机制,以及实现过程中最难的部分。

迁移确实是比较刺手的一件事情,要考虑的细节很多。大体的步骤是:我们提交迁移计划,指定什么时间开始迁移,到时间点以后JTransfer就会自动迁移。JTransfer一开始是dump源分库的数据,然后将这些数据恢复到目标实例上,但是在这个期间业务是正常访问的,需要将增量数据迁移完,所以会有追增量过程。当增量追到一定程度,我们会阻塞这个库的访问,最后将剩余的少量数据迁移完。因为最后剩余数据量不多的时候,阻塞过程其实很短暂,所以对业务影响非常小。

最难的部分是:整个迁移过程中的路由变更,要保证路由变更的过程中数据不能写花,且变更以后的路由要准确的推送到JProxy中,由JManager和多个JProxy之间在变更路由的时候采用类似两阶段提交的协议,从而保证路由的变更是正确的。

Q7:可以分享一下JProxy的并发性能优化,以及JProxy中间状态的异常与恢复机制吗?谢谢!

并发性能优化我们主要是通过采用基于事件驱动的网络模型,这种方式的特点是避免上下文切换避免锁的开销,但是代价的话刚才也说了需要考虑得非常周全,把一个上下文切成很多片段,不太符合人类思维。

JProxy中间件状态的异常与恢复机制这个我不是太理解什么含义哈,我的理解是如果jproxy运行过程中访问出异常了怎么处理,如果是某个连接过来的sql出了问题我们的做法是将整个连接涉及到的资源都关闭,把该次查询涉及到的前后端资源清理干净,这样就不会影响到其他客户端的访问。正常来说不应该出现这种情况,所以也需要完善的日志信息以及监控信息。

京东价格监控封神实战:Scrapy+Redis分布式部署,10万商品5分钟抓取,附完整预警源码 items.py这套Scrapy+Redis分布式价格监控系统,核心不是“爬得快”,而是“稳定、实时、实用”——10万商品5分钟抓取解决了“海量数据”问题,Redis分布式调度解决了“高可用”问题,多渠道预警解决了“实时性”问题,真正帮开发者从繁琐的手动监控中解放出来。 阅读详情

相关推荐

曾很火的开源项目:腾讯,MySQL分布式解决方案,你看过没

前言 TenDB Cluster是腾讯游戏CROS DBA团队提供的MySQL分布式关系型数据库解决方案,主要包括兼容MySQL协议、透明分库分表、负载均衡、高可用、在线扩展等特点。业务开发可以仅专注于业务逻辑的开发和运营,无需编写数据分片逻辑,在海量用户并发情况下也无须关心DB存储层的负载压力。(开源地址见文末) 架构介绍 TenDB Cluster主要有三个模块:接入层TSpider,存储层TenDB,控制层Tdbctl。 架构图如下: TSpider是TenDB Cluster集群的接入层。T

程序媛小琬的博客 847

转载自infoq:MYSQL的集群方案

分布式MySQL集群方案的探索与思考 2016-04-29张成远 “本文整理自ArchSummit微信大讲堂张成远线上群分享内容 背景 数据库作为一个非常基础的系统,任何一家互联网公司都会使用,数据库产品也很多,有Oracle、SQL Server、MySQL、PostgeSQL、MariaDB等,像SQLServer/Oracle这类数据库在初期可以帮业务搞定很多棘手...

weixin_30902675的博客 307

京东完美编译MySQL Group Replication官方文档中文版

MySQL Group Replication(简称MGR)是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决方案。MySQL组复制提供了高可用、高扩展、高可靠的MySQL集群服务

太厉害了!阿里大牛就这样轻轻松松的把mysql给你讲清楚(基础+优化+架构)

爱因斯坦说过“耐心和恒心总会得到报酬的”,我也一直把这句话当做自己的座右铭,这句箴言在今年也彻底在“我”身上实现了。 每一个程序员都拥有一座大厂梦,我也不例外,去年面试阿里,竟然被MySQL问倒了,很多相关性的问题都没有答上来,才2面就凉凉了。为面试做了很多准备,收集很多关于MySQL面试题 MySQL有哪些特性? 使用C和C++编写,并使用了多种编译器进行测试,保证源代码的可移植性 支持AIX、FreeBSD、HP-UX、Linux、MacOS、Novell Netware、OpenBS...

Java架构师联盟 552

初识数据结构之入门必懂——线性表(顺序表)

本文将介绍数据结构中的线性表与线性表中最简单的结构——顺序表

m0_64705485的博客 904

STM32F407 CubeMX UART DMA高效解析BNO085九轴数据

本文详细介绍了如何在STM32F407平台上使用CubeMX配置UART和DMA高效解析BNO085九轴传感器数据。通过DMA循环接收机制实现低CPU占用的实时数据采集,并分享数据解析技巧、错误处理及实战调试经验,为嵌入式开发者提供完整解决方案。

o4p5q6r7s的博客 234

如何用Vitess打造高性能MySQL集群:免费开源的完整指南 [特殊字符]

Vitess 是一个基于 MySQL 的云原生水平扩展分布式数据库系统,能够通过通用分片实现无限扩展。它让应用代码和数据库查询无需关心数据如何分布到多个数据库服务器上,甚至可以随着需求增长拆分和合并分片,原子切换步骤仅需几秒钟。 ## 📊 Vitess 与传统数据库的核心差异 Vitess 巧妙地平衡了关系型数据库和 NoSQL 的优势,解决了传统 MySQL 在大规模场景下的扩展性痛点。

gitblog_00075的博客 837

实战指南 | IC模拟版图设计从零到精通,手把手带你掌握EDA工具与GDSII输出

本文提供了一份从零开始的IC模拟版图设计实战指南。详细介绍了如何搭建Linux环境、安装Cadence Virtuoso等EDA工具,并深入解析了PDK设计规则。通过手把手绘制CMOS反相器版图的实例,系统讲解了版图绘制、DRC/LVS验证、寄生参数提取、匹配设计以及ESD防护等核心技能,最终指导如何正确生成交付芯片制造厂的标准GDSII文件,帮助读者掌握完整的模拟版图设计流程。

weixin_29214691的博客 389

分布式专题(9)之Mysql高可用方案

数据库,应该是一个应用当中最为核心的价值所在,也是开发过程中必须熟练掌握的工具。之前我们就学习过很多对MySQL的调优。但是随着现在互联网应用越来越大,数据库会频繁的成为整个应用的性能瓶颈。我们经常使用的MySQL数据库,也就不断面临数据量太大、数据访问太频繁、数据读写速度太快等一系列的问题。而传统的这些调优方式,在真正面对海量数据冲击时,往往就会显得很无力。因此,现在互联网对于数据库的使用也越来越小心谨慎。例如添加Redis缓存、增加MQ进行流量削峰等。

jokeMqc的博客 2328

win10离线安装.NetFrameWork3.5出现0x800F081F解决办法。

由于公司开发环境是内网,并且安装arcgis10.2又需要.NetFrameWork3.5的环境,安装.NetFrameWork3.5的又总是报错“0x800F081F”找不到源文件。折腾了两天总算解决了。 首先我们能在网上搜索到的教程,你一定看到过这样的教程,就是使用下面的命令来进行安装。 dism /online /Enable-Feature /Featu...

AIGIS的博客 1万+

C# 死锁:原理、诊断与解决方案深度解析

本文深入探讨了C#中的死锁问题,详细介绍了死锁的基本概念、形成机制、常见场景、诊断方法及解决方案。死锁通常发生在多线程环境下,当多个线程因争夺资源而互相等待时,导致程序无法继续执行。文章通过代码示例展示了常见的死锁场景,如锁的嵌套、同步上下文死锁和线程池死锁,并提供了使用Visual Studio、WinDbg等工具进行死锁诊断的方法。此外,文章还提出了多种预防和解决死锁的策略,包括保持锁顺序一致性、使用锁超时机制、避免同步阻塞异步代码以及使用更高级的同步原语。通过这些方法,开发者可以有效减少死锁的发生,提

记录学习的过程 1407

京东分布式MySQL集群方案介绍

背景 数据库作为一个非常基础的系统,任何一家互联网公司都会使用,数据库产品也很多,有Oracle、SQL Server 、MySQL、PostgeSQL、MariaDB等,像SQLServer/Oracle 这类数据库在初期可以帮业务搞定很多棘手的事情,我们可以花更多的精力在业务本身的发展上,但众所周知也得交不少钱。 涉及到钱的事情在公司发展壮大以后总是会回来重新审视这个事情的,在京东早期发展

631

第03章 Hermes Agent 核心原理

环境跑通之后,读者会很自然地想问:Hermes 的内部到底是怎么转起来的?为什么它能做到"越用越聪明"?长对话不会忘记上下文吗?这一章用尽量短的篇幅把核心原理讲清楚。理解原理不是为了纸上谈兵,而是为了在第7章实战时能判断"为什么 Hermes 这么响应"以及"我应该把哪类任务交给它"。

亢少军的博客 141

sqlserver 集群_分布式MySQL集群方案的探索与思考

“本文整理自ArchSummit微信大讲堂张成远线上群分享内容背景数据库作为一个非常基础的系统,任何一家互联网公司都会使用,数据库产品也很多,有Oracle、SQL Server 、MySQL、PostgeSQL、MariaDB等,像SQLServer/Oracle 这类数据库在初期可以帮业务搞定很多棘手的事情,我们可以花更多的精力在业务本身的发展上,但众所周知也得交不少钱。涉及到钱的事情在公司发...

weixin_39815600的博客 866

《FPGA DDR3权威实战:从基础到高速故障录波系统》专栏导览:从不知所措到心中有数

本文是一份DDR3实战指南,作者从自身学习经历出发,分享了一套循序渐进的DDR3应用路线图。专栏包含12篇文章,从基础配置(MIG IP核、AXI总线)、仿真测试到实际项目应用(功能测试、性能测试),最后深入原生MIG接口实战,通过一个高速故障录播系统案例完整展示DDR3开发流程。文章特别强调实践性,旨在帮助读者系统掌握DDR3开发技能,避免作者当年踩过的坑。每篇都配有优快云链接,适合FPGA开发者按顺序学习参考。

FPGA_小田老师的博客 331

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

分布式MySQL集群方案

背景 数据库作为一个非常基础的系统,任何一家互联网公司都会使用,数据库产品也很多,有Oracle、SQL Server 、MySQL、PostgeSQL、MariaDB等,像SQLServer/Oracle 这类数据库在初期可以帮业务搞定很多棘手的事情,我们可以花更多的精力在业务本身的发展上,但众所周知也得交...

weixin_34406086的博客 414

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

分布式MySQL集群方案的探索与思考

原文地址:http://www.infoq.com/cn/articles/exploration-of-distributed-mysql-cluster-scheme?utm_source=infoq&utm_medium=popular_widget&utm_campaign=popular_content_list&utm_content=interview 背景

杨春建的博客 2424

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

京东如何基于Vitess管理大型MySQL实例集群

本文根据dbaplus社群第203期线上分享整理而成讲师介绍王云博京东数据库高级研发工程师2014年加入京东,一直致力于数据库运维自动化的发展;2018年专注于京东弹性数据库研发、运维工...

架构师小秘圈 2029

京东MYSQL分布式数据库:集群系统技术交流

京东MYSQL分布式数据库:集群系统技术交流 本篇由京东秦波分享的有关京东Mysql分布式数据库集群建设技术,主要介绍了目前京东业务驱动和运维需求,在此基础上自主开发的蓝海豚分布式Mysql集群系统... 详细解读 和小伙伴们一起来吐槽

chengying332 1564

价值20k的文章:分布式MySQL集群方案的探索

首先分布式事务涉及到的一致性和CAP中一致性是两个概念,事务ACID属性中的一致性不涉及最终一致性,对于关系型数据库中事务的概念,我的理解都是强一致的(通过原子性和隔离型保证)。只有涉及到某一个节点(内容是相同的情况)多副本之间的复制问题才会涉及到弱一致性或者最终一致性(CAP中C)的问题。而分布式事务本身如果保证了原子性和隔离性,数据库层面就提供了一致性保证,其余的是应用逻辑层面保证。

weixin_71690375的博客 131

mysql百万数据使用es_日均5亿查询量的京东订单中心,为什么舍弃MySQL用ES?

京东到家订单中心系统业务中,无论是外部商家的订单生产,或是内部上下游系统的依赖,订单查询的调用量都非常大,造成了订单数据读多写少的情况。我们把订单数据存储在MySQL中,但显然只通过DB来支撑大量的查询是不可取的。同时对于一些复杂的查询,MySQL支持得不够友好,所以订单中心系统使用了Elasticsearch来承载订单查询的主要压力。Elasticsearch作为一款功能强大的分布式搜索引擎,支...

weixin_32123259的博客 710

MySQL集群&主备&主从&负载&中间件&分区分库分表

mba pmp cobar SQL92标准 galera Cluster galera for mysql percona Cluster mariadb Cluster caltlet xa分布式事务 非堆内存聚合计算 haproxy jvm 分区 分表 分库 分表分库

喝醉酒的小白 7451
上一篇: RocketMQ使用P2P(点对点)消息传送模式,生产端生产一个消息,消费端消费几乎同时收到两个相同消息
下一篇: Java 关键字volatile 与 synchronized 作用与区别
yufei_java
博客等级 码龄10年 18粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值