共计 9237 个字符,预计需要花费 24 分钟才能阅读完成。
昆仑分布式数据库应用 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 |
2 | Flush&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。
- COM_BINLOG_ACK
应用 kunlun-storage 的客户端库文件及其 mysql.h 头文件编译程序,而后调用 mysql_send_binlog_ack() 函数发送 ACK。kunlun-storage fullsync 性能应用此办法发送 ACK 给其主节点。 - SLAVE server_id CONSISTENT TO file_index offset SQL 语句
这种办法能够应用任何社区版 mysql 客户端库,kunlun-storage 的主节点能够正确处理该语句,把它当作确认 ACK。此办法特地适宜各种 binlog 存储组件。 - Kunlun-storage Fullsync 的状态变量
这些状态变量能够帮忙 DBA 察看 fullsync 的运行状况和性能,并且作为辅助调节 fullsync 配置参数的根据。其意义在表格中,都是简略的英语,置信大家都能看懂,因而不再翻译了。
status variable name | |
---|---|
fullsync_received_replica_acks | NO. of received replica acks |
fullsync_old_acks_received | NO. of received ACKs that are obsolete,i.e. an obsolete ACK ACKs a position already ACK’ed by previously received ACKs. |
fullsync_txns_acked | NO. of txns the replica ACK’ed |
fullsync_txns_fully_acked_before_wait | NO. 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_wait | NO. 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_acks | NO. 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_acks | NO. of txns timed out waiting for ACKs |
fullsync_txns_received_by_replica | NO. of txns received by the replica |
fullsync_relay_log_syncs | NO. of relay log syncs. |
fullsync_acks_sent_to_master | NO. of ACKs sent to master |
fullsync_num_txns_in_acked_group | set by a replica, NO. of txns flushed and fsync’ed corresponding to latest ACK |
fullsync_replica_skipped_old_trx_acks | NO. 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 node | fullsync_num_waiting_txns NO. of transactions currently waiting for ACKs on master node |
- Fullsync 配置参数
Kunlun-storage Fullsync 反对丰盛的配置参数让用户在性能、资源耗费和一致性方面获得适当的均衡。这些变量都是 MySQL 的全局变量,其意义和用法说明见上面的表格,都是简略的英语,置信大家都能看懂,因而不再翻译了。
Fullsync Variables | meanings |
---|---|
fullsync_consistency_level | At 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_level | When 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_bytes | Accumulate at least this many relay log bytes before fsync’ing the relay log and sending an ACK. |
fullsync_fsync_ack_least_txns | Accumulate at least this many event groups before fsync’ing the relay log and sending an ACK. |
fullsync_fsync_ack_wait_max_milli_secs | Replica 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_than | If a replica is this many milli-seconds later than the primary node, skip fsync’ing the relay log or sending ACKs. |
fullsync_warning_timeout | If a replica ACK arrives this many milli-seconds since the transaction started to wait for it, write a warning in error log. |
fullsync_timeout | If 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_acks | Whether 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_fullsync | Whether enable fullsync mechanism. |
disable_fullsync_on_slave_ack_timeout | Whether 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