昆仑分布式数据库应用MySQL做存储节点,称为kunlun-storage。Kunlun-storage目前最新版本基于percona-mysql-8.0.26开发,在此社区版本根底上,咱们补充了MySQL的XA事务和binlog 复制方面的容错和数据一致性破绽,减少了kunlun数据库集群须要的若干性能,并且加强了其性能。咱们也始终在合并上游版本,继续会集MySQL社区的最新成绩到kunlun-storage中。

在Kunlun-storage Fullsync机制开发实现之前,咱们始终在应用MySQL Group Replication(MGR)实现存储集群高可用。为了实现更好的数据写入性能包含更高的吞吐量和更短的延时,以及升高对存储系统和网络带宽的耗费,并且在高可用方面实现更加灵便的策略,咱们在kunlun-storage中设计并开发了Fullsync高可用机制。

Kunlun-storage Fullsync性能简介

Kunlun-storage Fullsync详情和原理

昆仑数据库的Fullsync机制是一种存储集群的高可用机制,它用于确保一个存储集群在产生节点故障、网络分区等问题时,该集群中存在可用的备机含有所有向用户确认提交胜利的事务的binlog,以便能够按需选举出新的主节点,确保集群继续能够写入,实现高可用。

昆仑数据库的Fullsync机制基于MySQL久经考验的Row Based Replication(RBR)binlog复制机制,实现了主备复制的强同步,也就是确保主节点上提交的每一笔事务 --- 包含显式一般事务(即begin 。。。Commit),autocommit的update/delete/insert语句,以及XA事务 --- 在实现外部的事务提交流程(即engine log和binlog flush&sync和engine commit 这三个阶段)之后,继续期待直到收到了足够数量的备机的确认(ACK)之后,才向客户端(在昆仑数据库中就是计算节点)确认这个事务胜利提交。

一个ACK是一个binlog文件标识和偏移值的组合,它代表的是这个地位之前的binlog都曾经被这个备机收到并且长久存储(刷盘)。这样,所有那些在主节点的binlog文件中其binlog存储在此地位之前的事务都失去了确认,它们的提交操作就都能够返回胜利状态给客户端了。

一个备机发送该ACK是向其主节点确认收到并长久化(刷盘)了一组事务的binlog到其relay log文件中。只有主节点收到这个确认,才向客户端返回事务提交胜利的确认状态,客户端收到此后果后能力发送下一条SQL语句给昆仑数据库。只有向客户端返回事务胜利提交(或prepare),昆仑分布式数据库才有任务保障这样的事务的改变不失落(即ACID的D,Durability)。

Kunlun-storage Fullsync的前提条件

Kunlun-storage Fullsync机制须要一组特定的参数组合能力失常工作。Kunlun-storage自带的参数配置模版文件中含有通过咱们开发团队调优之后的参数设置,其中蕴含了fullsync性能须要的参数设置。

Kunlun数据库集群的所有存储节点实例都是应用其自带的参数模版创立的。具体来说包含一下参数:

  • gtid_mode=on, enforce_gtid_consistency=1,log_slave_updates=ON
  • binlog_format=row, i.e. 应用Row based replication
  • 所有主备节点都应用binlog
  • 会话都应用binlog,即 sql_log_bin=true。如果把一个会话的 sql_log_bin设置为false则此会话中fullsync机制不工作然而其余会话中fullsync依然工作。
  • enable_fullsync = ON 关上fullsync全局开关
  • thread_handling=2或者0, 即kunlun-storage的fullsync机制实用于线程池(thread_handling=2)以及每个线程解决一个事务(thread_handling=0)的状况。

Kunlun-storage Fullsync的功能设计与实现

1. 主节点

kunlun-storage的fullsync机制是一种after-commit的同步模式。在解决用户会话thd的工作线程thr 实现事务T提交或者prepare(XA prepare)并且还未向客户端确认胜利(即发送OK包)之前,主节点查看事务T的binlog是否曾经收到了足够数量的备机的ACK(备机的ACK 确认收到若干个事务的binlog) --- 此条件称为开释条件。

Fullsync_consistency_level定义了主节点须要让每个事务期待多少个备机的ack,如果是0就不期待任何ack;如果大于0则期待这么多个备机的ack。

在昆仑数据库集群中,clustermgr会依据集群节点数量为每个master节点设置正当的Fullsync_consistency_level,通常的设定办法是对于一个2*n+1个节点的storage shard,那么设置Fullsync_consistency_level=n,这样就达到了简略少数,所以同时有n个节点隐没的状况下,集群依然能够失常写入。clustermgr也能够反对其余策略,比方要求所有备机全副确认等。

如果开释条件满足那么thr间接返回胜利状态给客户端并且实现本次申请解决,否则工作线程thr就把会话对象thd放到fullsync ack期待队列,而后去解决其余连贯中收到的申请。

主节点收到ACK后会对期待队列中的会话做开释条件查看,满足开释条件条件的会话会被开释,也就是返回胜利状态给客户端。在期待备机ACK的过程中,用户回话并不占用工作线程。

如果超时(fullsync_timeout)未收到足够的ack来开释一个期待的会话时,kunlun-storage有两种策略,由全局变量disable_fullsync_on_slave_ack_timeout来管制:

A. 如果disable_fullsync_on_slave_ack_timeout=1,那么fullsync会主动进化为异步。这样后续期待的事务将不再做fullsync期待。当主节点再次收到备机ack后,会主动启用fullsync机制。

B. 如果disable_fullsync_on_slave_ack_timeout=0,那么fullsync期待超时的会话,会返回谬误(谬误号9000) 给客户端,对于昆仑数据库集群来说,就是计算节点收到了这个谬误,会触发主备切换。

如果主节点宕机时有某个事务T没有收到任何备机的ack,导致切换后新的主节点短少原来曾经在旧主机M0上 提交的T事务的binlog,并且这个老主节点M0随后重新加入集群, kunlun-storage会对M0做flashback(闪回),把T的改变及其binlog从实例的存储引擎(innodb)和binlog文件中去掉。

因为T并没有返回给客户端所以昆仑数据库并没有向客户端承诺T提交胜利了,因而咱们齐全能够把T闪回,并没有影响事务的durability。

2. 备节点

备机收到事件组(event group,即binlog事务,包含一般显式事务,XA事务第一阶段,XA事务第二阶段,DDL语句,autocommit语句这几种类型。下文简称EG)的终止binlog事件(XID_EVENT, XA_PREPARE_LOG_EVENT或者DDL事务)后,它会决定是否须要把收到的若干个EG写到relay log文件并且刷到长久存储系统中(即flush&fsync relay log),而后发送ACK给主节点来确认长久化了这些收到的EG。

这个决定基于最小化资源耗费和最优化性能来做出 --- 如果备机收到了足够多的EG(配置参数:fullsync_fsync_ack_least_txns)或者足够量的binlog(配置参数:fullsync_fsync_ack_least_event_bytes) ,或者太久没有发送ACK了( fullsync_fsync_ack_wait_max_milli_secs), 他就会flush&fsync relay log而后发送ACK。

一个ACK蕴含这些信息:备机的server_id, 落盘的最初一个EG在主节点binlog中的终止地位(文件编号和偏移值)。主节点收到一个备机的ACK后就能够确信这个备机收到并长久存储了ACK地位之前的所有EG。

应用fullsync_relaylog_fsync_ack_level 全局变量来管制一个备机节点的Fullsync机制在flush&fsync relay log和发送ACK的行为,其含意如下:

fullsync_relaylog_fsync_ack_level备机行为
0不flush或者fsync relay log也不发送ACK
1不flush或者fsync relay log也不发送ACK
2Flush&fsync relay log后发送ACK

在主节点上关上 log_fullsync_replica_acks 能够在mysqld运行日志中记录每一个收到的ACK,这个性能仅仅用于调试备机ACK机制,在生产零碎中千万不要关上否则会重大影响性能。

备机有两种办法发送ACK给主节点,这两种办法都要求备机应用mysql客户端库连贯主节点,这样每个备节点有两个连贯连到主节点,一个是备机的IO线程的连贯,另一个是备机发送ACK的连贯。在此连贯中备机发送kunlun-storage特有的COM_BINLOG_ACK命令或者发送kunlun-storage能够了解的SQL语句,前者性能更好,然而后者能够让各种第三方binlog存储组件向主节点发送ACK。

  1. COM_BINLOG_ACK
    应用kunlun-storage的客户端库文件及其mysql.h 头文件编译程序,而后调用 mysql_send_binlog_ack() 函数发送ACK。kunlun-storage fullsync性能应用此办法发送ACK给其主节点。
  2. SLAVE server_id CONSISTENT TO file_index offset SQL 语句
    这种办法能够应用任何社区版mysql客户端库,kunlun-storage的主节点能够正确处理该语句,把它当作确认ACK。此办法特地适宜各种binlog存储组件。
  3. Kunlun-storage Fullsync的状态变量
    这些状态变量能够帮忙DBA察看fullsync的运行状况和性能,并且作为辅助调节fullsync配置参数的根据。其意义在表格中,都是简略的英语,置信大家都能看懂,因而不再翻译了。
status variable name
fullsync_received_replica_acksNO. of received replica acks
fullsync_old_acks_receivedNO. of received ACKs that are obsolete,i.e. an obsolete ACK ACKs a position already ACK'ed by previously received ACKs.
fullsync_txns_ackedNO. of txns the replica ACK'ed
fullsync_txns_fully_acked_before_waitNO. of txns pre-ACK'ed before it starts to wait --- when the txn tries to wait for ack, its receives all needed ACKs from slaves
fullsync_txns_acked_before_waitNO. of txns partly ACK'ed before it starts to wait, when the txn tries to wait for ack, its receives part of all needed ACKs from slaves
fullsync_txns_long_wait_warnings_for_acksNO. of txns long wait warnings for ACKs. although the wait doesn't timeout, it's still long enough to trigger a fullsync warning.
fullsync_txns_timed_out_waiting_for_acksNO. of txns timed out waiting for ACKs
fullsync_txns_received_by_replicaNO. of txns received by the replica
fullsync_relay_log_syncsNO. of relay log syncs.
fullsync_acks_sent_to_masterNO. of ACKs sent to master
fullsync_num_txns_in_acked_groupset by a replica, NO. of txns flushed and fsync'ed corresponding to latest ACK
fullsync_replica_skipped_old_trx_acksNO. of times the replica skipped sending ACKs because received txns are too old
fullsync_replica_ack_upto_file and fullsync_replica_ack_upto_offset;fullsync replicas have ACKed upto this position(file and offset within master's binlog file).
fullsync_replica_fully_acked_upto_file; and fullsync_replica_fully_acked_upto_offset;fullsync replicas have fully ACKed upto this position(file and offset within master's binlog file).
fullsync_latest_recvd_trx_ts timestamp on master node of latest received transaction,it's the timestamp when the transaction on master node is flushed to its binlog file. it can be used to measure IO thread latency.fullsync_replica_ack_timedout whether the master node timed out waiting for replica acks
fullsync_effective whether fullsync is effective on this master or slave nodefullsync_num_waiting_txns NO. of transactions currently waiting for ACKs on master node
  1. Fullsync配置参数
    Kunlun-storage Fullsync反对丰盛的配置参数让用户在性能、资源耗费和一致性方面获得适当的均衡。这些变量都是MySQL的全局变量,其意义和用法说明见上面的表格,都是简略的英语,置信大家都能看懂,因而不再翻译了。
Fullsync Variablesmeanings
fullsync_consistency_levelAt end of transaction commit, whether and how to wait for fullsync replica ACKs before replying the client that a transaction has committed. 0: no wait; 99: wait for simple majority replicas; 100: wait for all replicas; [1, 98]: wait for this number of ACKs.
fullsync_relaylog_fsync_ack_levelWhen fullsync is enabled, how should the replica fsync relay log and/or reply an ACK to primary after it write its received event group(s) to relay log file.\t" "0: don't fsync or send ACK; 1: don't fsync but send ACK; 2: fsync and send ACK.
fullsync_fsync_ack_least_event_bytesAccumulate at least this many relay log bytes before fsync'ing the relay log and sending an ACK.
fullsync_fsync_ack_least_txnsAccumulate at least this many event groups before fsync'ing the relay log and sending an ACK.
fullsync_fsync_ack_wait_max_milli_secsReplica nodes wait for more event groups to arrive at most this many milli-seconds before fsync'ing the relay log and sending an ACK.
skip_fullsync_replica_acks_older_thanIf a replica is this many milli-seconds later than the primary node, skip fsync'ing the relay log or sending ACKs.
fullsync_warning_timeoutIf a replica ACK arrives this many milli-seconds since the transaction started to wait for it, write a warning in error log.
fullsync_timeoutIf a replica ACK doesn't arrive after this many milli-seconds since the transaction started to wait for it, return error to client and write an error in error log.
log_fullsync_replica_acksWhether log replica ACKs to mysqld error log. Note that when fullsync is enabled there can be a huge amount of such logs which are seldom used.
enable_fullsyncWhether enable fullsync mechanism.
disable_fullsync_on_slave_ack_timeoutWhether disable fullsync when replicas do not ACK in time and timeout happened, if this is false, then the primary node can't be written when it has no running replicas.

Kunlun-storage Fullsync的劣势

与MySQL的半同步(semisync)插件相比,kunlun-storage 的fullsync机制有如下劣势。

期待备机确认期间,客户端会话及其事务不占用工作线程。这样就能够防止大量工作线程阻塞期待备机的ACK,导致线程池为了解决来自其余客户端会话的继续大量到来的申请不得不启动更多的工作线程,耗费过多系统资源。

备机会汇集若干个事务的binlog后(可配置),才对relay log做fsync,确保binlog落盘。这样不仅能够防止备机断电或者其OS crash或者重启导致备机失落了最近的relay log的重大问题,还不会对存储设备造成微小的写入负载。达到了性能,延时和存储资源耗费之间的完满均衡。

Fullsync有灵便的配置能力,让用户在高可用性、数据强一致性和性能之间做出灵便的管制和取舍。

Fullsync提供丰盛的运行状态信息,不便DBA监控fullsync的运行时状态,为无效的fullsync相干配置提供残缺的信息

DBA能够配置主节点去期待若干个(可配置)备机返回ACK,从而达到更高的容错级别。比方对于某些高价值业务,DBA能够配置一主四备,让主节点为每个事务期待2个备机ACK。任何一个事务提交操作实现后在返回给客户端之前,必须期待收到两个备机的ACK,这个事务提交状态能力返回给客户端。

同时,DBA还能够配置一个备机的特定channel是否发送ACK,即便这个备机的fullsync_relaylog_fsync_ack_level为1或者2,达到灵便配置集群高可用架构的指标。

END

昆仑数据库是一个HTAP NewSQL分布式数据库管理系统,能够满足用户对海量关系数据的存储管理和利用的全方位需要。

利用开发者和DBA的应用昆仑数据库的体验与单机MySQL和单机PostgreSQL简直完全相同,因为首先昆仑数据库反对PostgreSQL和MySQL双协定,反对规范SQL:2011的 DML 语法和性能以及PostgreSQL和MySQL对规范 SQL的扩大。同时,昆仑数据库集群反对程度弹性扩容,数据主动拆分,分布式事务处理和分布式查询处理,强壮的容错容灾能力,欠缺直观的监测剖析告警能力,集群数据备份和复原等 罕用的DBA 数据管理和操作。所有这些性能无需任何利用零碎侧的编码工作,也无需DBA人工染指,不停服不影响业务失常运行。

昆仑数据库具备全面的OLAP 数据分析能力,通过了TPC-H和TPC-DS规范测试集,能够实时剖析最新的业务数据,帮忙用户发掘出数据的价值。昆仑数据库反对私有云和公有云环境的部署,能够与docker,k8s等云基础设施无缝合作,能够轻松搭建云数据库服务。

请拜访 http://www.zettadb.com/ 获取更多信息并且下载昆仑数据库软件、文档和材料。

KunlunDB我的项目已开源
【GitHub:】
https://github.com/zettadb
【Gitee:】
https://gitee.com/zettadb