Centos7 YUM安装Percona XtraDB 5.7

node1    10.0.3.111
node2    10.0.3.112
node3    10.0.3.113
注意:避免创建两个或任意偶数个节点集群,因为这可能会导致脑裂。

关闭selinux

sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

设置防火墙

确保以下端口未被防火墙阻止或其他软件使用。Percona XtraDB集群需要它们进行通信。

3306
4444
4567
4568

安装 node1

yum install -y http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
yum install -y Percona-XtraDB-Cluster-57
mkdir -p /data/app/mysql/xtradb/{data,logs}
touch /data/app/mysql/xtradb/logs/{data-slow.log,error.log}
chown mysql:mysql /data/app/mysql/xtradb -R
mysqld --initialize --datadir=/data/app/mysql/xtradb/data --user=mysql
mv /etc/my.cnf /etc/my.cnf_bak
mv /etc/percona-xtradb-cluster.cnf /etc/percona-xtradb-cluster.cnf_bak
vi /etc/my.cnf
[client]
port=3306
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysqld_safe]
socket=/var/lib/mysql/mysql.sock
nice=0
[mysqld]
server-id=111
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/lib/mysql/mysql.sock
port=3306
datadir=/data/app/mysql/xtradb/data/
log_error = /data/app/mysql/xtradb/logs/error.log
skip-external-locking
character-set-server=utf8
max_connections=10000
slow_query_log=1
slow_query_log_file=/data/app/mysql/xtradb/logs/data-slow.log
long_query_time=5
log_queries_not_using_indexes=1
bind-address=0.0.0.0
max_allowed_packet=1024M
myisam_recover_options=BACKUP
query_cache_limit=1M
query_cache_size=16M
expire_logs_days=10
log-bin-trust-function-creators=1
log-bin=bin-log
innodb_buffer_pool_size = 4G
sync_binlog=1
explicit_defaults_for_timestamp = 1
innodb_flush_method = O_DIRECT
disable_ssl
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.3.111,10.0.3.112,10.0.3.113
wsrep_slave_threads=16
wsrep_cluster_name=my_centos_cluster
wsrep_sst_method=xtrabackup-v2
wsrep_node_name=node1
wsrep_node_address=10.0.3.111
wsrep_sst_auth="sstuser:P@ssw0rd"
innodb_locks_unsafe_for_binlog=1
innodb_autoinc_lock_mode=2
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
systemctl start [email protected]
mysqladmin -uroot -p`cat /var/log/mysqld.log | grep 'temporary password' | awk '{print $NF}'` password 'P@ssw0rd'
mysql -uroot -p'P@ssw0rd'
mysql> CREATE USER 'sstuser'@'localhost' IDENTIFIED BY 'P@ssw0rd';
mysql> GRANT RELOAD, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost';
mysql> FLUSH PRIVILEGES;

安装 node2

yum install -y http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
yum install -y Percona-XtraDB-Cluster-57
mkdir -p /data/app/mysql/xtradb/{data,logs}
touch /data/app/mysql/xtradb/logs/{data-slow.log,error.log}
chown mysql:mysql /data/app/mysql/xtradb -R
mysqld --initialize --datadir=/data/app/mysql/xtradb/data --user=mysql
mv /etc/my.cnf /etc/my.cnf_bak
mv /etc/percona-xtradb-cluster.cnf /etc/percona-xtradb-cluster.cnf_bak
vi /etc/my.cnf
[client]
port=3306
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysqld_safe]
socket=/var/lib/mysql/mysql.sock
nice=0
[mysqld]
server-id=112
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/lib/mysql/mysql.sock
port=3306
datadir=/data/app/mysql/xtradb/data/
log_error = /data/app/mysql/xtradb/logs/error.log
skip-external-locking
character-set-server=utf8
max_connections=10000
slow_query_log=1
slow_query_log_file=/data/app/mysql/xtradb/logs/data-slow.log
long_query_time=5
log_queries_not_using_indexes=1
bind-address=0.0.0.0
max_allowed_packet=1024M
myisam_recover_options=BACKUP
query_cache_limit=1M
query_cache_size=16M
expire_logs_days=10
log-bin-trust-function-creators=1
log-bin=bin-log
innodb_buffer_pool_size = 4G
sync_binlog=1
explicit_defaults_for_timestamp = 1
innodb_flush_method = O_DIRECT
disable_ssl
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.3.111,10.0.3.112,10.0.3.113
wsrep_slave_threads=16
wsrep_cluster_name=my_centos_cluster
wsrep_sst_method=xtrabackup-v2
wsrep_node_name=node2
wsrep_node_address=10.0.3.112
wsrep_sst_auth="sstuser:P@ssw0rd"
innodb_locks_unsafe_for_binlog=1
innodb_autoinc_lock_mode=2
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
systemctl start mysql.service

安装 node3

yum install -y http://www.percona.com/downloads/percona-release/redhat/0.1-4/percona-release-0.1-4.noarch.rpm
yum install -y Percona-XtraDB-Cluster-57
mkdir -p /data/app/mysql/xtradb/{data,logs}
touch /data/app/mysql/xtradb/logs/{data-slow.log,error.log}
chown mysql:mysql /data/app/mysql/xtradb -R
mv /etc/my.cnf /etc/my.cnf_bak
mv /etc/percona-xtradb-cluster.cnf /etc/percona-xtradb-cluster.cnf_bak
vi /etc/my.cnf
[client]
port=3306
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysqld_safe]
socket=/var/lib/mysql/mysql.sock
nice=0
[mysqld]
server-id=113
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/lib/mysql/mysql.sock
port=3306
datadir=/data/app/mysql/xtradb/data/
log_error = /data/app/mysql/xtradb/logs/error.log
skip-external-locking
character-set-server=utf8
max_connections=10000
slow_query_log=1
slow_query_log_file=/data/app/mysql/xtradb/logs/data-slow.log
long_query_time=5
log_queries_not_using_indexes=1
bind-address=0.0.0.0
max_allowed_packet=1024M
myisam_recover_options=BACKUP
query_cache_limit=1M
query_cache_size=16M
expire_logs_days=10
log-bin-trust-function-creators=1
log-bin=bin-log
innodb_buffer_pool_size = 4G
sync_binlog=1
explicit_defaults_for_timestamp = 1
innodb_flush_method = O_DIRECT
disable_ssl
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://10.0.3.111,10.0.3.112,10.0.3.113
wsrep_slave_threads=16
wsrep_cluster_name=my_centos_cluster
wsrep_sst_method=xtrabackup-v2
wsrep_node_name=node3
wsrep_node_address=10.0.3.113
wsrep_sst_auth="sstuser:P@ssw0rd"
innodb_locks_unsafe_for_binlog=1
innodb_autoinc_lock_mode=2
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
systemctl start mysql.service

基于分布式框架Jepsen的X-Cluster正确性测试

一、概述

AliSQL X-Cluster(简称X-Cluster)是阿里巴巴数据库团队推出的兼容MySQL-5.7,提供数据强一致功能,支持全球部署的分布式数据库集群产品,其分布式核心组件X-Paxos是阿里巴巴数据库团队面向高性能、全球部署以及阿里业务特征等需求,实现高性能分布式强一致的Paxos独立基础库。Paxos算法作为分布式系统的基石,号称是最难理解的算法。Google的论文《Paxos made live》中说了下面一段话:

Paxos从理论到现实世界的实现之间有巨大的鸿沟,在真正实现一个Paxos的时候,往往需要对Paxos的经典理论做一些扩展,尤其是在实现一个高性能的Paxos的时候,扩展点更多,这往往会导致真正的Paxos实现都是基于一个未被证明的协议。

理论证明一个Paxos的实现,比实现这个Paxos还要难。因此一个成熟的Paxos实现很难独立产生,往往需要和一个系统结合在一起,通过一个或者多个系统来验证其可靠性和完备性。我们的愿景是希望提供一个经过实践检验的、高度成熟可靠的独立Paxos基础库。基于X-Paxos构建高可用、强一致、全球部署的分布式数据库集群X-Cluster。因此X-Cluster、X-Paxos的正确性验证就显得尤为重要。

Jepsen是一个开源的分布式一致性验证框架,可用于验证分布式数据库、分布式消息队列、分布式协调系统。Jepsen探索特定故障模式下分布式系统是否满足相应的一致性模型,其作者使用它验证过许多著名的分布式系统(etcd, CockroachDB,MongoDB,Galera,Percona,ZooKeeper …),号称没有一个能完整的通过其测试。Jepsen作者Kyle Kingsbury的博客展示了其验证过程以及一些思考分析,帮助这些分布式系统发现问题。

我们扩展了Jepsen框架以适应阿里的应用场景,并使用扩展之后的框架验证X-Cluster、X-Paxos的正确性。针对上十种场景和特性,设计了相应的测试用例予以验证,用例涵盖所有Jepsen验证过的分布式数据库系统的场景和特性,另外还设计了新的独有的测试用例,验证过程中周期性的注入分布式环境下的各种错误。验证结果表明,X-Cluster、X-Paxos鲁棒性非常强。

二、X-Cluster、X-Paxos简介

X-Cluster是阿里巴巴数据库团队推出的兼容MySQL-5.7,提供数据强一致功能,支持全球部署的分布式数据库集群产品。说到X-Cluster就不能不提其分布式核心,一致性协议。X-Paxos是阿里巴巴自主研发的一致性协议库,目标是填补市面上高性能、易接入的一致性协议库的空白。市面上已开源的一致性协议实现,都存在或性能不够,或功能上无法满足复杂的现实应用场景需求的问题。 有了X-Paxos,可基于它打造一套强一致的分布式系统,X-Cluster是第一个接入X-Paxos生态的重要产品,利用了X-Paxos实现了自动选主,日志同步,集群内数据强一致,在线集群配置变更等功能。同时X-CLuster基于MySQL生态,兼容最新版本的MySQL-5.7,集成了AliSQL过去的各种功能增强。 MySQL的用户可以零成本迁移到X-Cluster上。

未分类

上图展示的是一个部署三个实例的X-Cluster集群。X-Cluster是一个单点写入,多点可读的集群系统。在同一时刻,整个集群中至多会有一个Leader节点来承担数据写入的任务。相比多点写入,单点写入不需要处理数据集冲突的问题,可以达到更好的性能与吞吐率。

X-Cluster 的每个实例都是一个单进程的系统,X-Paxos被深度整合到了数据库内核之中,替换了原有的复制模块。集群节点之间的增量数据同步完全是通过X-Paxos来驱动,如何复制,从哪个点回放不再需要运维人员或者外部工具来介入。 X-Cluster为了追求最高的性能,利用MySQL的Binlog进行深度改造和定制来作为X-Paxos的Consensus日志,实现了一系列的X-Paxos日志接口,赋予X-Paxos直接操纵MySQL日志的能力。

为了保证集群数据的一致性以及全球部署的能力,在事务提交、日志复制回放以及恢复上X-Cluster都进行了重新设计。

三、Jepsen简介

1、Jepsen架构

Jepsen是一个开源的分布式一致性验证框架,可用于验证分布式数据库、分布式消息队列、分布式协调系统。Jepsen探索特定故障模式下分布式系统是否满足一致性。Jepsen框架是一个Clojure程序库,Clojure是一门运行在JVM上的解释型的类Lisp语言。Jepsen测试程序是一个Clojure程序,它使用Jepsen框架来构建一个分布式系统,对其执行一系列操作,并验证这些操作的历史记录是否有意义。它还可以生成性能和可用性图,帮助描述系统如何响应不同故障。

未分类

Jepsen测试程序在Control node上运行,使用SSH登录到一些DB node,在其上部署并启动相应的DB进程,DB进程组成待测试的分布式系统。测试开始后,Control node创建一组Client进程,每个Client都有自己的分布式系统客户端。Generator产生每个Client执行的operation,Client进程使用其客户端将operation应用于待测试的分布式系统。每个operation的开始和结束以及操作结果记录在历史记录中。同时,一个特殊的Client进程Nemesis将故障引入系统,其operation也来自Generator。测试结束后,DB将停止并卸载。Checker分析历史记录是否正确,并可生成报告、图表等。Checker在分析时可使用一个定义系统行为的Model。

2、Jepsen技术

2.1 黑盒系统测试

Jepsen测试真实集群上运行的真实二进制文件,这使得Jepsen测试系统而不用接触其源代码,不需要深入检查网络数据包、形式化系统设计等。Jepsen测试出的Bug 在生产环境中是可观察的,而不是理论上的。Jepsen也牺牲了形式化方法的一些优点,如测试是非确定性的,无法证明正确性,只能发现错误。

2.2 分布式环境错误模型

在生产环境中,网络可能分区,时钟可能不同步,节点可能失效,分布式系统应该正确应对这些错误。许多测试框架仅测试正常集群的行为,但生产环境中系统可能面临各种失效模式,Jepsen测试分布式系统在各种错误模型下的行为。

2.3 生成式随机测试

Jepsen构造随机的操作,将其应用于系统,包括正常的访问系统操作、错误注入操作。并发的操作结果将记在历史记录中,历史记录将按照事先定义好的模型分析其正确性。生成式的随机测试通常显示边缘的情况与巧妙的输入组合下的结果。

四、X-Cluster、X-Paxos验证

1、验证结果

X-Cluster、X-Paxos使用Jepsen验证,用例涵盖所有Jepsen验证过的分布式数据库系统的场景和特性,另外还设计了新的独有的测试用例。已验证的场景和特性如下表所示:

未分类

2、错误模型

验证过程中周期性注入分布式环境下的各种错误,过一段时间恢复正常,注入的错误模型如下表所示:

未分类

3、用例设计

3.1 事务原子性

验证事务是否是原子的执行,即事务中的操作要么全部完成,要么全部不完成。

模拟银行系统的转账业务,多个账户之间互相转账,但总的余额保持不变。一次转账事务包含两个操作步骤:转出账户余额减去转账金额,转入账户余额加上转账金额。两个操作必须原子的执行,否则将违反总额不变的不变式。

并发的进行转账操作,同时读取所有账户的余额,将所有账户的余额相加,验证是否与总额一致,若否则违反事务原子性(或者是产生了脏读、过期读,此验证也验证了事务隔离性)。

3.2 事务隔离性

验证并发情况下,是否存在脏读(Dirty Read)、过期读(Stale Read)。
如果每次写入的值唯一,则读到的数据具有如下特点:a.失败的写操作写入的值不会被读到; b.发生脏读或过期读时,读到的数据与正确读到的数据值不同。否则违反事务隔离性。

并发批量的将一批记录更新至某个相同的值,保证每次更新的记录值唯一,同时批量读取这批记录,检查读到的记录中,是否存在失败的写操作写入的值,是否出现不相同的值。若是则违反事务隔离性。

3.3 丢失更新

验证并发情况下,是否存在丢失更新(Lost Update)。

可将每次更新的值都记录下来,最后读取出来,检查更新记录的完整性,若不完整,则出现丢失更新。

创建一个text类型的字段,每次更新将更新的值拼接到该字段中,最后读出该字段,检查更新记录是否完整。为了增加用例的难度,我们还创建了一个version字段,更新前先读出version,更新时检查version是否已被其它事务覆盖,若否才更新记录并递增version。

3.4 线性一致性

验证系统是否满足线性一致性(Linearizability)。

写操作在一个全局时钟体系内立刻对所有客户端进程可见,检查读操作是否返回最近的写操作的结果,若否则不满足线性一致性。

关于线性一致性的测试已有很多研究成果。随机并发的进行read、write、cas(compare and set),记录操作结果以及开始和结束时间,检查是否满足可线性化。例如下图(图片出自Jepsen作者的博客):

未分类

图中显示了三个进程(10,11,18)并发执行读取到2,读取到4和写入0的操作记录。从左到右为时间线,操作方框的左侧表示操作的开始时间,右侧表示结束时间,操作实际生效的时间可能在开始时间和结束时间之间的任意时刻。进程10读取到的值为2,该读取可以在进程18写入0的之前或之后,在进程11执行读取的时间段内,数据的值可能为0或者2,但不管数据的值为0还是2,都不允许进程11读取到4,因此不满足可线性化。

3.5 顺序一致性

验证系统是否满足顺序一致性(Sequential Consistency)。

写事务应该以写入的顺序对所有客户端可见,客户端如果读到某次写入的值,则在该写入之前写入的值都应该能被读到。否则违反顺序一致性。
使用一个客户端进程按顺序向不同的表中插入k1, k2, … , 同时其它客户端进程尝试按照kn, … , k2, k1的顺序读取,若读取结果不满足此顺序,则违反顺序一致性。

3.6 单调一致性

验证系统是否满足单调一致性(Monotonic Consistency)。

并发的插入操作应该按全局时间顺序执行,否则违反单调一致性。

在插入事务中,我们先查询表中最大的值,然后获取时间戳,将表中最大值加一后的值和时间戳插入表中,最后读出表中所有记录,按照时间戳排序,排序后值应该单调递增,否则违反单调一致性。

3.7 最终一致性

验证系统是否满足最终一致性(Eventually Consistency)。

所有成功写入的数据最终会被读到,读到的数据一定是之前写入的。否则违反最终一致性。

先不断插入新的记录,最后等待足够长一段时间后读取所有记录。检查所有成功插入的记录是否都被读到,读到的记录是否都是之前写入的。否则违反最终一致一性。

3.8 严格可串行化

验证系统是否满足严格可串行化(Strict Serializability) 。

并发情况下,事务是否按照提交顺序可串行化,先提交的事务是否对后提交的事务可见,若否则违反严格可串行化。

并发向多张表中插入记录,同时不断读取所有记录,读到的记录必然不断增加,检查是否有后插入的记录先出现在读到的结果中。若有则违反严格可串行化。

3.9 副本一致性

验证系统中同一数据的多个副本是否一致。

比较一条记录的多个副本是否具有相同的值,若否则违反副本一致性。

不断修改记录的值,并增加版本号字段,同时不断从所有副本读取记录,比较同一版本的不同副本上的记录值是否一致,若否则违反副本一致性。

3.10 Adya

Adya在其论文中讨论的场景,验证事务依赖图中有环时是否保证数据一致性,如T1 r(x)、T2 r(y)、T1 w(y)、T2 w(x),则T1、T2只能有一个成功。
构造并发的环形依赖的事务,检查事务执行结果,是否违反一致性。
并发向两张表中插入新的记录,插入事务先查询两张表中相应记录是否存在,若都不存在,则一个事务插入到其中一张表,另一个事务插入到另一张表,若记录存在于某张表中,则插入失败。对于一条记录,检查是否只有一个插入事务成功,若两张表都插入成功,则违反一致性。

五、验证总结

基于X-Paxos的X-Cluster是一个单点可写,多点可读的数据库集群,Leader上提供强一致性,Follower上数据落后,提供最终一致性。X-Cluster通过了所有的Jepsen测试,验证了X-Cluster的正确性,也间接的验证了X-Paxos的正确性。

验证过程中也发现X-Cluster和X-Paxos的一些特性可以加以改进:

  • Follower上数据落后,只提供最终一致性。针对数据强一致性要求的场景,X-Cluster可增加一个配置项,用于配置Follower上是否对外提供读功能,防止应用读到过期的数据。还可考虑实现Follower上的read lease,让Follwer也能提供强一致性读。

  • Follower被隔离时,仍对外提供读功能。此时并没有违反最终一致性,只是达到最终一致性的时间会延长至Follower重新与Leader连通之后。当Follower发现自己被隔离时,可对外禁止读操作,防止应用读到过老的数据。

  • 只有Leader上提供了查询成员组信息的功能,Follwer上没有。Follwer可增加查询成员组信息的功能,便于应用重定向至Leader。

Paxos是分布式系统的基石,X-Paxos提供了一个经过实践检验的,高度成熟可靠的独立Paxos基础库。基于X-Paxos的X-Cluster实现了高可用、强一致、全球部署的分布式数据库集群。X-Paxos、X-Cluster后续还将不断改进、演化,实现更多的功能,更好的性能。

AliSQL X-Cluster 基于X-Paxos的高性能强一致MySQL数据库

一、前言

MySQL数据库从诞生以来就以其简单、易用、开源为其主打特点,成为不少开发者首选的数据库系统。集团在2008年开始提出”去IOE”的口号,其中,使用大量的MySQL,配合业务的改造替代原有的商业版Oracle系统。自此集团迈入了MySQL数据库的时代。根据阿里交易型应用的特点,以及双十一这样业界罕有的需求推动下,我们在官方的MySQL基础上增加了非常多实用的功能、性能补丁,打造了AliSQL这个业界响当当的MySQL分支品牌。

时间很快走到2014年,随着业务高速的增长,同城主备AliSQL部署的方式已经无法满足阿里对可扩展的部署、国际化、以及容灾方面的需求。“异地多活”成为了公司应用的新标准。“异地多活”也给底层的数据库提出了新的容灾要求。传统的Master-Slave架构下,主备如果不使用强同步模式就会存在数据丢失的可能,然而强同步下一旦有节点异常则整体不可服务。 而且这套架构下需要HA工具来进行选主的仲裁和控制。过去阿里巴巴的DBA们开发了高效可靠的HA以及一整套工具和流程来做主备切换后数据和日志的校验和订正。然而我们相信技术的发展能带来更大的运维便利性以及更好的用户体验。 以Google Spanner以及Amazon Aruora 为代表的NewSQL系统为数据库的数据一致性给出了与以往不同的思路: 基于一致性协议搭建分布式的多副本数据库。

二、AliSQL X-Cluster介绍

AliSQL X-Cluster(本文中简称X-Cluster)是阿里巴巴数据库团队推出的兼容MySQL-5.7,提供数据强一致功能,支持全球部署的分布式数据库集群产品。

说到AliSQL X-Cluster就不能不提其分布式核心,一致性协议。
X-Paxos是阿里巴巴自主研发的一致性协议库,目标是填补市面上高性能、易接入的一致性协议库的空白。而市面上已开源的一致性协议实现,包括etcd以及其他厂商等都存在或性能不够,或功能上无法满足复杂的现实应用场景需求的问题。 有了X-Paxos,可基于它打造一套强一致的分布式系统,X-Cluster是第一个接入X-Paxos生态的重要产品,利用了X-Paxos实现了自动选主,日志同步,集群内数据强一致,在线集群配置变更等功能。同时X-CLuster基于MySQL生态,兼容最新版本的MySQL-5.7,集成了AliSQL过去的各种功能增强。 MySQL的用户可以零成本迁移到X-Cluster上。

1、整体架构

先来看一下X-Cluster的基本架构:

未分类

上图展示的是一个部署三个实例的Cluster集群。X-Cluster是一个单点写入,多点可读的集群系统。在同一时刻,整个集群中至多会有一个Leader节点来承担数据写入的任务。相比多点写入,单点写入不需要处理数据集冲突的问题,可以达到更好的性能与吞吐率。

X-Cluster 的每个实例都是一个单进程的系统,X-Paxos被深度整合到了数据库内核之中,替换了原有的复制模块。集群节点之间的增量数据同步完全是通过X-Paxos来自驱动,如何复制,从哪个点回放不再需要运维人员或者外部工具来介入。 X-Cluster为了追求最高的性能,利用MySQL的Binlog进行深度改造和定制来作为X-Paxos的Consensus日志,实现了一系列的X-Paxos日志接口,赋予X-Paxos直接操纵MySQL日志的能力。

为了保证集群数据的一致性以及全球部署的能力,在事务提交、日志复制回放以及恢复上X-Cluster都进行了重新设计。

2、事务提交 复制流程

未分类

X-Cluster的复制流程是基于X-Paxos驱动Consensus日志进行复制。

Leader节点在事务prepare阶段会将事务产生的日志收集起来,传递给X-Paxos协议层后进入等待。X-Paxos协议层会将Consensus日志高效地转发给集群内其他节点。当日志在超过集群半数实例上落盘后 X-Paxos会通知事务可以进入提交步骤。否则如果期间发生Leader变更,期间prepare的事务会根据Paxos日志的状态进行相应的回滚操作。相比原生MySQL,日志传输采用了多线程、异步化、Batching、Pipelining等优化手段,特别是在长传链路的场景中,效率提升明显。

Follower节点也使用X-Paxos进行日志的管理操作,为提升接收效率,收到Leader传递过来的日志以后将日志内容Append到Consensus Log末尾,Leader会异步的将达成多数派的日志的消息发送给Follower,Follower的协调者线程会负责读取达成多数派的日志并加以解析,并传递给各个回放工作线程进行并发的数据更新。 Follower的并发回放可以有多种方式,包括按照Leader上的Group Commit维度或者是按照表级别的维度,未来会引入最新的writeset方式来精确控制最大并发。

3、Failover

X-Cluster 只要半数以上的节点存活就能保证集群正常对外服务。 因此当少数的follower节点故障时并不影响集群的服务能力。当Leader节点故障时会自动触发集群的重新选主流程。 选主流程由X-Paxos驱动,在Paxos协议的基础上,结合优先级推选出新的Leader节点。

对于X-Cluster而言,failover_time = election_time + apply_time
election_time代表协议选主的时间,一般在10s左右, apply_time是数据应用日志的时间,取决于回放的速度,优秀的并行回放算法能把应用日志的时间控制在10s之内。

相对来说之下Leader节点故障是一个相对复杂的场景,故障包括了宕机、网络隔离等等。

未分类

如上图所示,一个三节点的X-Cluster集群,左上的Case是原Leader A节点宕机,因此B节点和C节点会在较长的时间内收不到Leader的心跳,因此在一个选举超时周期后,B节点开始尝试推选自己为Leader, 并且C节点同意, 那么B成为新的主节点,恢复服务能力。

左下的Case 是原Leader A节点发生网络分区,此时在选举超时后,BC两个节点的行为和之间的Case类似。 A节点由于无法将心跳和日志发送给BC两个节点在超时后会降级,然后不断尝试选自己为Leader,但是因为没有其他节点的同意,达不成多数派,一直都不会成功。当网络分区恢复后,A收到B节点的心跳,触发Leader stickness机制,A降级成为Follower,整个集群保持一致。

在选举的过程中是否能成为Leader需要根据节点的日志情况来决定。X-Cluster 承诺在failover的情况下不会丢失提交的数据。Paxos协议保证了在集群恢复后一定能保证所有的节点日志一致。那么只要数据是按照日志进行回放,就能保证所有节点的状态机(数据)一致。 成为Leader的节点要求有最长的日志。如右上所示,假设A节点宕机或者分区前已经把3号日志复制到了B节点,那么在重新选举后,B节点由于日志较多,因此能够被选举成Leader。 在成为Leader后B节点会尝试将3号日志再复制到C节点。最终,ABC三个节点都会有1,2,3号日志,因此数据也是一致的。

4、AliSQL X-Cluster的优化特性

X-Cluster拥有一系列的新功能和特性,以满足不同类型的应用对于功能和性能上的需求。

4.1 跨地域部署

X-Cluster的一个显著功能就是能够支持跨地域部署,在跨域的情况下也能保证集群数据强一致,拥有城市级容灾的能力。即使某个城市的机房全部宕机,只要保证集群多数派节点存活,所有的数据都不会丢失。 依赖X-Paxos以及数据库内核中异步化工作线程的改造,在数十毫秒的网络RTT(RoundTrip Time)下,X-Cluster依然有非常高的吞吐性能。拥有了跨地域部署的能力,X-Cluster的部署方式是非常灵活的。 业务可以根据实际的业务情况以及不同的容灾级别需求,选择同机房容灾,机房容灾,城市容灾部署,并且可以在不同的容灾级别之间灵活切换。

4.2 集群的动态配置和选举

X-Cluster支持在线集群配置变更。包括:

  • 增加节点下线节点
  • 修改节点类型为一致性节点或者是只读节点
  • 修改节点优先级
  • 修改集群的Leader
  • 修改只读节点复制源

所有的上述修改配置的过程在线进行,不会阻塞业务的正常运行,集群配置的变化也会严格按照Paxos协议进行,记录日志并且对应的推动状态机变更,并且有完善的恢复机制。保证最终集群内配置达成一致,不会因为集群配置变更过程中的异常导致脑裂或者其他配置出现终态不一致的问题。X-Cluster集群的节点从功能上看有两个类型, 包括参与选主与多数派协议的一致性协议节点还有只读节点。一致性协议节点是XCluster的基础。目前一个X-Cluster集群支持至少1个一致性节点,至多99个一致性节点。 只读节点可以无限扩展。 用户可以从一开始的单节点集群开始,后续不断根据需求扩展不同类型的节点。

4.3 优先级

应用往往对于容灾后新主节点是有要求的,在原先的主节点意外宕机后,新主如若落在了一个低规格的节点, 那么对于应用来说是很难接受的服务降级。 X-Cluster 支持同一个集群中的节点拥有不同的优先级,用户可以根据实际的部署需要,在配置集群时为每个实例节点设置优先级。

优先级功能主要包括以下两方面:

  • 权重化选主
  • 策略化多数派

权重化选主代表选主的顺序权重。只要在选举的时候没有网络隔离,选举Leader的顺序会按照集群存活节点的权重顺序进行。权重越高的节点,就有更大的优先级被选为Leader。我们实现了两段式的选举时间,第一阶段是集群内统一的租约时间,而二阶段是根据权重来决定,权重越大的节点时间越短,也就是会越早发起自选举。 除此之外,还有一重权重检测机制来保证权重优先级,节点上任时会广播检测一遍所有能够联通的集群内节点,如果发现权重更高的节点会主动发起一次Leader Transfer将Leader角色过继过去。 权重化选主在跨地域部署的场景下尤其重要。 跨地域的部署业务和数据库之间的访问延时会非常敏感,如果Leader节点随机的切换到了另一个地域的机房可能会导致应用大规模的访问异地实例,大幅增加客户端的响应时间。 权重化选主可以完美解决此问题。 按照应用的部署需求进行动态设置,非常灵活。

策略化多数派是指在事务提交日志同步过程中,哪些节点必须要日志复制完成。复制优先级分为两档,强复制和弱复制。标准的paxos只要超过半数的节点同步日志即可推进状态机,但是由于每个连接会自动分配路由的问题,可能在跨Region的访问中rtt时间会有误差。那么为了缩短网络/节点故障后按照选主优先级重新选主并继续服务的时间间隔,我们可以配置在规定日志复制到多数节点的基础上必须还要复制到了所有强复制的节点才可以推进状态机并返回客户端事务提交成功的响应。这是一个类Max protection模式的设计,如果检测到强一致节点宕机,可选择适当的降级。

4.4 低成本副本管理

在X-Cluster中,副本按照是否有数据状态机分为普通型(Normal),日志型(Log)两类。 普通型拥有全部的功能;日志型只拥有日志不包含数据。 如果日志型节点还是一个参与Paxos投票的一致性节点,那么它只有投票权,没有被选举权。

之所以要创建不同的类型的副本,还是出于应用需求以及成本控制的考虑。

相比传统的两节点主备复制,X-Cluster的常规同城部署方式是三节点。
日志型副本是作为降低部署成本的一种选择。日志型副本只存储日志,不需要存储数据,也不需要回放日志更新数据。因此无论是存储还是CPU的开销,日志型副本相比普通副本都有很大的优势。在实际应用规划中,非常适合来当做容灾型的节点部署。

4.5 只读节点管理

未分类

如上图所示,X-Cluster集群中的只读节点可以从任何一个一致性节点复制日志,这不仅是考虑到如果所有节点的日志都从Leader节点复制会对Leader节点造成过大的网络和IO瓶颈,而且由于跨区域部署下不同地域的数据状态机可能会有延时,设置了读写分离的用户在特定的场景下需要有特定的只读状态延时的要求。 但是这时的问题就是如果某个一致性节点发生了宕机,那么和它建立复制关系的只读节点应该如何进行灾备联动? 作为一个自运维的数据库服务,X-Cluster自然要解决好这个问题。X-Cluster定义了Learner Source Group。 每个Group是一个只读节点的容灾单元。 当Group内某个一致性节点发生意外状况(宕机或者网络隔离)集群会根据Group的配置,将挂载在故障节点下的只读节点配置到Group中另外一个正常工作的节点下进行数据同步。

4.6 高性能日志

未分类

MySQL系统在开启主备复制的情况下除了会记录Binlog之外,在备库上还会记录一份RelayLog。即从库通过指定对应主库的Binlog位置去同步一份二进制日志写入RelayLog,供复制线程读取和回放。

在X-Cluster中,只使用一份日志进行节点间的同步,利用X-Paxos的插件式日志模块的特性,每个节点有一份Consensus日志。这样既方便了对Consensus日志的管理,也降低了日志存储以及读写的开销。 Consensus Log 拥有Append,Get,Truncate以及Purge等基本接口,它的控制权完整地交给了X-Paxos,由X-Paxos进行控制。 除此之外,X-Cluster为Consensus Log设计了日志索引和日志缓存、预读机制,极大的提升了日志模块的性能保证一致性协议运作的高效性。

4.7 异步化事务提交

传统的MySQL都是 One Thread per Connection的工作模式, 在引入线程池后是以一个线程池孵化一定数量的工作线程, 每个线程负责处理一次query的解析、优化、修改数据、提交、回网络包等等。集群需要跨地域部署下,一次事务的提交由于需要在集群之间同步事务日志,受限于网络的RTT的限制,会达到数十毫秒的级别,那么对于一个普通的写事务来说,大量的时间会耗费在同步节点日志等待事务提交的过程。在大压力下,很快数据库内部的工作线程会耗尽, 吞吐达到瓶颈。 如果一味的放大数据库内部的工作线程数目,那么线程上下文的代价会大幅增加。 如果将整个事务的提交异步化,将工作线程从等待X-Paxos日志同步中解放出来,去处理新的连接请求,在大负载下可以拥有更高的处理能力。

异步化改造的说明示意如下图所示:

未分类

X-Cluster的异步化提交核心思想是将每个事务的请求分成两个阶段,提交之前一个阶段,提交和回包一个阶段。两个阶段都可以由不同的工作线程来完成。 为了完成异步化的改造,X-Cluster增加了等待同步队列和等待提交队列,用于存储处于不同阶段的事务。前者队列中的事务是等待Paxos多数派日志同步的事务,后者是等待提交的事务。 当用户发起Commit/Rollback/XA_Prepare时, 处理用户连接的线程池Worker产生事务日志并将事务上下文存储到等待同步的队列中。 等待同步队列的消费由少量数目的worker线程来完成,其余工作线程可以直接参与其他任务的处理。 事务等待多数派完成后会被推入等待提交队列。这个队列里的事务都是可以被立即提交的。所有的worker线程发现该队列里有事务,就可以顺道取出来执行提交操作。 这样一来,系统中只有少数的线程在等待日志同步操作, 其余的线程可以充分利用CPU处理客户端的请求。 X-Cluster以这样的思路为指导原则, 结合MySQL的Group Commit逻辑,将原有需要等待的操作全部异步化,让Worker线程可以去执行新的请求响应。在测试中,异步化改造在同城部署的场景中相比同步提交有10%的吞吐率提升,跨区域的部署后有500%的吞吐提升。

4.7 热点更新

热点更新原本就是数据库的一个难题,受制于行锁竞争,性能吞吐一直很难提升上去。X-Cluster面对跨域场景下的长传网络更加是雪上加霜,提交的时间变长,事务占据行锁的时间也显著增加。

为了解决此问题,X-Cluster在单机版AliSQL的热点功能之上优化了复制,使得在保证数据强一致的情况下,热点更新性能提升200倍。

未分类

如上图所示,X-Cluster针对热点行更新的基本思路是合并多个事务对同一行的更新。为了让批量的更新事务能够同时进行提交,X-Cluster增加了一种新的行锁类型——热点行锁。热点行锁下,热点更新的事务之间是相容的。 X-Cluster为了保证数据的一致性,对同一批的热点更新事务日志打上特殊tag, X-Paxos会根据tag将这一整批事务的日志组成一个单独的网络包进行集群间的数据同步,保证这些事务是原子的提交/回滚。除此之外为了提升日志回放的效率,X-Cluster将每个批次事务中对于热点行的更新日志也做了合并。

4.9 一体化的客户端和服务端

未分类

X-Cluster有完整的Client-Server生态。 所以整个系统不需要外部组件的介入,能够自封闭的成为一个生态闭环。 作为客户端的X-Driver能够订阅Server端发生的一切改变,从而进行自动寻主,实例列表动态维护等功能。 客户端的元数据就保存在X-Cluster服务内部。相比外置的元数据中心,这套自封闭体系能够以最快的时间获取到准确的集群变化。降低集群变更对用户的感知程度。

4.10 优化的备份以及数据订阅体系

未分类

基于强大的X-Paxos体系,日志备份以及数据订阅系统都能够以日志订阅者的方式接入进来。 由于有了X-Paxos的全局唯一位点支持,这些订阅系统的failover不再会有难以找到准确位点的困扰。而且由于X-Paxos是流式的推送日志消息,因此数据的实时性也能大幅改进。

三、AliSQL X-Cluster 实战部署方案

X-Cluster最为经典的两个部署方案是同城3副本,两份数据一份日志。以及跨地域5副本,四份数据一份日志。分别用于满足机房级容灾和城市级容灾需求。这里的副本概念指的都是一致性节点的部署,只读节点部署不影响容灾能力。这两类经典的部署方案都是考虑了可用性以及成本之间的权衡,以较小的代价换来目标的容灾能力。

未分类

X-Cluster的同城部署三副本能够方便的实现零数据丢失的实例容灾以及机房级容灾。 相比主备方式,额外增加了一个日志节点,换取强一致以及可用性。

未分类

三地五实例(四数据、五日志)能够保证城市级容灾, 如图所示,任何一个城市的节点全部宕机都不会影响到集群可用性,5个节点中至少还有3个节点是能够正常运行的。

在日常运行中,5节点在每次事务提交的时候必定需要将日志同步到3个节点,因此必然会出现一次跨域的网络同步,这也就是长传链路网络场景,X-Cluster对于慢网络的优化正是应对类似这样的需求。

四、AliSQL X-Cluster 性能表现

测试中我们使用了三节点部署的方式,分别在同域三机房、跨域三机房的网络环境下进行了测试。 测试工具使用标准的Sysbench的 insert/oltp, Insert测试下,并且每个事务中只包含一条插入语句,属于密集的小事务场景, 而相反的OLTP是读写大事务。 针对热点环境,测试的场景是改造update_nonindex , 使更新同一行数据。 只读场景不在本次测试的范畴内,原因是只读不涉及到节点的日志、数据同步,因此可以认为只读测试对于X-Cluster这样的分布式系统是没有意义的。

作为对比,我们使用了最新的单机版MySQL-5.7.19 以及该版本下的Group Replication。Group Replication在测试中关闭限流

测试机均是64core 512G内存 PCIE SSD。

测试结果如下:

Sysbench的对比

sysbench 主要是针对写以及读写混合场景下的测试,数据量为10张表,每张表20万记录
测试同域下的集群,Insert我们使用300并发线程、 OLTP使用400并发线程, 热点更新使用300并发线程。

未分类

未分类

在同一个域下,X-Cluster的吞吐和响应时间表现都是非常出色的,甚至略好于单机版本的MySQL-5.7.19。 相比Group Replication, 在本次测试的压力下,Insert case X-Cluster有超过一倍的吞吐以及55%左右的响应时间,OLTP case X-Cluster 有超过5%的吞吐以及接近70%的响应时间表现。

跨域下的集群需要大量的连接来保证吞吐,因此Insert使用2000并发线程,OLTP使用700并发线程,热点更新使用2500并发线程。

未分类

未分类

当集群部署在不同域时,X-Cluster和Group Replication相比同域的部署下吞吐都有下降,响应时间收到物理网络延迟的影响也有显著提高,然而在Insert case下,X-Cluster仍然可以达到超过单机版50%的吞吐,领先Group Replication 5倍,响应时间只有GR的四分之一。OLTP case下,X-Cluster 的吞吐领先Group Replication接近4倍,响应时间只有三分之一。

未分类

未分类

热点更新是X-Cluster的一大亮点功能, 根据测试结果,无论是同域还是跨域部署, X-Cluster的吞吐和响应时间表现都要远远超过单机MySQL和Group Replication。

五、AliSQL X-Cluster正确性保障

分布式系统的测试是非常复杂的,因为没有人能够通过穷举来罗列所有可能出现的情况。简单的接口测试和性能回归也只能覆盖一小部分场景,无法来衡量一个分布式系统版本的质量。只有日复一日的测试以及线上系统的正常运行能够真正地说明分布式系统的鲁棒性。

X-Cluster最大的挑战就是保证其基于分布式一致性协议实现的正确性。

经过实践证明,灰盒测试时最有效的手段。X-Cluster集成了X-Paxos,X-Paxos项目本身有一系列的测试框架用于发现和回归。除此之外X-Cluster基于tc、systemtap等工具构建了多种多样模拟网络异常、实例宕机、I/O异常的环境。在这套环境下网络分区、丢包、各种IO异常,各种实例宕机可以随机组合。同时使用benchmark工具对每个节点施加大压力的读写,定期的去校验集群中不同节点的数据以及日志的一致性。 一致性相关所有的操作都会记录在X-Cluster专门的日志中,方便追溯集群节点间的交互行为。 数据和日志的最终一致性校验交由外部系统来完成。阿里内部有专门的分片校验系统可以做X-Cluster不同节点的全量数据校验。

Consensus日志解析工具可以快速解析日志内容进行比对。这套测试环境帮助我们发现了非常多的系统BUG。包括实例恢复的BUG,网络异常导致的BUG等等。我们认为一个稳定的版本的标准是一定需要通过这个场景长时间的测试并各种表现符合预期。

除了数据和日志的最终一致性,对于数据的线性一致,事务隔离性,我们引入了Jepsen工具。 Jepsen帮助了大量分布式系统发现了分布式协议和实现的正确性问题。我们为X-Cluster专门构造了一系列的测试用例来尽可能覆盖各种异常场景,来发现系统在隔离性和一致性上的问题。

六、AliSQL X-Cluster与竞品的对比

AliSQL X-Cluster不是第一个基于MySQL的强一致集群方案,然而是最适合阿里场景的方案。对比下面这些竞品,不难看出X-Cluster真正的价值。

Galera

Galara是MariaDB支持的MySQL集群版本,支持强同步,支持多点写入,支持自动的集群配置以及节点failover, 支持行级别的并行复制,支持原生的MySQL客户端。在这套架构下,slave不会有延时,任意节点读到的都是一致数据,不会有事务数据丢失,读写可扩展。

Galera的集群通信是用了一种基于单令牌环的Totem组播协议。 为了能支持多点写入,主机在收到写请求后,会原子广播到组内所有的机器,由它们各自的事务管理层来决定是提交或者回滚。组播由于是P2P的通信,随着节点数增加,延时会放大,响应时间会变慢,并且只适用于低延时的局域网。 除此之外组播还有一个问题,如果组内的某台机器宕机,组播会超时,在踢掉fail的机器重新确定组内成员关系之前,整个集群不可服务。

Galera 采用了专门的文件gcache进行增量状态复制,gcache不做任何他用,很难基于它做周边数据消费系统的开发。

Group Replication

Group Replication是MySQL 官方出品的集群方案。

Group Replication多少是借鉴了Galera的思想,同样支持多主多点写入。Group Replication实现了一个X-COM的通信层,其新版本中已经使用了Paxos算法。目前一个GR集群中最多可以有9个节点,响应延时相对稳定,在节点同步日志层面, GR使用binlog,相比Galera更加的通用。

Group Replication 为了保证能够多点写入,会传递WriteSet的信息,其他节点收到WriteSet后需要进行合法性验证,确保正确处理冲突事务。在测试中,我们发现为了支持多点写入而做合法性验证也是一个非常明显的性能瓶颈点,在之前的对比测试也验证了GR尚有大量的改进余地。

七、总结

X-Cluster是针对数据质量要求较高的用户推出的全新的数据库解决方案。X-Cluster不仅能够享受到开源社区带来的红利,其中涉及一致性的关键的技术也能够做到完全的自主、可控,能够针对业务的需求进行灵活的变更。未来 X-Cluster会在此基础上做更多的优化,例如支持多分片的Paxos, 多节点提供强一致读等功能。

X-Paxos — 阿里巴巴的高性能分布式强一致Paxos独立基础库

一、引言

Paxos(分布式一致性算法)作为分布式系统的基石,一直都是计算机系统工程领域的热门话题。Paxos号称是最难理解的算法,其实现真的这么困难么?“X-Paxos”是阿里巴巴数据库团队面向高性能、全球部署以及阿里业务特征等需求,实现的一个高性能分布式强一致的Paxos独立基础库。X-Paxos具体又有哪些优势,能给现有的系统带来什么用的收益呢?

二、背景

分布式一致性算法(Consensus Algorithm)是一个分布式计算领域的基础性问题,其最基本的功能是为了在多个进程之间对某个(某些)值达成一致(强一致);进而解决分布式系统的可用性问题(高可用)。Paxos是最重要的分布式一致性算法,很多人都把它作为“分布式一致性协议”的代名词(Mike Burrows, inventor of the Chubby service at Google, says that “there is only one consensus protocol, and that’s Paxos”)。

关于Paxos的历史和原理,已经有很多经典的论文可以参考,也有厂内外的文章有详细的描述,本文就不再重复了。感兴趣的同学可以阅读下这些论文[1,2,3,4]。

三、业内

虽然Paxos的理论提出已经17年了,从第一个Paxos的工业实现到现在也已经11年了,但是直到近几年,无论是顶级会议,还是业内,Paxos相关的文章和项目还是层出不穷。

转向业内,虽然使用了Paxos及各种变种的产品已经层出不穷;但是真正工业级的,独立的,Paxos基础库还是相当的少见:Google并没有开源其任何Paxos基础库(连包含Paxos的项目都没有开源过); Facebook也没有公布过包含Paxos的产品; Apache有Zookeeper,但是其协议并不能支持一个高吞吐的状态机复制,且并没有提供独立的第三方库,可供快速接入。在Github上能找到的Paxos的独立库,star最高的是腾讯于去年开源的phxpaxos(后文会作为竞品进行详细对比)。

因此到目前为止业内还鲜有成熟可靠的,可供快速使用的独立第三方Paxos库,开源的Paxos生态也尚未成熟。

四、X-Paxos

1、愿景

我们的初衷并不是要做一个Paxos的公共库,X-Paxos诞生于阿里巴巴的分布式数据库AliSQL X-Cluster,但X-Paxos并不属于AliSQL X-Cluster。Paxos是分布式系统的基石,X-Paxos可用于解决各种各样的分布式系统中的一致性问题。因此在整个分布式数据库的设计之初,我们就独立设计了分布式一致性协议模块,并把它独立为X-Paxos。X-Paxos为AliSQL X-Cluster解决了分布式一致性问题,同样可以快速赋予其他系统分布式一致性能力。分布式一致性需求,并不是AliSQL X-Cluster所特有的,很多系统都存在这高可用和强一致的需求,我们把Paxos的能力独立成一个基础库,希望能够把这个能力带给更多的其他系统。例如:团队内的同学把X-Paxos融入到单机KV数据库RocksDB中,快速实现了一个分布式KV引擎。CNZZ团队把X-Paxos融入到业务存储系统中,构建全新的分布式强一致存储服务。

同时也正是AliSQL X-Cluster,成就了X-Paxos。Google的论文《Paxos made live》中有一段话说的很好,大意是说:Paxos从理论到现实世界的实现之间有巨大的鸿沟,在真正实现一个Paxos的时候,往往需要对Paxos的经典理论做一些扩展,(尤其是在实现一个高性能的Paxos的时候,扩展点就更多了,可以参考后文的功能增强和性能优化),这往往会导致真正的Paxos实现其实都是基于一个未被完全证明的协议。这也就是传说中,理论证明一个Paxos的实现,比实现这个Paxos还要难的原因了。因此一个成熟的Paxos实现很难独立产生,往往需要和一个系统结合在一起,通过一个或者多个系统来验证其可靠性和完备性。这也是为什么大部分成熟的Paxos案例都是和分布式数据库相结合的,例如最早的Paxos实现(Chubby),当前的主要Paxos实现(Google的MegaStore、Spanner,AWS的DynamoDB、S3等)。而X-Paxos正是依托于AliSQL X-Cluster验证了其可靠性和完备性。

我们的愿景是希望能够提供一个经过实践检验的,高度成熟可靠的独立Paxos基础库。使得一个后端服务能够通过简单的接入,就能拥有Paxos算法赋予的强一致、高可用、自动容灾等能力。真正将晦涩难懂的Paxos,变得平易近人,带入千万家。

2、架构

X-Paxos的整体架构如下图所示,主要可分为网络层、服务层、算法模块、日志模块4个部分。

未分类

网络层

网络层基于阿里内部非常成熟的网络库libeasy实现。libeasy的异步框架和线程池非常契合我们的整体异步化设计,同时我们对libeasy的重连等逻辑进行了修改,以适应分布式协议的需求。

服务层

服务层是驱动整个Paxos运行的基础,为Paxos提供了事件驱动,定时回调等核心的运行功能,每一个Paxos实现都有一个与之紧密相关的驱动层,驱动层的架构与性能和稳定性密切相关。

X-Paxos的服务层是一个基于C++11特性实现的多线程异步框架。常见的状态机/回调模型存在开发效率较低,可读性差等问题,一直被开发者所诟病;而协程又因其单线程的瓶颈,而使其应用场景受到限制。C++11以后的新版本提供了完美转发(argument forwarding)、可变模板参数(variadic templates)等特性,为我们能够实现一种全新的异步调用模型提供了可能。

例如这是X-Paxos内实际的一行创建单次定时任务的代码

new ThreadTimer(srv_->getThreadTimerService(), srv_, electionTimeout_, ThreadTimer::Oneshot,
                &Paxos::checkLeaderTransfer, this, targetId, currentTerm_.load(), log_->getLastLogIndex());

以上一行程序,包含了定时器的创建,任意回调函数的设置,回调函数参数的转发,并保证在回调触发后(Oneshot)内存的自动回收。同时服务层支持嵌套回调,即在回调函数中再一次生成一个定时/即时任务,实现一个有限次定时循环逻辑。

算法模块

X-Paxos当前的算法基于unique proposer的multi-paxos[3]实现,大量理论和实践已经证明了基于unique proposer的multi-paxos,性能好于multi-paxos/basic paxos,当前成熟的基于Paxos的系统,大部分都采用了这种方式。

算法模块的基础功能部分本文不再重复,感兴趣的同学可以参考相关论文[1,2,4]。在基础算法的基础上,结合阿里业务的场景以及高性能和生态的需求,X-Paxos做了很多的创新性的功能和性能的优化,使其相对于基础的multi-paxos,功能变的更加丰富,在多种部署场景下性能都有明显的提升。下一章中,将对这些优化进行详细的介绍。

日志模块

日志模块本是算法模块的一部分,但是出于对极致性能要求的考虑,我们把日志模块独立出来,并实现了一个默认的高性能的日志模块;有极致性能以及成本需求的用户,可以结合已有的日志系统,对接日志模块接口,以获取更高的性能和更低的成本。这也是X-Paxos作为高性能独立库特有的优势,下一章会进行详细的介绍。

3、功能增强

>>结合广泛的业务场景,构建开放的生态

  • 在线添加/删除节点,在线转让leader

X-Paxos在标准multi-paxos的基础上,支持在线添加/删除多种角色的节点,支持在线快速将leadership节点转移到其他节点(有主选举)。

  • 策略化多数派和权重化选主

集团及蚂蚁目前的多地有中心的架构,很多应用因其部署的特点,往往要求其在未发生城市级容灾的情况下,仅在中心写入数据库,或调用其他分布式服务;同时又要求在发生城市级容灾的时候(同一个城市的多个机房全部不可用),可以完全不丢失任何数据的情况下,将写入点切换到非中心。
而经典的multi-paxos并不能满足这些需求。经典理论中,多数派强同步以后即可完成提交,而多数派是非特定的,并不能保证某个/某些节点一定能得到完整的数据,并激活服务。在实际实现中,往往地理位置较近的节点会拥有强一致的数据,而地理位置较远的节点,一直处于非强一致节点,在容灾的时候永远无法激活为主节点,形同虚设。
同时当中心单节点出现故障需要容灾的时候,往往需要将主节点就近切换到同中心的另外一个节点;由于应用在多地的部署往往是非对称的原因,才出现单个region全挂的时候,写需要将主节点切到特定的region内。这些需求都需要Paxos在选主的时候,可以由用户指定规则,而经典理论中同样没有类似的功能,添加权重也需要保证Paxos的正确性。
X-Paxos在协议中实现了策略化多数派和权重化选主。基于策略化多数派,用户可以通过动态配置,指定某个/某些节点必须保有强一致的数据,在出现容灾需求的时候,可以立即激活为主节点。基于权重化选主,用户可以指定各个节点的选主权重,只有在高权重的节点全部不可用的时候,才会激活低权重的节点。

  • 节点角色定制化(Proposer/Accepter/Learner的独立配置)

在经典的multi-paxos实现中,一般每个节点都包含了Proposer/Accepter/Learner三种功能,每一个节点都是全功能节点。但是某些情况下我们并不需要所有节点都拥有全部的功能,例如:

  • 经典的三个副本部署中,我们可以裁剪其中一个节点的状态机,只保留日志(无数据的纯日志节点,但是在同步中作为多数派计算),此时我们需要裁剪掉协议中的Proposer功能(被选举权),保留Accepter和Learner功能。

  • 我们希望可以有若干个节点可以作为下游,订阅/消费协议产生的日志流,而不作为集群的成员(不作为多数派计算,因为这些节点不保存日志流),此时我们裁剪掉协议的Proposer/Accepter 功能,只保留Learner功能

当然还有其他的组合方式,通过对节点角色的定制化组合,我们可以开发出很多的定制功能节点,即节约了成本,又丰富了功能。

未分类

  • Witness SDK

基于上节节点角色定制化中的单独Learner角色的功能,引发了无穷的想象力。Learner角色,可以抽象成一个数据流订阅者(Witness Node),整个集群中可以加入无数个订阅者,当有新的日志被提交的时候,这些订阅者会收到其关心的日志流,基于订阅者功能,我们可以让一个集群很容易的实现下游订阅消费,日志即时备份,配置变更推送等等的功能。
因此我们把Learner角色单独封装成了一个SDK。基于这个SDK,用户可以快速的为自己的集群添加,订阅注册,流式订阅定功能;结合特定的用途打造一个完成的生态。

例如日志流SDK在AliSQL X-Cluster中打造的生态:

未分类

采用了X-Paxos也可以利用Witness SDK快速实现分布式系统和下游的其他系统的对接,形成一个完整的生态。
我们拿MySQL的日志(binlog)备份来举例:

  • 普通方案
    • 每隔固定时间Tb,将MySQL生成的binlog文件备份到永久备份系统(OSS、S3等)
    • RPO (Recovery Point Objective)为 Tb
  • SDK方案
    • X-Paxos支持由SDK订阅增量日志,备份系统只需要简单的实现从SDK流到OSS流的对接,即可实现流式备份
    • RPO (Recovery Point Objective)为 0

除备份以外,Witness SDK在下游流式订阅(DRC)、自封闭高可用系统(X-Driver)、异步只读备库等方面都有实战案例,更多的应用案例在不断的添加中。

4、性能优化

>>我们一直坚信网络延迟不应该影响吞吐

  • Batching & Pipelining

Paxos除了设计之初的强一致和高可用以外,其高性能也是至关重要的,尤其是应用于AliSQL X-Cluster这种高性能分布式数据库的时候,对协议的吞吐,延迟都提出了很高的要求。同时作为可全球部署的分布式一致性协议,在高延迟下的性能挑战变得尤为重要。
X-Paxos针对高延迟网络做了大量的协议优化尝试和测试,并结合学术界现有的理论成果[5,6,7]通过合理的Batching和Pipelining,设计并实现了一整套自适应的针对高延迟高吞吐和低延迟高吞吐网络的通信模式,极大的提升了X-Paxos的性能(对比见下节)。类似的优化在同类竞品中还非常的罕见。

Batching是指,将多个日志合并成单个消息进行发送;Batching可以有效的降低消息粒度带来的额外损耗,提升吞吐。但是过大Batching容易造成单请求的延迟过大,导致并发请求数过高,继而影响了吞吐和请求延迟。

Pipelining是指在上一个消息返回结果以前,并发的发送下一个消息到对应节点的机制,通过提高并发发送消息数量(Pipelining数量),可以有效的降低并发单请求延迟,同时在transmission delay小于propagation delay的时候(高延迟高吞吐网络),有效提升性能。

经推导可知 Batching(消息大小:M)和Pipeling(消息并发:P)在如下关系下,达到最高吞吐

M/R * P = D

其中R为网络带宽,D为网络传播延迟(propagation delay,约为RTT/2)
X-Paxos结合以上理论,通过内置探测,针对不同节点的部署延迟,自适应的调整针对每个节点的Batching和Pipeling参数,达到整体的最大吞吐。
Pipeling的引入,需要解决日志的乱序问题,特别是在异地场景下,window加大,加大了乱序的概率。X-Paxos实现了一个高效的乱序处理模块,可以对底层日志实现屏蔽乱序问题,实现高效的乱序日志存储。

未分类

  • 多线程,全异步的Paxos库

由于Paxos的内部状态复杂,实现高效的单实例多线程的Paxos变成一个非常大的挑战。无论我们上面提到的github中star最多的phxpaxos,还是Oracle MySQL Group Replication中使用的xcom,都是单线程的实现。phxpaxos采用了单分区单线程,多实例聚合的方式提升总吞吐,但是对单分区的性能非常的有限;而xcom是一个基于协程的单线程实现。单线程的Paxos实现,在处理序列化/反序列化,分发、发包等逻辑的时候都为串行执行,性能瓶颈明显。
X-Paxos完全基于多线程实现,可以在单个分区Paxos中完全的使用多线程的能力,所有的任务都有通用的woker来运行,消除了CPU的瓶颈。依赖于服务层的多线程异步框架和异步网络层,X-Paxos除了必要的协议串行点外,大部分操作都可以并发执行,并且部分协议串行点采用了无锁设计,可以有效利用多线程能力,实现了Paxos的单分区多线程能力,单分区性能远超竞品,甚至超过了竞品的多分区分区性能。

  • Locality Aware Content Distribution

基于unique proposer的分布式系统的存在的一个瓶颈点就是主节点是唯一的内容输出源,当集群存在大量节点的时候,主节点的大量网络收发工作会导致主节点的负载过大,引发CPU和带宽的瓶颈;在全国/全球部署的时候,所有节点和主节点之间的直接通信会造成跨region之间的长传/国际链路的带宽占用过大。
X-Paxos是旨在解决全球分布式强一致问题的Paxos独立库,在设计之初就考虑到了这个问题。X-Paxos在稳态运行时会感知各个节点之间的网络延迟(物理距离),并形成级联拓扑,有效降低主节点的负载,降低长传链路的带宽使用;而在有节点异常的时候,又会自动重组拓扑,保证各个存活节点间的同行的正常进行。同时X-Paxos支持有业务来设定重组拓扑的规则,业务可以根据自己APP的部署架构和延迟特性来针对性的设置拓扑重组规则。

未分类

  • 可插拔日志

X-Paxos和现有的大部分paxos库很大的不同点就是X-Paxos支持可插拔的日志模块。日志模块是Paxos中一个重要的模块,它的持久化关系到数据的一致性,它的读写性能很大程度上会影响协议整体的读写性能。当前大部分独立Paxos库都是内置日志模块,并且不支持插拔的。这会带来2个弊端:

  • 默认的日志模块提供通用的功能,很难结合具体的系统做针对性的优化
  • 现有的系统往往已经存在了WAL(Write Ahead Log),而Paxos协议中需要再存一份。这使得 a)单次commit本地需要sync 2次(影响性能);b)双份日志浪费了大量的存储

例如:phxpaxos内置的日志模块采用LevelDB,作为日志系统其操作大量冗余,无针对优化,性能堪忧;同时采用phxpaxos的phxsql单节点需要即保存binlog,又保存Paxos log(在独立的phxbinlogsvr中),严重影响了性能,浪费了存储空间。而采用X-Paxos的AliSQL X-Cluster直接改造了现有的binlog模块,对接到X-Paxos的日志模块,单节点仅一份日志,即降低了存储,又提高了性能。

5、分布式正确性验证

对于一个分布式强一致协议来说,正确性是生命线。上文已经提及,一个分布式强一致协议,很难完整的理论证明其正确性,再加上工程实现的问题,困难就更多了。我们从理论和工程2方面用了大量的理论和技术手段来保证X-Paxos的正确性和完备性。

  • Jepsen
    • Jepsen是开源社区比较公认的分布式数据库的测试框架。Jepsen验证过包括VoltDB、CockroachDB、Galera、MongoDB、etcd在内的几乎所有的主流分布式数据库/系统,检验出了不少的问题。
    • X-Paxos完成了和Jepsen的对接,并验证了各个分布式数据库已有的case。
  • TLA+
    • TLA+是Paxos创始人、图灵奖获得者Leslie Lamport老爷子发明的一种形式化规约语言。TLA+专用于设计、建模和验证分布式并发系统。Amazon DynamoDB/S3/EBS和Microsoft Cosmos DB都通过TLA+的模型验证发现了不少问题
    • X-Paxos目前已经通过了TLA+的模型验证。
  • 随机异常系统

  • 我们搭建了一套自动随机异常验证系统,可以自动化验证各种异常场景下的协议正确性和稳定性。验证X-Paxos在模拟网络丢包、闪断、隔离,磁盘故障等情况下的功能正确和数据一致。

  • 异常回归系统

    • X-Paxos拥有一套异常case回归系统,对于曾经出现过或者预期的并发异常case,都会加到异常case库中,进行日常回归验证。同时异常case库也在不断的丰富中。

6、竞品分析与对比

XCOM (MySQL Group Replication)

MySQL Group Replication是MySQL官方借鉴Galera的思想,在MySQL上构建分布式强一致集群的一个插件。MySQL Group Replication早期采用的分布式协议是CoroSync,这是由Red Hat开发的基于Totem(The Totem Single-Ring Ordering and Membership Protocol)[8]协议开发的分布式一致性协议库;由于Totem算法本身存在的一些局限性能原因,从MySQL 5.7.9以后,官方采用了自己研发的基于类Paxos(Mencius)[10]的一致性协议库XCOM。
XCOM是MySQL Group Replication的核心组件,称为Group Communication Core[9]。我们分析了XCOM的源码,XCOM内部是一个由纯C语言编译的核心模块以及有C++实现的proxy实现的系统。纯C模块由单线程驱动,依赖协程实现任务调度。因此Client(MySQL Group Replication Plugin)必须用tcp连接向XCOM发送请求。因此XCOM存在如下的不足之处:

  • 单线程驱动,无多线程能力
    • 架构决定,很难突破
  • 通信流需要额外的一次TCP协议栈
    • 在内存拷贝都要精细计算的应用中,线程间多一次网络通信很难接受
      XCOM虽然实现了Batching和Pipelining,但是其值均为固定值,很难适应
  • 真实的场景
    • 官方的文档中也提到了这一点[9]
    • 这也使得MySQL Group Replication在跨Region场景中性能很不理想(见AliSQL X-Cluster对比测试)

phxpaxos (phxsql)

phxpaxos是腾讯推出的基于Paxos协议的独立库,其和MySQL结合后推出了phxsql项目,也是基于MySQL实现的分布式强一致MySQL集群。phxpaxos可独立用于其他项目,是目前github上star最多(1000+)的Paxos独立库。关于phxsql的细节本文不再叙述,可以参考(AliSQL X-Cluster的竞品分析部分),我们这里主要分析phxpaxos。phxpaxos也是基于multi-Paxos实现的独立库,其架构上采用单Paxos单线程设计,但是支持多Paxos分区以扩展多线程能力,这种扩展需要多数据进行提前分区。因此phxpaxos的不足之处如下:

  • 单Paxos对象只支持单线程;可支持多Paxos对象,共享网络层

  • 不支持pipelining,在跨Region环境(高延迟)下,几乎不可用

  • 多份日志冗余,基于LevelDB的日子系统性能瓶颈

性能对比

我们还是拿腾讯的phxpaxos作为竞品和我们进行对比(XCOM无独立组件,可间接参考MySQL Group Replication和AliSQL X-Cluster的对比测试结果)
我们分别在a) Region内3节点部署 b) 3个Region各一个节点部署 调节下,以不同的请求大小进行压测。

未分类

未分类

从上面2个对比图中可以看到:

  • X-Paxos的同Region性能是phxpaxos的100倍以上
  • 跨Region场景下phxpaxos几乎不可用,而X-Paxos在444Byte(sysbench insert场景单请求大小),性能只有3.5%的下降,几乎不影响吞吐。

五、现状与未来

1、现状

目前X-Paxos一期已经发布上线。
基于X-Paxos的集团数据库团队产品AliSQL X-Cluster(兼容MySQL生态的分布式关系型数据库)已在阿里巴巴集团、优酷等多个核心业务中使用,运行稳定。菜鸟、钉钉、蚂蚁等多个业务线在正在上线过程中。
我们和CNZZ团队合作,CNZZ团队为我们打造了JAVA版本的X-Paxos,并将JX-Paxos和分布式存储系统DTS结合,打造了高可用强一致的DTS2,目前已经上线引流,表现稳定。

2、未来

Paxos是分布式系统的基石,即使是近几年,学术界关于Paxos的文章,新的演进方向一致在不断的涌现,我们的X-Paxos也会不停的发展,以更好的适应集团内外的需求,未来主要的发展方向如下:

  • 高效率,多分区支持
    • 基于新的异步框架,实现一个深度底层共享的多分区Paxos
  • 多节点强一致读
    • 经典的multi-paxos只有在leader上才能提供强一致读,spanner和业界都有一些在多节点上提供强一致读的方案,但还是有比较明显的缺陷。

最后,无论是对Paxos协议/分布式数据库感兴趣的同学,还是想更多的了解或使用X-Paxos的同学,欢迎交流,互相学习!

Ubuntu安装配置uWSGI Nginx部署Flask项目

关于 uWSGI ,可以先看这篇文章。简单来说,WSGI 是一个 Python 协议,定义了应用程序(我们写的软件)如何与 Web 服务器(如 Nginx)通信,WSGI 只是一个接口。而 uWSGI 是一个支持多种语言的服务器容器,使用 WSGI 定义的标准实现与多种 Web 服务器的通信,并将 Web 服务器发来的请求“翻译”成应用程序所能理解形式。

安装

Python 2:

sudo apt-get update
sudo apt-get install python-pip python-dev nginx

Python 3:

sudo apt-get update
sudo apt-get install python3-pip python3-dev nginx

安装 Flask 和 uwsgi:

pip install uwsgi flask

创建一个简单的 Flask 项目 ~/myproject/myproject.py:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "<h1 style='color:blue'>Hello There!</h1>"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

创建启动文件为 ~/myproject/run.py:

from myproject import app

if __name__ == "__main__":
    app.run()

运行 python run.py ,然后访问 http://server_domain_or_IP:5000 将会看到:

未分类

当然直接使用 python run.py 的方法只适合本地开发,线上的话速度太慢,我们需要使用 uwsgi。

uwsgi

首先确保你安装了 uwsgi,然后运行:

uwsgi --socket 0.0.0.0:5000 --protocol=http -w run:app

protocol 说明使用 http 协议,-w 指明了要启动的模块,run 就是项目启动文件 run.py 去掉扩展名,app 是 run.py 文件中的变量 app,即 Falsk 实例。然后访问 http://server_domain_or_IP:5000,同样会看到上图。说明 uwsgi 可以正常运行。

但是这样的话每次都从命令行启动太麻烦,可以在 ~/myproject/目录下创建一个配置文件 myproject.ini:

[uwsgi]
module = run:app
master = true
processes = 3

chdir = /home/ubuntu/myproject
socket = /path/to/sock/myproject.sock
logto = /home/to/log/ishuhui.log
chmod-socket = 660
vacuum = true
  • processes = 5 说明要启动5个子进程处理请求;module = run:app 和命令行使用的意义一样;
  • chdir = /home/ubuntu/myproject 只想我们项目的根目录,即 run.py 所在文件夹;
  • socket = /path/to/sock/myproject.sock 是 uwsgi 启动后所需要创建的文件,这个文件用来和 Nginx 通信,后面会在配置 Nginx 时用到,所以 chmod-socket = 660 是为了修改 .sock 文件权限来和 Nginx 通信;
  • logto = /home/to/log/ishuhui.log 指明了 uwsgi 日志目录,uwsgi 会将请求历史写入该文件。

配置完成后运行:

uwsgi --ini myproject.ini

可以看到 /path/to/sock/myproject.sock 目录下多了 myproject.sock 文件,用来和 Nginx 通信。接下来配置 Nginx。

配置 Nginx

配置 Nginx 特别简单,找到 Nginx 配置文件(sudo vim /etc/nginx/sites-available/default),修改为如下格式:

server {
    listen 80;
    server_name server_domain_or_IP;

    location / {
        include uwsgi_params;
        uwsgi_pass unix:/path/to/sock/myproject.sock;
    }
}

其实重要的就两行:

include uwsgi_params;
uwsgi_pass unix:/path/to/sock/myproject.sock;

接下来不出意外,访问 80 端口,就可以看到你的程序了。

将 uwsgi 设置为系统服务

我们运行 uwsgi –ini myproject.ini 之后,按 ctrl+c 或者关闭 ssh 连接窗口,都会导致 uwsgi 进程关闭。 uwsgi 进程一关闭,.sock 文件就会消失,这时访问网站 Nginx 就会报错:

未分类

这时,我们需要进程管理软件管理 uwsgi 进程的运行了。Ubuntu 自带的 systemd 是最简单的方法,可以将我们的项目变为系统服务。首先创建 myproject.service 文件 sudo vim /etc/systemd/system/myproject.service:

[Unit]
Description=uWSGI instance to serve myproject
After=network.target

[Service]
User=lufficc
Group=www-data
WorkingDirectory=/home/ubuntu/myproject
Environment=FLASKR_SETTINGS=/home/ubuntu/myproject/env.cfg
ExecStart=/usr/local/bin/uwsgi --ini /home/ubuntu/myprojectenv/ishuhui.ini

[Install]
WantedBy=multi-user.target
  • WorkingDirectory: 你的项目目录。
  • Environment:需要的环境变量,比如指明你的项目的配置文件。
  • ExecStart:服务启动的代码。
  • WantedBy=multi-user.target:指明会跟随系统启动而启动该服务。

注意以上所有路径为绝对路径。

接下来可以愉快的启动了(myproject 就是 myproject.service 文件名去掉扩展名):

sudo systemctl start myproject
sudo systemctl restart myproject
sudo systemctl stop myproject

配置Haproxy代理实现MySQL从服务器的负载均衡

之前的文章配置过haproxy以及简单使用,具体可以参考《Centos系统环境下进行负载均衡软件Haproxy安装及配置》(http://www.21yunwei.com/archives/5111), 今天文章记录下通过配置Haproxy代理实现MySQL从服务器的负载均衡。

haproxy本身支持TCP协议的负载均衡转发,对于各种基于tcp的软件进行负载均衡比如mysql,之前配置的web负载均衡都是基于应用层,今天记录下tcp的。

环境准备:

  • centos 6.x三台,具体如下:
    • IP:192.168.1.104 角色:haproxy,mysql_master
    • IP:192.168.1.122 角色:mysql_slave
    • IP:192.168.1.123 角色:mysql_slave
  • 说明:
    • mysql主从安装这里不单独配置写出,配置非常简单,可以参考之前的博客文章《Linux系统如何设置mysql数据库主从以及互为主从》(http://www.21yunwei.com/archives/1035)
    • 由于1.104已经配置了mysql_master占用了3306端口,haproxy我们启用3307端口测试。

一、配置haproxy

global                                                     
    log         127.0.0.1 local2                     
    chroot      /usr/share/haproxy
    pidfile     /var/run/haproxy.pid         
    maxconn     4000                                
    user        haproxy
    group       haproxy                        
    daemon                                               
defaults
        mode tcp               #默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
        retries 2               #两次连接失败就认为是服务器不可用,也可以通过后面设置
        option redispatch       #当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
        option abortonclose     #当服务器负载很高的时候,自动结束掉当前队列处理比较久的链接
        maxconn 4096            #默认的最大连接数
        timeout connect 5000ms  #连接超时
        timeout client 30000ms  #客户端超时
        timeout server 30000ms  #服务器超时
        #timeout check 2000      #=心跳检测超时
        log 127.0.0.1 local0 err #[err warning info debug]
listen test1
        bind 192.168.1.104:3307
        mode tcp
        #maxconn 4086
        #log 127.0.0.1 local0 debug
        server s1 192.168.1.122:3306
        server s2 192.168.1.123:3306

二、测试mysql的负载均衡

利用navicat连接192.168.1.104的3307端口,理论上我们会连接到后端的122或者123的mysql上,为了区别,我们分别从mysql_slave单独建立两个库以便区分:

  • 192.168.1.122 mysql_slave建立测试数据库web122;
  • 192.168.1.123 mysql_slave建立测试数据库web123;

(具体sql语句:create database web122/123 default charset utf8;)

连接测试:

未分类

连接进入查看:

未分类

查看我们连接到了192.168.1.123 mysql_slave,看到了建立的测试库web123.

断开连接,重新连接:

未分类

查看我们连接到了192.168.1.122 mysql_slave,看到了建立的测试库web122.

总结,配置Haproxy代理实现MySQL从服务器的负载均衡已经完成。后续需要根据配置文件进行一些参数的优化或者架构的优化,比如配置keepalive实现高可用、根据mysql_slave配置分配权重等等,具体情况具体分析。

如何通过haproxy配置多个独立站点

通过之前的文章《Centos系统环境下进行负载均衡软件Haproxy安装及配置》(http://www.21yunwei.com/archives/5111) 记录下如何安装haproxy,当时测试的比较简单,不过还是里边配置了几个站点,这里单独拿出来进行一下站点配置说明。

配置目的:对三个站点lvs.21yunwei.com、21yunwei.21yunwei.com、bbs.21yunwei.com进行单独设置web后端节点以及设置节点的权重,实现访问每个域名,都访问具体自己设置的站点节点以及自己的网站内容。没有配置站点ID的,则访问设置好的默认站点。

1、配置haproxy

说白了,就是针对haproxy进行配置后重启。根据配置目的,haproxy配置文件如下:

global                                                     
    log         127.0.0.1 local2                     
    chroot      /usr/share/haproxy
    pidfile     /var/run/haproxy.pid         
    maxconn     4000                                
    user        haproxy
    group       haproxy                        
    daemon                                               
defaults
    mode                    http                      
    log                        global   
    option                  httplog      

    option                  dontlognull          
    option http-server-close                  
    option forwardfor       except 127.0.0.0/8    
    option                  redispatch        
    retries                 3                             
    timeout http-request    10s             
    timeout queue           1m                
    timeout connect         10s                
    timeout client          1m                   
    timeout server          1m                   
    timeout http-keep-alive 10s           
    timeout check           10s                 
    maxconn                 3000                
frontend  http_default_80
    bind 0.0.0.0:80
    mode http
    log  global
    option  httplog
    option  httpclose
    option  forwardfor
    acl 21yunwei_site  hdr(host) -i 21yunwei.21yunwei.com
    acl lvs_site hdr(host) -i   lvs.21yunwei.com
    acl bbs_site  hdr(host) -i bbs.21yunwei.com
    use_backend   web_21yunwei  if 21yunwei_site
    use_backend   web_lvs   if lvs_site
    use_backend   web_bbs   if bbs_site
    default_backend             web_21yunwei
frontend www
   bind :81
   monitor-uri   /haproxy 
backend static                                                
    balance     roundrobin                             
    server      static 127.0.0.1:80 check            
backend web_21yunwei          
    mode    http                       
    balance roundrobin                              
    cookie SERVERID 
    option httpchk GET /index.html
    server  21web1 192.168.1.123:80  check inter 2000 fall 3 weight 1             
    server  21web2 192.168.1.122:80  check inter 2000 fall 3 weight 1
backend web_lvs
    mode    http
    balance roundrobin    
    cookie SERVERID
    option httpchk GET /index.html
    server  lvsweb1 192.168.1.123:80  check inter 2000 fall 3 weight 1 
    server  lvsweb2 192.168.1.122:80  check inter 2000 fall 3 weight 3  
backend web_bbs
    mode    http
    balance roundrobin
    cookie SERVERID
    option httpchk GET /ok.php
    server  21web1 192.168.1.123:80  check inter 2000 fall 3 weight 1
    server  21web2 192.168.1.122:80  check inter 2000 fall 3 weight 1

listen  admin_stats 0.0.0.0:88
        option httplog
         stats refresh 30s
         stats uri /admin
         stats realm Haproxy Manager
         stats auth admin:admin

大如上边配置文件,我们配置了一个的frontend 指定前端访问虚拟节点和三个backend后端集群。
说明:

  • frontend里边包含了网站的端口、模式、日志以及acl规则,这里主要是acl规则,访问每个域名都指定访问哪个后端集群,不在acl访问控制规则里边的则访问到默认站点。

  • backend主要是配置对应的后端集群,包含模式、指定算法、健康检测url以及对应后端的真实server节点,节点包含具体IP以及端口、检测以及权重。

  • 补充内容:haproxy作为一款负载均衡软件,本身还是支持动静分离的,可以通过acl规则设置动静分离,分别走独立配置的backend后端集群。比如这样配置可以设置动静分离(本博客这里没这样设置,有实际需要的时候可以针对设置):

   acl url_static       path_beg       -i /static /images /javascript /stylesheets
   acl url_static       path_end       -i .jpg .jpeg .gif .png .css .js .html
   acl url_php          path_end       -i .php

   use_backend static_servers          if url_static
   use_backend dynamic_servers         if url_php
   default_backend dynamic_servers

2、测试

由于设置了监控页面,可以先进入监控页面看下节点是否都正常:

未分类

查看节点没异常,这里分别访问三个域名进行测试:

访问bbs.21yunwei.com效果:

未分类

访问21yunwei.21yunwei.com效果:

未分类

访问lvs.21yunwei.com效果:

未分类

可见设置是正确的,没问题。 同时安装了论坛或者其他有session会话保持的系统的,可以进行session会话保持测试。 单独停掉其中的一个web节点,会话保持不受影响,依旧可以进行正常登陆操作。

ubuntu安装配置轻量级http代理服务器Tinyproxy

先安装

apt-get install tinyproxy

配置文件默认:/etc/tinyproxy.conf

nano /etc/tinyproxy.conf

修改访问端口:Port yourPort

安全策略修改允许访问ip:可以添加 Allow yourIP

如果允许任何人访问则把 allow 注释或者删除掉

测试,打开允许访问的主机的命令行窗口,执行

curl -x proxyIp:proxyPort www.baidu.com

看看是否返回百度首页html代码

几个命令:

service tinyproxy start

默认启动

sudo service tinyproxy start

重启

sudo service tinyproxy restart

停止

sudo service tinyproxy stop

修改配置文件后需要重新启动。

Ubuntu 16.04安装python3.6.2

前言

自从昨天把电脑的双系统 win10(1703) + Ubuntu (16.04) 安装好后 就打算 以后在使用时尽量linux系统! 一来是为了更快上手 Linux 虽然有种说法 “学习Linux 虚拟机就够了”,emm ,不得不承认 虚拟机利用的好 确实是不错的选择,可是对于我,更想以更加亲近地方式接近 Linux ,所以呢不怕折腾的我 到底还是把系统装上了 二来 也基于对Linux 的向往 虽然新版的win10 更加迎合用户体验 , 我还是 选择 去折腾linux , Linux 也有不一样的美 所以 打算把编译环境都搬到这里

关于 Ubuntu16.04

Ubuntu16.04 上默认使用 Python2.7 和 python3.5 (可以分别使用 命令行 $ python2 -v 、$ python3 -v 查看Ubuntu上的python 版本 )

如果想要安装最新的python 版本 python3.6x 的可以通过python官网 提供的源代码安装

Ubuntun 安装 python 3.6.2

使以下命令行 :

# wget https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tar.xz
# tar -xvf Python-3.6.2.tar.xz
# cd Python-3.6.2
# ./configure
# make
# make install

备注:

1 . “Python-3.6.2.tar.xz ” 这个包 也可以 通过python官网网站直接下载然后定位到 下载目录 在目录下 解压安装此包

如 我是直接接下载到相应目录下解压的

~$cd /media/trsky/系统/编码软件工具
~$ cd  Python-3.6.2
~$./configure
~$ make
~$ make install
~$ sudo make install

2. 如果 在这过程中被提示 “权限不够” :

  • ubuntu 的权限不够, 这是因为 进入ubuntu的身份是自己默认登入名的那种情况 而不是 root ,使用自己默认登录名的情况下 ” 创建文件的权限不够 ” ,使用 root 身份即可获得相应权限

  • 在终端上 , 在 需要执行的命令行之前 加上 ” sudo ” ,使用root 权限 ,然后按照提示 输入用户密码就可以执行想做的操作了

  • 或者,在linux终端命令下 ,使用 “sudo -i ” 命令 直接进入 root 身份 用 ” logout ” 退出 root 权限 ,也可以 ” sudo su root ” 进入 ” exit ” 退出 ,例如 开始时是 ” user@ubuntu:~$” , 使用命 令后 ,变为 ” root@ubuntu:~#” , 改变了用户对一些命令的权限

如 我的终端输出情况 :

trsky@trsky-ubuntu:~$ sudo -i
root@trsky-ubuntu:~# logout
trsky@trsky-ubuntu:~$ sudo su root
root@trsky-ubuntu:/home/trsky# exit
exit
trsky@trsky-ubuntu:~$ 

3. 如果 提示 ” can’t decompress data; zlib not available ”

缺少依赖包 ” zlib ” ,则安装相应的包

# 安装依赖zlib、zlib-devel
# 在ubuntu里,zlib叫zlib1g,相应的zlib-devel叫zlib1g-dev
$ sudo apt-get install zlib1g
$ sudo apt-get install zlib1g-dev

4. 安装完后的一些操作

查看python3安装路径 和 版本

~ which python3
~ python3 -V

直接在 Linux 终端上也可以直接 ” ~$ python3 ” 查看python3 版本是否为自己所要更新的版本

5. 进入 python

要出现 Python提示符号

~$ python3

退出Python提示符

~$ quit() 
# 或者 
~$ exit() 

当你看到的python3 版本为Python 3.6.2 , 那么 Python 3.6.2 成功安装在了系统上!!

CentOS 7.2使用yum安装PHP 7

a使用webstatic源,官方文档 https://webtatic.com/packages/php70/ 

查看版本号

lsb_release -a

添加源

rpm  -Uvh  https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm  -Uvh  https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

安装

yum  install  php70w

问题

1、缺少gmp Processing Dependency: libgmp.so.3()(64bit)

解决方案

下载 compat-libgmp-4.3.1-1.sl7.x86_64.rpm (https://drive.google.com/file/d/0B7S255p3kFXNZFJDdWtkV3RyZTA/view)

安装rpm

rpm -ivh gmp-4.3.1-7.el6_2.2.x86_64.rpm

2、安装依赖缺失 Requires: httpd-mmn = 20051115

解决方案 清理yum

yum clean all