热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MariaDBParallelReplication并行复制

官方文档:https:mariadb.comkbenmariadbparallel-replication从10.0.5版本开始,MariaDB开始支持并行复制MariaDB10.

官方文档: https://mariadb.com/kb/en/mariadb/parallel-replication


从10.0.5版本开始,MariaDB开始支持并行复制

MariaDB10.0的从服务器能并行的执行查询和复制操作,这篇文章将会解释是如何实现的和你可以做的调优。


注意:主从服务器上的 MariaDB 的版本必须是10.0.5和10.0.5的以后的版本,才能启用并行复制


Parallel replication overview -- 并行复制概述


MariaDB 的复制通过三步完成:

1.从服务的IO线程去主库上读取变更事件,并把读取的事件顺序放到relay log中

2.从服务器的SQL线程一次读取relay log中的一个事件

3.SQL线程依次应用relay log中的事件


MariaDB 10之前的版本中,第三步是通过SQL线程来执行的,这意味着,一次只能执行一个事件,复制本质上是单线程的。

MariaDB 10之后的版本中,第三步可以通过一组相互独立的复制线程,因为可以一次并行复制多个事件,提升了复制性能。


How to enable parallel slave -- 如何开启并行复制

在 my.cnf 指定 slave-parallel-threads = n 作为参数传递给MySQL.

并行复制也可以用于多源连接设置 "@@connection_name.slave-parallel-mode" 设置为 none, 即 set @@connection_name.slave-parallel-mode = none


slave_parallel_threads 的值决定了池中会有多少个工作线程会被创建用来在从服务器上执行并行复制事件

如果值为0,默认采用旧的复制方式(即slave的SQL线程来重放event事件)

通常来讲,如果值为非0,应该设置为多源主服务器链接数的至少两倍。一个连接用一个工作线程的意义不大,因为这不但会增加内部线程通讯(即SQL线程和工作线程之间的通讯)的负担,而且一个连接使用一个工作线程的时候,事件不能被并行复制。

slave_parallel_threads 的值可进行动态调整,即可在不重启MySQL的情况下,进行更改,但是更改的时候,所有的从库连接都要被停止。


What can be run in parallel  -- 如何运行并行复制


并行复制的方式有哪些?

in-order 有序 和 out-of-order 无序两种方式

有序方式

并行执行事务,但是对commit顺序进行排序,以确保从库上事务提交和主库上事务提交顺序一致。只有那些被自动确认为不会引起冲突的事务才会被并行执行,也就是说,并行复制对应用来说,是完全透明的。


无序方式

无序意味着在从库上执行和提交事务的顺序跟主库可能不一致,也就是说,应用必须要具备容忍主从服务器上数据更新顺序不一致的问题,同时这种方式要求应用来确保事务之间的没有冲突。无序方式只在GTID模式和应用明确指定使用无序的时候才会被使用, 复制域属于gtid的一部分。


Conservative mode of in-order parallel -- 乐观并行复制模式(optimistic)

Optimistic模式,从MariaDB 10.1.3版本开始支持。


这种模式提供了大量的并行应用slave,同时从应用程序的角度来看,仍然保留精确的事务语义。

开启使用配置选项 --slave-parallel-mode=optimistic.


任何事务DML(插入/更新/删除)可以并行运行,达到限制@@slave_domain_parallel_threads。这可能在slave导致冲突,如果两个交易试图修改同一行,检测到任何这样的冲突,并且两个事务的后者被回滚,允许前者继续, 一旦前者已经完成,后者的事务重新尝试。


Optimistic模式适用于这种方式,因为服务器会发生一些冲突乐观的假定,这额外的工作花了回滚后重新事务冲突时从运行大部分交易获得合理的并行。


有一些启发,试图避免不必要的冲突,如果在master上一个事务执行了一个行锁等待。它不会再并行运行slave,

事务也可以明确在master上标识为潜在的冲突,通过设置变量@@skip_parallel_replication。这种启发式可能在以后加入MariaDB版本(现在还不支持)

这是接下来的选项--slave-parallel-mode 叫 侵略性"aggressive"模式。当这些启发式呗禁用,允许更多的交易将被应用在并行。


非事务DML和DDL不安全的乐观应用并行,因为它不能再冲突的情况下,回滚。因此,在乐观的模式下,非事务性的(如MyISAM)更新不适用于并行或者早期的事件。(不过,可能适用于并联一个MyISAM更新后会更新),DDL语句不适用于任何其他事务,或早或晚。


不同的事务类型可以在mysqlbinlog输出确定,例如:

#150324 13:06:26 server id 1  end_log_pos 6881 GTID 0-1-42 ddl

...

#150324 13:06:26 server id 1  end_log_pos 7816 GTID 0-1-47

...

#150324 13:06:26 server id 1  end_log_pos 8177  GTID 0-1-49 trans

/*!100101 SET @@session.skip_parallel_replication=1*//*!*/;

...

#150324 13:06:26 server id 1  end_log_pos 9836 GTID 0-1-59 trans waited


gtid 0-1-42标明DDL。gtid 0-1-47被标记为非事务DML。而gtid 0-1-49是事务性的DML("trans" 关键字),另外,gtid 0-1-49在master上运行@@ skip_parallel_replication,gtid 0-1-59是事务型的,在master上有一排等待DML锁。("waited" 关键字)。


Conservative mode of in-order parallel -- 保守并行复制(conservative)模式


默认是conservative模式,在10.0版本中唯一可用的模式,可以使用 --slave-parallel-mode=conservative 开启。

在conservative模式中,并行复制在master上使用"组提交“,以发现潜在的并行应用事件的slave,

在mater上如果两个事物提交在一组,他们都写进同一个commit id,此类事件的binlog一定不会互相冲突,他们可以计划安排由复制到运行在不同的线程中。


两个在主上单独提交的事务可能会发生冲突(如,修改同一个表的一行)。因此,应用第二个事务的worker不会立即开始。

但是等到第一个事务开始提交步骤之后,在这一点上,启动第二个事务是安全的,因为它不能再扰乱第一个的执行。


这是mysqlbinlog输出的一个例子,显示gtid events都标有commit id,gtid 0-1-47 没有提交ID,不能并行运行,

gtid 0-1-48和0-1-49有相同的commit id 630,可以在另一个slave上并行复制。


binlog信息如下:

#150324 12:54:24 server id 1  end_log_pos 20052 GTID 0-1-47 trans

...

#150324 12:54:24 server id 1  end_log_pos 20212 GTID 0-1-48 cid=630 trans

...

#150324 12:54:24 server id 1  end_log_pos 20372 GTID 0-1-49 cid=630 trans


在任何一种情况下,当两个事务到达低级别提交的点,并确定提交顺序时,这两个提交以相同的顺序发生在mater上,这样操作对应用程序是透明的。

如果在一个组提交中提交了更多的事务,则可以高度地增加对slave的并行复制的机会。

这个可以调整使用binlog_commit_wait_count和binlog_commit_wait_usec变量,例如,如果应用程序在master可以容忍额外延迟50毫秒,你可以设置binlog_commit_wait_usec = 50000和binlog_commit_wait_count = 20,在一个可用的时间,并行复制可获得高达20的事务处理。

不过小心不要设置binlog_commit_wait_usec太高,因为这可能导致应用程序会放缓,运行大量的串行小事务一个接一个的。


请注意:在master上即使没有组提交的并行性,仍然有个机会,提升并行速度。

由于不同事务的实际提交步骤可以运行。在slave上特别有效,binlog开启(log_slave_updates=1)

甚至如果slave配置崩溃修复安全(sync_binlog=1 and innodb_flush_log_at_trx_commit=1),这种组提交可能在slave上


在--slave-parallel-mode=minimal模式下,仅仅事务提交步骤被并行应用。所有其他事务复制都是连续发生的。


Out-of-order parallel -- 无序并行复制

无序并行复制只使用在GTID模式下,当使用不同的复制域GTID时,复制域是有DBA/应用程序中使用的变量gtid_domain_id.

在并行复制中有两个事务gtids,不同domain_id定于不同的线程,并允许执行完全独立于此,它是应用程序的责任,只为那些真正独立的交易设置不同的domain_ids,

并保证不会相互冲突,应用程序还必须正常工作,即使事务中有不同的domain_id,被视为不同的顺序呢,在slave和master之间,或者在不同的slave中。


由于应用程序可以显式地提供更多并行运行事务的机会。而不是服务器可以自动确定的,出于事务并行复制的顺序并行复制可能自动自己确定自己


一个简单但有效的用法是运行单独的复制域中的长时间运行的语句,如“更改表”。这允许复制其他事务继续进行不间断:

SET SESSION gtid_domain_id=1

ALTER TABLE t ADD INDEX myidx(b)

SET SESSION gtid_domain_id=0


通常,一个长时间运行的ALTER TABLE语句或者 其他查询,将会停止所有后面的事务。会引发slave落后于master至少需要很长的时间去执行这个运行时间很长的查询。

通过无序并行复制,设置复制domain id。是可以避免的。当运行ALTER TABLE时,DBA/应用程序必须确保没有冲突的事务将被复制。


出于无序并行复制的另一个常见的条件,是于多源复制有关的。假设我们有两个不同的master M1 M2,我们利用多源复制S1作为一个M1和M2的slave,S1将收到从M2事件并行M1接收事件。

如果我们现在有三分之一级的奴隶,从S1 S2复制master,我们希望S2也能够应用事件起源于M1与M2平行事件起源于。这可以从顺序并行复制来实现,通过设置在M1和M2 gtid_domain_id不同。



请注意,没有什么特殊限制,可以使用无序的并行复制,这样的操作可以在同一个database/schema,甚至在同一个table中,唯一的限制是,操作必须不冲突,这是他们必须能够以任何顺序应用,并最终获得相同的结果。



当使用了无序并行复制时,

当前slave position就是 master 位置

在master binlog在任何一个时间,成为多维 - 每个复制域可以达到一个不同的点,

当前的position可以在gtid_slave_pos变量看到。当slave被停止、重启、或者切换复制从不同master 使用CHANGE MASTER时,MariaDB自动处理重启每个复制域在binlog适当点。


当--slave-parallel-mode=minimal(或none)模式,无序并行复制是关闭的。


Checking worker thread status in SHOW PROCESSLIST -- 检查显示列表的线程状态

在show processlist中,工作线程将会列出"system user",他们的状态将显示他们目前正在进行的查询,或者它可以显示其中一个:


"Waiting for work from main SQL threads". "等待工作从主要的SQL线程"。

这意味着工作线程空闲,没有工作可用于它的时刻。

"Waiting for prior transaction to start commit before starting next transaction". "等待之前的交易开始下一次交易开始之前提交"。

这意味着,前一批提交的事务在主必须完成第一个。这个工作线程在等待它发生之前,它可以开始工作在下面的一批。

This worker thread is waiting for that to happen before it can start working on the following batch.

"Waiting for prior transaction to commit". ”等待优先交易提交“。

这意味着事务已被工作线程执行了,为了确保订单提交,工作线程等待提交,知道上一次事务准备在它之前提交为止。



Expected performance gain -- 性能预期测试的文章


这里有一篇关于使用并行复制时,改进后高达10倍的性能文章

http://kristiannielsen.livejournal.com/18435.html。


slave-parallel-max-queued配置参数:

变量slave_parallel_max_queued是唯一有意义的,前提并行复制技术被使用(slave_parallel_threads参数大于0时),当并行复制被使用时, SQL线程会预读relay-log中的event,队列时间放在内存中,在并行复制中,同时寻找并行执行事件的机会。@@slave_parallel_max_queued变量设置为SQL 线程将在预读多少内存限制的日志,寻找这样的机会。每个线程是有限制的,因此,这次预读的值是设置@@slave_parallel_threads变量值得来的


如果这个值设置的太高,并且slave落后于master落得太远(如千兆字节的binlog),然后SQL线程可以快速读,填补大量内存的binlog事件比工作线程消耗的更快


另一方面,如果值定的太低,SQL线程可能没有足够的空间来保持足够的事件队列忙的线程,这可能降低性能。


注意,@@slave_parallel_max_queued不是硬性限制,因为binlog事件当前执行总是需要保存在内存中,

例如,每个工作者线程至少有两个事件总是可以在内存中排队,不管slave_parallel_threads是多


通常,slave_parallel_threads应该设置的足够大,SQL线程利用所有可能的并行性可以预读的足够远的binlog,在正常操作中,slave将不希望落后太远,因此不会将大量数据队列有必要的放在内存中的。所以slave_parallel_threads可能设置的相当高(如几百KB)不限制吞吐量。它应该被设置的足够低,slave_parallel_threads * slave_parallel_max_queued 不会造成服务器内存不足。


slave_domain_parallel_threads配置参数:

在所有多源主连接中共享复制工作线程池,在所有可以在并行使用顺序复制的复制域中。

如果一个主连接或者一个复制域 当前正在执行处理一个长时间的查询,可能它将分配在池中的所有工作线程,只能等待让他们长时间运行的查询完成。

拖延任何master主库连接或者复制域,这将不得不等待复制域工作线程变得空闲。


可以通过slave_domain_parallel_threads变量设置的值避免低于slave_parallel_threads设置的值,

当设置不等于0时,一个主连接中的每个复制域都可以保留至多一个时间段的多个线程,

其余的,达到slave_parallel_threads参数的值,在并行复制中无其他主连接或者复制域去使用。


slave_domain_parallel_threads变量是可以动态修改的,可以在不重启服务的情况下更改。所有的slave必须停止掉更改。


本文出自 “会飞的蚂蚁” 博客,谢绝转载!

MariaDB Parallel Replication 并行复制


推荐阅读
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 基于PgpoolII的PostgreSQL集群安装与配置教程
    本文介绍了基于PgpoolII的PostgreSQL集群的安装与配置教程。Pgpool-II是一个位于PostgreSQL服务器和PostgreSQL数据库客户端之间的中间件,提供了连接池、复制、负载均衡、缓存、看门狗、限制链接等功能,可以用于搭建高可用的PostgreSQL集群。文章详细介绍了通过yum安装Pgpool-II的步骤,并提供了相关的官方参考地址。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 本文详细介绍了MySQL表分区的创建、增加和删除方法,包括查看分区数据量和全库数据量的方法。欢迎大家阅读并给予点评。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • React基础篇一 - JSX语法扩展与使用
    本文介绍了React基础篇一中的JSX语法扩展与使用。JSX是一种JavaScript的语法扩展,用于描述React中的用户界面。文章详细介绍了在JSX中使用表达式的方法,并给出了一个示例代码。最后,提到了JSX在编译后会被转化为普通的JavaScript对象。 ... [详细]
  • 如何在php文件中添加图片?
    本文详细解答了如何在php文件中添加图片的问题,包括插入图片的代码、使用PHPword在载入模板中插入图片的方法,以及使用gd库生成不同类型的图像文件的示例。同时还介绍了如何生成一个正方形文件的步骤。希望对大家有所帮助。 ... [详细]
  • Asp.net Mvc Framework 七 (Filter及其执行顺序) 的应用示例
    本文介绍了在Asp.net Mvc中应用Filter功能进行登录判断、用户权限控制、输出缓存、防盗链、防蜘蛛、本地化设置等操作的示例,并解释了Filter的执行顺序。通过示例代码,详细说明了如何使用Filter来实现这些功能。 ... [详细]
author-avatar
大帅哥明日夜
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有