MySQL 主从复制原理如图 1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OiB2LXLe-1692948454604)(png/2019-11-30-10-41-11.png)]
如上图示,主从复制相关概念有:Master server(主服务器)、Slave server(从服务器)、
Binary logs(二进制日志)、Relay logs(中继日志)及相关的信息文件。
主服务器数据变动后,二进制日志记录下来,主服务器的 Binlog Dump 线程将二进制日志
发送给从服务器的 I/O Thread。接着从服务器 I/O 线程将其写入中继日志 Relay log。后面的
SQL Thread 将中继日志应用到从服务器,执行相应的 SQL 语句生成同步数据。
# at 237
#150416 18:30:21 server id 1 end_log_pos 316 CRC32 0x54b3fd07 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1429209021/*!*/;
BEGIN
/*!*/;
# at 316
#150416 18:30:21 server id 1 end_log_pos 440 CRC32 0x23bfcad7 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1429209021/*!*/;
insert into t1 (f1,f2) values(17650, 'hohdeal3lo')
/*!*/;
# at 440
#150416 18:30:21 server id 1 end_log_pos 471 CRC32 0x569c6fe3 Xid = 19
COMMIT/*!*/;
DELIMITER ;
# at 311
#130419 16:27:17 server id 1 end_log_pos 385 CRC32 0x572186a8 Rows_query
# insert into t1 (f1,f2) values(17650, 'hohdeal3lo') <- 5.6 only – binlog_rows_query_log_events needs to be ON
# at 385
#130419 16:27:17 server id 1 end_log_pos 433 CRC32 0x538010c4 Table_map: `test`.`t1` mapped to number 70
# at 433
#130419 16:27:17 server id 1 end_log_pos 484 CRC32 0x44f810d4 Write_rows: table id 70 flags: STMT_END_F
BINLOG '
tbZxUR0BAAAASgAAAIEBAACAADJpbnNlcnQgaW50byB0MSAoZjEsZjIpIHZhbHVlcygxNzY1MCwg
J2hvaGRlYWwzbG8nKaiGIVc=
tbZxURMBAAAAMAAAALEBAAAAAEYAAAAAAAEABHRlc3QAAnQxAAIDDwItAADEEIBT
tbZxUR4BAAAAMwAAAOQBAAAAAEYAAAAAAAEAAgAC//zyRAAACmhvaGRlYWwzbG/UEPhE
'/*!*/;
### INSERT INTO `test`.`t1`
### SET
### @1=17650 /* INT meta=0 nullable=0 is_null=0 */
### @2='hohdeal3lo' /* VARSTRING(45) meta=45 nullable=0 is_null=0 */
# at 48
SHOW PROCESSLIST
命令看到,叫 Binlog Dump 线程如:Command: Binlog Dump
。 MariaDB [(none)]> SHOW PROCESSLIST\G
*************************** 1. row ***************************
Id: 10
User: root
Host: localhost
db: NULL
Command: Query
Time: 0
State: NULL
Info: show processlist
Progress: 0.000
*************************** 2. row ***************************
Id: 202
User: repluser1
Host: 172.20.1.40:35346 # 从服务器1号
db: NULL
Command: Binlog Dump # Binlog Dump线程
Time: 214
State: Master has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
Progress: 0.000
*************************** 3. row ***************************
Id: 204
User: repluser1
Host: 172.20.1.43:49098 # 从服务器2号
db: NULL
Command: Binlog Dump # Binlog Dump线程
Time: 163
State: Master has sent all binlog to slave; waiting for binlog to be updated
Info: NULL
Progress: 0.000
3 rows in set (0.00 sec)
START SLAVE
命令时其就(Master:Binlog Dump Thread ----> binlog ----> Slave:I/O Thread)
SHOW SLAVE STATUS
命令查看MariaDB [(none)]> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.20.4.74
Master_User: repluser1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000005
Read_Master_Log_Pos: 245
Relay_Log_File: slave-relay-bin.000005
Relay_Log_Pos: 546
Relay_Master_Log_File: mariadb-bin.000005
Slave_IO_Running: Yes # I/O Thread status
Slave_SQL_Running: Yes
......略部分信息
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
1 row in set (0.00 sec)
SQL Thread:从服务器创建一个 SQL 线程读取被 I/O 线程写入磁盘的中继日志 Relay log,并执行其中记录的事务,生成数据。
每个主/从复制结构都涉及到三个线程:Master:Binlog dump thread;Slave:Slave I/O thread 和 Slave SQL thread
主服务器为每个从服务器创建一个 Binlog dump thread;每个从服务器自己创建两个线程。
bin-log
server-id=#
1 to 4294967295 (>= MariaDB 10.2.2),默认值为1
0 to 4294967295 (<= MariaDB 10.2.1),默认值为0,如果从节点为0,所有master都将拒绝此slave的连接
sync_binlog=1 每次写后立即同步二进制日志到磁盘,性能差
# 如果用到的为InnoDB存储引擎:建议如下
innodb_flush_log_at_trx_commit=1 #每次事务提交立即同步日志写磁盘
innodb_support_xa=ON #分布式事务MariaDB10.3.0废除
sync_master_info=# #次事件后master.info同步到磁盘
master<---->master
auto_increment_offset=1 #开始点
auto_increment_increment=2 #增长幅度
semi-replication
#主服务器配置:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
UNINSTALL PLUGIN rpl_semi_sync_master ;
SHOW PLUGINS; #查看插件
SET GLOBAL rpl_semi_sync_master_enabled=1;
SET GLOBAL rpl_semi_sync_master_timeout = 1000; #超时长1s,默认值为10s
SHOW GLOBAL VARIABLES LIKE '%semi%';
SHOW GLOBAL STATUS LIKE '%semi%';
semi-replication----mariadb-10.3版以后
#主服务器配置:
[mysqld]
plugin_load_add = semisync_master
#从服务器配置:
[mysqld]
plugin_load_add = semisync_slave
replication filter
binlog-do-db = #数据库白名单列表,多个数据库需多行实现
binlog-ignore-db = #数据库黑名单列表
GTID
gtid_mode=ON #gtid模式
enforce_gtid_consistency #保证GTID安全的参数
log_bin
log_slave_updates
server-id=#
read_only=ON
relay_log=relay-log
relay_log_file=relay-log.index
sync_relay_log=# #次写后同步relay log到磁盘
sync_relay_log_info=# #次事务后同步relay-log.info到磁盘
master<---->master
auto_increment_offset=2 #开始点
auto_increment_increment=2 #增长幅度
semi-replica
#从服务器配置:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled=1;
replication filter
replicate_do_db= #指定复制库的白名单
replicate_ignore_db= #指定复制库黑名单
replicate_do_table= #指定复制表的白名单
replicate_ignore_table= #指定复制表的黑名单
replicate_wild_do_table= foo%.bar% #支持通配符
replicate_wild_ignore_table=
GTID
gtid_mode=ON #gtid模式
enforce_gtid_consistency #保证GTID安全的参数
mysql>CHANGE MASTER TO MASTER_HOST='192.168.110.112',
MASTER_USER='repluser',
MASTER_PASSWORD='passwd',
MASTER_PORT=3306,
MASTER_AUTO_POSITION=1; ## Enable GTID
#打开独立表空间
innodb_file_per_table = 1
#MySQL 服务所允许的同时会话数的上限,经常出现Too Many Connections的错误提示,则需要增大此值
max_connections = 8000
#所有线程所打开表的数量
open_files_limit = 10240
#back_log 是操作系统在监听队列中所能保持的连接数
back_log = 300
#每个客户端连接最大的错误允许数量,当超过该次数,MYSQL服务器将禁止此主机的连接请求,直到MYSQL
服务器重启或通过flush hosts命令清空此主机的相关信息
max_connect_errors = 1000
#每个连接传输数据大小.最大1G,须是1024的倍数,一般设为最大的BLOB的值
max_allowed_packet = 32M
#指定一个请求的最大连接时间
wait_timeout = 10
# 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序
sort_buffer_size = 16M
#不带索引的全表扫描.使用的buffer的最小值
join_buffer_size = 16M
#查询缓冲大小
query_cache_size = 128M
#指定单个查询能够使用的缓冲区大小,缺省为1M
query_cache_limit = 4M
# 设定默认的事务隔离级别
transaction_isolation = REPEATABLE-READ
# 线程使用的堆大小. 此值限制内存中能处理的存储过程的递归深度和SQL语句复杂性,此容量的内存在每次连接时被预留.
thread_stack = 512K
# 二进制日志功能
log-bin=/data/mysqlbinlogs/
#二进制日志格式
binlog_format=row
#InnoDB使用一个缓冲池来保存索引和原始数据, 可设置这个变量到物理内存大小的80%
innodb_buffer_pool_size = 24G
#用来同步IO操作的IO线程的数量
innodb_file_io_threads = 4
#在InnoDb核心内的允许线程数量,建议的设置是CPU数量加上磁盘数量的两倍
innodb_thread_concurrency = 16
# 用来缓冲日志数据的缓冲区的大小
innodb_log_buffer_size = 16M
在日志组中每个日志文件的大小
innodb_log_file_size = 512M
# 在日志组中的文件总数
innodb_log_files_in_group = 3
# SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间
innodb_lock_wait_timeout = 120
#慢查询时长
long_query_time = 2
#将没有使用索引的查询也记录下来
log-queries-not-using-indexes
#查看进程信息
SHOW PROCESSLIST;
#查看当前的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
#查看当前锁定的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
#查看当前等锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
#查看错误日志
SHOW GLOBAL VARIABLES LIKE 'log_error'
#查看从节点信息
SHOW SLAVE STATUS;
#查看主节点信息
SHOW MASTER STATUS;
#查看二进制文件和位置
SHOW MASTER LOGS;
#查看插件情况
SHOW PLUGINS;
#查看半同步复制变量和信息
SHOW GLOBAL VARIABLES LIKE '%semi%';
SHOW GLOBAL STATUS LIKE '%semi%';
#查看所有的二进制文件信息
SHOW BINARY LOGS
#查看二进制日志事件
SHOW BINLOG EVENTS
Percona Tookit—Percona 官网提供的工具集
pt-table-checksum [OPTIONS] [DSN]
$pt-table-checksum --replicate=test.cksums --create-replicate-table
TS ERRORS
DIFFS ROWS CHUNKS SKIPPED TIME TABLE
04-30T11:31:50 0 0 633135 8 0 5.400 sakila.actor
04-30T11:31:52 0 0 290859 1 0 2.692 sakila.film
Checksumming sakila.film: 16% 02:27 remain
Checksumming sakila.film: 55% 01:58 remain
Checksumming sakila.film: 86% 00:24 remain
04-30T11:34:38 2 0 22187768 126 0 165.216 sakila.film
...
04-30T11:38:09 0 0 0 1 0 0.033 mysql.time_zone_name
04-30T11:38:09 0 0 0 1 0 0.052 mysql.time_zone_transition
04-30T11:38:09 0 0 0 1 0 0.054 mysql.time_zone_transition_type
04-30T11:38:09 0 0 8 1 0 0.064 mysql.user
...
$pt-table-checksum --replicate-check-only --replicate=test.cksums
Differences on h=127.0.0.1
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
sakila.film 1 0 1 PRIMARY 1 100
如果检查到数据不一致,可以使用 pt-table-sync 再次同步数据
用法
pt-table-sync [OPTIONS] DSN [DSN]
pt-table-sync --execute h=host1,D=db,t=tbl h=host2
pt-table-sync --execute host1 host2 host3
pt-table-sync --execute --sync-to-master slave1
例如:
$pt-table-sync --print --verbose --replicate=test.cksums --sync-to-master slave_server
# Syncing via replication h=slave_server
# DELETE REPLACE INSERT UPDATE ALGORITHM START END EXIT DATABASE.TABLE
REPLACE INTO `sakila`.`film`(`film_id`, `title`, `description`, `release_year`, `language_id`,
òriginal_language_id`, `rental_duration`, `rental_rate`, `length`, `replacement_cost`, `rating`,
`special_features`, `last_update`) VALUES ('1', 'ACADEMY DINOSAUR', 'A Epic Drama of a Feminist And a Mad
Scientist who must Battle a Teacher in The Canadian Rockies', '2006', '1', NULL, '6', '0.99', '86', '20.99',
'PG', 'Deleted Scenes,Behind the Scenes', '2006-02-15 05:03:42') /*percona-toolkit src_db:sakila src_tbl:film
src_dsn:P=3306,h=192.168.70.2 dst_db:sakila dst_tbl:film dst_dsn:h=192.168.70.3 lock:1 transaction:1
changing_src:test.cksums replicate:test.cksums bidirectional:0 pid:10109 user:root
host:localhost.localdomain*/;
REPLACE INTO `sakila`.`film`(`film_id`, `title`, `description`, `release_year`, `language_id`,
òriginal_language_id`, `rental_duration`, `rental_rate`, `length`, `replacement_cost`, `rating`,
`special_features`, `last_update`) VALUES ('2', 'ACE GOLDFINGER', 'A Astounding Epistle of a Database
Administrator And a Explorer who must Find a Car in Ancient China', '2006', '1', NULL, '3', '4.99', '48',
'12.99', 'G', 'Trailers,Deleted Scenes', '2006-02-15 05:03:42') /*percona-toolkit src_db:sakila src_tbl:film
src_dsn:P=3306,h=192.168.70.2 dst_db:sakila dst_tbl:film dst_dsn:h=192.168.70.3 lock:1 transaction:1
changing_src:test.cksums replicate:test.cksums bidirectional:0 pid:10109 user:root
host:localhost.localdomain*/;
...
# 0 10 0 0 Chunk 19:58:50 19:58:50 2 sakila.film
$pt-table-sync --execute --verbose --replicate=test.cksums --sync-to-master 192.168.70.3
# Syncing via replication h=192.168.70.3
# DELETE REPLACE INSERT UPDATE ALGORITHM START END EXIT DATABASE.TABLE
# 0 10 0 0 Chunk 20:08:23 20:08:23 2 sakila.film
Mycat 官网
Mycat 是什么?从定义和分类来看,它是一个使用 java 开发的开源的分布式数据库系统,是一个实现了
MySQL 协议的的 Server,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其
后端可以用 MySQL 原生(Native)协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服
务器通信,其核心功能是分表分库,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他
数据库里。
Mycat 基于阿里曾经开源的知名产品——Cobar。Cobar 的核心功能和优势是 MySQL 数据库分片,此产品曾经
广为流传,据说最早的发起者对 Mysql 很精通,后来从阿里跳槽了,阿里随后开源 Cobar,并维持到 2013 年初。
Cobar 是阿里巴巴研发的关系型数据的分布式处理系统,该产品成功替代了原先基于 Oracle 的数据存储
方案,已经接管了三千多个 MySQL 数据库的 schema,平均每天处理近 50 亿次的 SQL 执行请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XrIn2VqG-1692948454607)(png/2019-12-06-19-36-55.png)]
如上图所表示,数据被分到多个分片数据库后,应用如果需要读取数据,就要需要处理多个数据源的数据。
如果没有数据库中间件,那么应用将直接面对分片集群,数据源切换、事务处理、数据聚合都需要应用直接处理,
原本该是专注于业务的应用,将会花大量的工作来处理分片后的问题,最重要的是每个应用处理将是完全的重复
造轮子。所以有了数据库中间件,应用只需要集中与业务处理,大量的通用的数据聚合,事务,数据源切换都由
中间件来处理,中间件的性能与处理能力将直接决定应用的读写性能,所以一款好的数据库中间件至关重要。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWHNheAO-1692948454608)(png/2019-12-06-19-38-45.png)]
通常对实际应用来说,并不需要知道中间件的存在,业务开发人员只需要知道数据库的概念,所以数据库中间件
可以被看做是一个或多个数据库集群构成的逻辑库。在云计算时代,数据库中间件可以以多租户的形式给一个或
多个应用提供服务,每个应用访问的可能是一个独立或者是共享的物理库,常见的如阿里云数据库服务器 RDS。
3.逻辑表
既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表,可以是
数据切分后,分布在一个或多个分片库中,也可以不做数据切分,不分片,只有一个表构成。
4.分片节点(dataNode)
数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点(dataNode)。
5.节点主机(dataHost)
数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样
一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost),为了规避单节点主机并发数限制,尽量
将读写压力高的分片节点(dataNode)均衡的放在不同的节点主机(dataHost)。
6.分片规则(rule)
前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个
分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度。
7.全局序列号(sequence)
数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯一性
标识,这种保证全局性的数据唯一标识的机制就是全局序列号(sequence)。
[root@stevenux ~]#ansible websrvs -m yum -a 'name=java state=installed'
[root@stevenux ~]#ansible websrvs -a 'java -version'
172.20.1.67 | CHANGED | rc=0 >>
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)
[root@stevenux ~]#wget http://dl.mycat.io/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
[root@stevenux ~]#mkdir /app
[root@stevenux ~]#tar xf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /app
[root@stevenux ~]#ls /app/mycat/
bin catlet conf lib logs version.txt
bin: mycat命令,启动、重启、停止等
catlet: catlet为Mycat的一个扩展功能
conf: Mycat 配置信息,重点关注
server.xml Mycat软件本身相关的配置文件,设置账号、参数等
schema.xml Mycat对应的物理数据库和数据库表的配置,读写分离、高可用、分布式策略定制、节点控制
rule.xml Mycat分片(分库分表)规则配置文件,记录分片规则列表、使用方法等
lib: Mycat引用的jar包,Mycat是java开发的
logs: 日志文件,包括Mycat启动的日志和运行的日志
wrapper.log mycat启动日志
mycat.log mycat详细工作日志
version.txt mycat版本说明
#配置环境变量
vim /etc/profile.d/mycat.sh
PATH=/app/mycat/bin:$PATH
source /etc/profile.d/mycat.sh
#启动
mycat start
#查看日志,确定成功
cat /app/mycat/logs/wrapper.log
...省略...
INFO | jvm 1 | 2019/11/01 21:41:02 | MyCAT Server startup successfully. see
logs in logs/mycat.log
#连接mycat:
mysql -uroot -p123456 -h 127.0.0.1 -P8066 ##mycat 默认端口不是3306而是8066
Mycat 的配置文件使用 xml 文件,使用标签和标签所带的属性来定义配置项。主要分为 server.xml 和 schema.xml;
server.xml 几乎保存了所有 mycat 需要的系统配置信息。其在代码内直接的映射类为 SystemConfig 类。
Schema.xml 作为 MyCat 中重要的配置文件之一,管理着 MyCat 的逻辑库、表、分片规则、DataNode 以及 DataSource。
server.xml
参数 | 说明 |
---|---|
user | 用户配置节点,定义登录 mycat 的用户和权限 |
name | 客户端登录 MyCAT 的用户名,也就是客户端用来连接 Mycat 的用户名。 |
password | 客户端登录 MyCAT 的密码 |
schemas | 数据库名,这里会和 schema.xml 中的配置关联,多个用逗号分开,例如:db1,db2 |
privileges | 配置用户针对表的增删改查的权限 |
readOnly | mycat 逻辑库所具有的权限。true 为只读,false 为读写都有,默认为 false |
> server.xml文件里登录mycat的用户名和密码可以任意定义,这个账号和密码是为客户机登录mycat时使用的
账号信息
> 逻辑库名(如上面的TESTDBt,也就是登录mycat后显示的库名,切换这个库之后,显示的就是代理的真实mysql
数据库的表)要在schema.xml里面也定义,否则会导致mycat服务启动失败!
> 如果定义多个标签,即设置多个连接mycat的用户名和密码,那么就需要在schema.xml文件中定义多个对应的库!
schema.xml
schema.xml 是最主要的配置项,此文件关联 mysql 读写分离策略,读写分离、分库分表策略、分片节点都是在此
文件中配置的.MyCat 作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的 MySQL 物理服务器,
此文件就是用来连接 MySQL 服务器的
schema.xml 配置文件中的主要标签
参数 | 说明 |
---|---|
schema | schema 标签用于定义 MyCat 实例中的逻辑库,MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用 schema 标签来划分这些不同的逻辑库。如果不配置 schema 标签,所有的表配置,会属于同一个默认的逻辑库。 |
table | Table 标签定义了 MyCat 中的逻辑表,所有需要拆分的表都需要在这个标签中定义。 |
dataNode | 分片信息,也就是分库相关配置 |
dataHost | 物理数据库,真正存储数据的数据库 |
schema 标签属性
属性 | 说明 |
---|---|
name | 逻辑数据库名,与 server.xml 中的 schema 对应 |
checkSQLschema | 数据库前缀相关设置,这里为 false |
sqlMaxLimit | select 时默认的 limit,避免查询全表 |
table 标签属性
属性 | 说明 |
---|---|
name | 表名,物理数据库中表名 |
dataNode | 表存储到哪些节点,多个节点用逗号分隔。节点为下文 dataNode 设置的 name |
primaryKey | 主键字段名,自动生成主键时需要设置 |
autoIncrement | 是否自增 |
rule | 分片规则名,具体规则下文 rule 详细介绍 |
dataNode 标签属性
属性 | 说明 |
---|---|
name | 节点名,与 table 中 dataNode 对应 |
datahost | 物理数据库名,与 datahost 中 name 对应 |
database | 物理数据库中数据库名 |
dataHost 标签属性
属性 | 说明 |
---|---|
name | 物理数据库名,与 dataNode 中 dataHost 对应 |
balance | 均衡负载的方式 |
writeType | 写入方式 |
dbType | 数据库类型 |
heartbeat | 心跳检测语句,注意语句结尾的分号要加 |
schema.xml 文件中有三点需要注意:balance=“1”,writeType=“0” ,switchType=“1”
schema.xml 中的 balance 的取值决定了负载均衡对非事务内的读操作的处理。balance 属性负载均衡类
型,目前的取值有 4 种:
balance=“0” | 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上,即读请求仅发送到 writeHost 上 |
balance=“1” | 读请求随机分发到当前 writeHost 对应的 readHost 和 standby 的 writeHost 上。即全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 ,M2->S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1, S2 都参与 select 语句的负载均衡 |
balance=“2” | 读请求随机分发到当前 dataHost 内所有的 writeHost 和 readHost 上。即所有读操作都随机的在 writeHost、 readhost 上分发 |
balance=“3” | 读请求随机分发到当前 writeHost 对应的 readHost 上。即所有读请求随机的分发到 wiriterHost 对应的 readhost 执行, writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有 |
writeHost 和 readHost 标签
这两个标签都指定后端数据库的相关配置给 mycat,用于实例化后端连接池。唯一不同的是:
writeHost 指定写实例、readHost 指定读实例,组合这些读写实例来满足系统的要求。
在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是,如果 writeHost 指定的后端数据库宕
机,那么这个 writeHost 绑定的所有 readHost 都将不可用。另一方面,由于这个 writeHost 宕机系统会
自动的检测到,并切换到备用的 writeHost 上去
cat /etc/centos-release
CentOS Linux release 8.0.1905 (Core)
mycat-server 172.20.1.87
mysql-master 172.20.1.89
mysql-slave 172.20.1.91
systemctl stop firewalld
setenforce 0
[root@centos8 ~]#yum -y install mariadb-server
#master上的my.cnf
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id = 1
log-bin
#slave上的my.cnf
[mysqld]
server-id = 2
[root@centos8 ~]#systemctl start mariadb
[root@centos8 ~]#mysql -uroot -p
MariaDB [(none)]>GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'172.20.1.91' IDENTIFIED BY 'replpass';
mysql> FLUSH PRIVILEGES;
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
|mariadb-bin.000001| 403 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
[root@centos8 ~]#mysql -uroot -p
mysql> CHANGE MASTER TO
-> MASTER_HOST='172.20.1.89',
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='replpass',
-> MASTER_LOG_FILE='mariadb-bin.000001',
-> MASTER_LOG_POS=403;
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.20.1.89
Master_User: repluser
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mariadb-bin.000001
Read_Master_Log_Pos: 439
Relay_Log_File: mariadb-relay-bin.000002
Relay_Log_Pos: 689
Relay_Master_Log_File: mariadb-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
......
[root@centos8 ~]#yum -y install java mariadb
#确认安装成功
[root@centos8 ~]#java -version
openjdk version "1.8.0_201"
OpenJDK Runtime Environment (build 1.8.0_201-b09)
OpenJDK 64-Bit Server VM (build 25.201-b09, mixed mode)
#下载并安装
[root@centos8 ~]#wget http://dl.mycat.io/1.6.7.3/20190927161129/Mycat-server-
1.6.7.3-release-20190927161129-linux.tar.gz
[root@centos8 ~]#mkdir /app
[root@centos8 ~]#tar xvf Mycat-server-1.6.7.3-release-20190927161129-
linux.tar.gz -C /app
#配置环境变量
[root@centos8 ~]#vim /etc/profile.d/mycat.sh
PATH=/app/mycat/bin:$PATH
[root@centos8 ~]#source /etc/profile.d/mycat.sh
#查看端口
[root@centos8 ~]#ss -ntl
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:*
LISTEN 0 128 [::]:22 [::]:*
*:*
#启动mycat
[root@centos8 ~]#mycat start
Starting Mycat-server...
[root@centos8 ~]#ss -ntlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=791,fd=5))
LISTEN 0 1 127.0.0.1:32000 0.0.0.0:* users:(("java",pid=4640,fd=4))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=791,fd=7))
LISTEN 0 50 *:1984 *:* users:
LISTEN 0 100 *:8066 *:* users:
(("java",pid=4640,fd=87))
LISTEN 0 50 *:43465 *:* users:(("java",pid=4640,fd=58))
LISTEN 0 100 *:9066 *:* users:
(("java",pid=4640,fd=83))
LISTEN 0 50 *:45259 *:* users:(("java",pid=4640,fd=56))
#查看日志,确定成功
[root@centos8 ~]#cat /app/mycat/logs/wrapper.log
#用默认密码123456来连接mycat:
[root@centos8 ~]#mysql -uroot -p123456 -h 127.0.0.1 -P8066
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.29-mycat-1.6-RELEASE-20161028204710 MyCat Server
(OpenCloundDB)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>
[root@centos8 ~]#vim /app/mycat/conf/server.xml
...省略...
<user name="root"> #连接Mycat的用户名
<property name="password">stevenux</property> #连接Mycat的密码
<property name="schemas">TESTDB</property> # 数据库名要和schema.xml相
对应
</user>
</mycat:server>
这里使用的是 root,密码为 stevenux,逻辑数据库为 TESTDB,这些信息都可以自己随意定义,读写权限都
有,没有针对表做任何特殊的权限。重点关注上面这段配置,其他默认即可。
4 修改 schema.xml 实现读写分离策略
[root@centos8 ~]#vim /app/mycat/conf/schema.xml
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
</schema>
<dataNode name="dn1" dataHost="localhost1" database="mycat" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0"
dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="host1" url="172.20.1.89:3306" user="root" password="123456">
<readHost host="host2" url="172.20.1.91:3306" user="root" password="123456"
/>
</writeHost>
</dataHost>
</mycat:schema>
#重新启动mycat
[root@centos8 ~]#mycat restart
上面配置中,balance 改为 1,表示读写分离。以上配置达到的效果就是 172.20.1.89 为主库, 172.20.1.91 为从库
注意:要保证 192.168.100.11 和 192.168.100.12 机器能使用 root/123456 权限成功登录 mysql 数据库。
同时,也一定要授权 mycat 机器能使用 root/123456 权限成功登录这两台机器的 mysql 数据库!!这很
重要,否则会导致登录 mycat 后,对库和表操作失败!
5 在后端主服务器创建用户并对 mycat 授权
[root@centos8 ~]#mysql -uroot -p
mysql> create database mycat;
mysql>GRANT ALL ON *.* TO 'root'@'192.168.100.10' IDENTIFIED BY '123456' WITH
GRANT OPTION;
mysql> flush privileges;
[root@centos8 ~]#mysql -uroot -pstevenux -h127.0.0.1 -P8066 -DTESTDB
mysql> show databases;
+----------+
| DATABASE |
+----------+
| TESTDB | //只能看一个虚拟数据库
+----------+
mysql> use TESTDB;
mysql> create table t1(id int);
MySQL> select @@server_id;
show variables like 'general_log'; #查看日志是否开启
set global general_log=on; #开启日志功能
show variables like 'general_log_file'; #看看日志文件保存位置
set global general_log_file='tmp/general.log'; #设置日志文件保存位置
[root@centos8 ~]#vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
general_log=ON
[root@centos8 ~]#systemctl restart mariadb
[root@centos8 ~]#tail -f /var/lib/mysql/centos8.log
Mycat 权威指南
ProxySQL 官网
高可用简单的说就是对外提供服务的系统长时间不间断的提供服务;该服务不仅在线并且是有响应的。如某个 web 服务要
求在其上线期间的 99.99%的时间都必须能够正常提供服务,让用户正常访问也就是说一年内其不可用时间仅仅为:52.6
分钟[365*24*(1-0.9999)*60];某些互联网公司的要求就是每年的高可用时间占所有服务时间 99.99%;为什么互联网
企业对于其服务的高可用性要求高?高可用代表着可以持续的提供服务,持续不断的营收,哪怕一分一秒,对于大企业来
说都是不可轻易接受的,一个实实在在的例子是:在 2013 年 8 月份,亚马逊全球购物网站Amazon服务停了仅仅 15 分钟
(包括 web 和移动端服务),结果损失接近 990000 美元,每分钟接近 66000 美元,也即是每分钟损失近 52 万人民币。
即使对于如此体量的公司也是不小的数目。
一个简单的公式可以用来衡量高可用程度
HA=(T-W)*100/T
T:total time 服务总时间
W:waste time 服务不可用时间
现实中的企业要求各不一样,比如传统制造业的服务可用级别可以为 99.9%,而互联网公司的要求则比较高如 99.99%,比较
理想的是 5 个 9 的可用级别 99.999%,几乎无法达到,比如前几天支付宝后台服务器突然不可用,估计那几分钟过去了也就
没有 5 个 9 什么事儿了。下面是一些不同的可用级别不可用时间折算。可以看出 99%和 99.9%差别是巨大的。
可用级别 | 每年最长不可用时间 | 每天最长不可用时间 |
---|---|---|
One Nine: 90% | 36.5 days | 2.4 hours |
Two Nines: 99% | 3.65 days | 14 minutes |
Three Nines: 99.9% | 8.76 hours | 86 seconds |
Four Nines: 99.99% | 52.6 minutes | 8.6 seconds |
Five Nines: 99.999% | 5.25 minutes | 0.86 seconds |
Six Nines: 99.9999% | 31.5 seconds | 8.6 milliseconds |
MySQL 官方和社区里推出了很多高可用的解决方案,大体如下,仅供参考(数据引用自 Percona)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fX0VAjhd-1692948454609)(png/2019-12-06-22-11-07.png)]
MMM: Multi-Master Replication Manager for MySQL,Mysql 主主复制管理器是一套灵活的脚本
程序,基于 perl 实现,用来对 mysql replication 进行监控和故障迁移,并能管理 mysql Master-
Master 复制的配置(同一时间只有一个节点是可写的)
MMM 官网
源码
MHA:Master High Availability,对主节点进行监控,可实现自动故障转移至其它从节点;通过
提升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现,目前 MHA 主要支持
一主多从的架构,要搭建 MHA,要求一个复制集群中必须最少有三台数据库服务器,一主二从,即
一台充当 master,一台充当备用 master,另外一台充当从库,出于机器成本的考虑,淘宝进行了
改造,目前淘宝 TMHA 已经支持一主一从
MHA 官网
源码
Galera Cluster:Galera Cluster 集群底层采用 WSREP 技术实现(MySQL extended with the Write Set Replication)
通过 WSREP 协议在全局实现复制;任何一节点都可读写,不需要主从复制,实现多主读写。
Galera Cluster:wsrep(MySQL extended with the Write Set Replication)通过 wsrep 协议在全局实现复制;
任何一节点都可读写,不需要主从复制,实现多主读写。
Galera Cluster:集成了 Galera 插件的 MySQL 集群,是一种新型的,数据不共享的,高度冗余的高可用方案,
目前 Galera Cluster 有两个版本,分别是 Percona Xtradb Cluster 及 MariaDB Cluster,Galera 本身是具有
多主特性的,即采用 multi-master 的集群架构,是一个既稳健,又在数据一致性、完整性及高性能方面有出色表现
的高可用解决方案
Galera Cluster 优点
Galera Cluster 缺点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ssg0T4NS-1692948454611)(png/2019-12-07-09-21-40.png)]
Galera Cluster 解决方案包括两个组件
1.Galera replication library (galera-3):
组件 | 功能 |
---|---|
wsrep API | wsrep API 指明 DBMS 和复制提供者的职责的接口 |
wsrep hooks | wsrep hooks 是 wsrep 在 DBMS 引擎的集成 |
Galera provider | Galera provider 针对 Galera 库的 wsrep API 的实现 |
certification layer | 认证层:复制准备事务写集和进行认证 |
replication | 复制组件,负责管理复制协议和提供全局排序能力 |
GCS framework | GCS 框架:为组通讯系统提供插件架构 |
2.WSREP:MySQL extended with the Write Set Replication
Galera Cluster 官方文档
galeracluster.com-pdf
galeracluster.com-html
www.percona.com-html
mariadb.com-html
在 galera 集群中,服务器通过向集群中的每个节点广播与事务相关的写集并在提交时各节点同时复制该事务。
基于认证的复制使用组通讯技术和事务排序技术来实现同步复制。事务仅仅在某一节点执行,当提交时,集群内的
各节点间进行一个协调的认证过程来保证全局一致性。节点在各个并发的事务之间建立全局顺序的广播服务的帮助下
达成全局一致性。这保证了数据的一致性。
也不是所有的数据库系统都可以实现基于认证的复制技术。数据库需要有如下要求:
基于认证的复制如何工作的呢?
当一个新的节点加入集群时,它将像集群请求数据。某个节点(此时成 donor,捐赠者),会使用 SST 复制技术提供
一个数据全备份给新加入的节点(称 joiner)。可以使用wsrep_set_donor
参数事先指定某个节点为 donor,
不指定,则集群会根据已有信息自动指定一个节点作为 donor。组通信模块会监视节点状态,以便进行流控制、状态
传输和仲裁计算。它确保显示为 JOINING 状态(正在加入)的节点不计入流控制和仲裁。某个节点为 SYNCED 状态
时可以作为 donor,joiner 节点会从 synced 节点中选一个来复制数据。其倾向于选择有相同 gmcast.segment
选项的节点,或者直接选择索引中的第一个。当某个节点被选中后其状态立即变为 DONOR,此时其不再提供查询。
Galera 对于 SST 复制技术支持好几种后端复制方式。使用 wsrep_sst_method 参数来设置 SST 复制方式。
Method | Speed | Blocks Donor | Live Node Availability | Type | DB Root Access |
mysqldump | Slow | Blocks | Available | Logical | Donor and Joiner |
rsync | Fastest | Blocks | Unavailable | Physical | None |
xtrabackup | Fast | Briefly | Unavailable | Physical | Only Donor |
在下面的例子中,SST 复制方式设置为 rsync,donor 默认。需要注意的是,并没有最好的复制方式可以选择,需要根据
业务的需求和规模来灵活选择 SST 复制方式。
wsrep_sst_method = rsync
wsrep_sst_donor = "node1, node2"
3306:数据库对外服务的端口号
4444:请求SST的端口号
4567:组成员之间进行沟通的端口号
4568:用于传输IST的端口号
状态 | 意义 |
---|---|
open | 节点启动成功,尝试连接到集群时的状态 |
primary | 节点已处于集群中,在新节点加入并选取 donor 进行数据同步时的状态 |
joiner | 节点处于等待接收同步文件时的状态 |
joined | 节点完成数据同步工作,尝试保持和集群进度一致时的状态 |
synced | 节点正常提供服务时的状态,表示已经同步完成并和集群进度保持一致 |
donor | 节点处于为新加入的节点提供全量数据时的状态 |
备注:donor 节点就是数据的贡献者,如果一个新节点加入集群,此时又需要大量数据的 SST 数据传输,就有可能
因此而拖垮整个集群的性能,所以在生产环境中,如果数据量较小,还可以使用 SST 全量数据传输,但如果数据量
很大就不建议使用这种方式,可以考虑先建立主从关系,然后再加入集群。
3.节点的数据传输方式:
SST | State Snapshot Transfer,全量数据传输 |
IST | Incremental State Transfer,增量数据传输 |
SST 数据传输有 xtrabackup、mysqldump 和 rsync 三种方式,而增量数据传输就只有一种方式 xtrabackup,但生产环
境中一般数据量较小时,可以使用 SST 全量数据传输,但也只使用 xtrabackup 方法。
4.GCache 模块:在 PXC 中一个特别重要的模块,它的核心功能就是为每个节点缓存当前最新的写集。如果有新节
点加入进来,就可以把新数据的增量传递给新节点,而不需要再使用 SST 传输方式,这样可以让节点更快地加入集
群中,涉及如下参数:
gcache.size | 缓存写集增量信息的大小,它的默认大小是 128MB,通过 wsrep_provider_options 参数设置,建议调整为 2GB~4GB 范围,足够的空间便于缓存更多的增量信息。 |
gcache.mem_size | GCache 中内存缓存的大小,适度调大可以提高整个集群的性能 |
gcache.page_siz: | 如果内存不够用(GCache 不足),就直接将写集写入磁盘文件中 |
172.20.1.69 ---> node1
172.20.1.68 ---> node2
172.20.1.67 ---> node3
172.20.1.79 ---> node4
root@ubuntu1904:~#ansible websrvs -a 'cat /etc/redhat-release'
172.20.1.69 | CHANGED | rc=0 >>
CentOS Linux release 7.5.1804 (Core)
172.20.1.67 | CHANGED | rc=0 >>
CentOS Linux release 7.5.1804 (Core)
172.20.1.68 | CHANGED | rc=0 >>
CentOS Linux release 7.5.1804 (Core)
172.20.1.79 | CHANGED | rc=0 >>
CentOS Linux release 7.5.1804 (Core)
root@ubuntu1904:~#vim percona.repo
[percona]
name=percona_repo
baseurl=https://mirrors.tuna.tsinghua.edu.cn/percona/release/$releasever/RPMS/$basearch
enabled=1
gpgcheck=0
root@ubuntu1904:~#ansible websrvs -m copy -a 'src=~/percona.repo dest=/etc/yum.repos.d/'
172.20.1.69 | SUCCESS => {
"changed": false,
"checksum": "f8216c997d05be33581b307197515c3a8f0b9b34",
"dest": "/etc/yum.repos.d/percona.repo",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/etc/yum.repos.d/percona.repo",
"size": 137,
"state": "file",
"uid": 0
}
172.20.1.68 | SUCCESS => {
"changed": false,
"checksum": "f8216c997d05be33581b307197515c3a8f0b9b34",
"dest": "/etc/yum.repos.d/percona.repo",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/etc/yum.repos.d/percona.repo",
"size": 137,
"state": "file",
"uid": 0
}
172.20.1.67 | SUCCESS => {
"changed": false,
"checksum": "f8216c997d05be33581b307197515c3a8f0b9b34",
"dest": "/etc/yum.repos.d/percona.repo",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"path": "/etc/yum.repos.d/percona.repo",
"size": 137,
"state": "file",
"uid": 0
}
root@ubuntu1904:~#ansible websrvs -m yum -a 'name=Percona-XtraDB-Cluster-57 state=installed'
......
root@ubuntu1904:~#ansible websrvs -m yum -a 'name=Percona-XtraDB-Cluster-57'
172.20.1.68 | SUCCESS => {
"ansible_facts": {
"pkg_mgr": "yum"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"Percona-XtraDB-Cluster-57-5.7.27-31.39.1.el7.x86_64 providing Percona-XtraDB-Cluster-57 is already installed"
]
}
172.20.1.69 | SUCCESS => {
"ansible_facts": {
"pkg_mgr": "yum"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"Percona-XtraDB-Cluster-57-5.7.27-31.39.1.el7.x86_64 providing Percona-XtraDB-Cluster-57 is already installed"
]
}
172.20.1.67 | SUCCESS => {
"ansible_facts": {
"pkg_mgr": "yum"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"Percona-XtraDB-Cluster-57-5.7.27-31.39.1.el7.x86_64 providing Percona-XtraDB-Cluster-57 is already installed"
]
}
172.20.1.79 | SUCCESS => {
"ansible_facts": {
"pkg_mgr": "yum"
},
"changed": false,
"msg": "",
"rc": 0,
"results": [
"Percona-XtraDB-Cluster-57-5.7.27-31.39.1.el7.x86_64 providing Percona-XtraDB-Cluster-57 is already installed"
]
}
/etc/percona-xtradb-cluster.conf.d/wsrep.cnf # 最重要
/etc/percona-xtradb-cluster.conf.d/mysqld.cnf
/etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf
/etc/percona-xtradb-cluster.conf.d/wsrep.cnf
root@ubuntu1904:~#ansible websrvs -a 'grep -Ev "^#|^$" /etc/percona-xtradb-cluster.conf.d/wsrep.cnf'
172.20.1.79 | CHANGED | rc=0 >>
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.1.69,172.20.1.68,172.20.1.67,172.20.1.79
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.1.79
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-4
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
172.20.1.67 | CHANGED | rc=0 >>
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.1.69,172.20.1.68,172.20.1.67,172.20.1.79
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.1.67
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-3
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:s3cretPass"
172.20.1.68 | CHANGED | rc=0 >>
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.1.69,172.20.1.68,172.20.1.67,172.20.1.79
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.1.68
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-2
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth="sstuser:s3cretPass"
172.20.1.69 | CHANGED | rc=0 >>
[mysqld]
wsrep_provider=/usr/lib64/galera3/libgalera_smm.so
wsrep_cluster_address=gcomm://172.20.1.69,172.20.1.68,172.20.1.67,172.20.1.79
binlog_format=ROW
default_storage_engine=InnoDB
wsrep_slave_threads= 8
wsrep_log_conflicts
innodb_autoinc_lock_mode=2
wsrep_node_address=172.20.1.69
wsrep_cluster_name=pxc-cluster
wsrep_node_name=pxc-cluster-node-1
pxc_strict_mode=ENFORCING
wsrep_sst_method=xtrabackup-v2
注意:尽管 Galera Cluster 不再需要通过 binlog 的形式进行同步,但还是建议在配置文件中开启二进制日志
功能,原因是后期如果有新节点需要加入,老节点通过 SST 全量传输的方式向新节点传输数据,很可能会拖垮集群
性能,所以让新节点先通过 binlog 方式完成同步后再加入集群会是一种更好的选择
各项配置含义
wsrep_provider | 指定 Galera 库路径 |
wsrep_cluster_name | Galera 集群的名称 |
wsrep_cluster_address=gcomm:// | Galera 集群中各节点的地址。组通讯协议(Group communication) |
wsrep_node_name | 本节点在 Galera 集群中的名称 |
wsrep_node_address | 本节点在 Galera 集群中的通信地址 |
wsrep_sst_method | state_snapshot_transfer(SST)使用的传输方法,可用方法 mysqldump、rsync 和 xtrabackup,前两者在传输时都需要对 Donor 加全局只读锁(FLUSH TABLES WITH READ LOCK),xtrabackup 则不需要(它使用 percona 自己提供的 backup lock) 强烈建议采用 xtrabackup |
wsrep_sst_auth | 在 SST 传输时需要用到的认证凭据,格式为:“用户:密码” |
pxc_strict_mode | 是否限制 PXC 启用正在试用阶段的功能,ENFORCING 是默认值,表示不启用 |
binlog_format | 二进制日志的格式。Galera 只支持 row 格式的二进制日志 |
default_storage_engine | 指定默认存储引擎。Galera 的复制功能只支持 InnoDB |
innodb_autoinc_lock_mode | 只能设置为 2,设置为 0 或 1 时会无法正确处理死锁问题 |
/etc/percona-xtradb-cluster.conf.d/mysqld.cnf
root@ubuntu1904:~#ansible websrvs -a 'cat /etc/percona-xtradb-cluster.conf.d/mysqld.cnf'
172.20.1.67 | CHANGED | rc=0 >>
# Template my.cnf for PXC
# Edit to your requirements.
[client]
socket=/var/lib/mysql/mysql.sock
[mysqld]
server-id=67
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin
log_slave_updates
expire_logs_days=7
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
172.20.1.68 | CHANGED | rc=0 >>
# Template my.cnf for PXC
# Edit to your requirements.
[client]
socket=/var/lib/mysql/mysql.sock
[mysqld]
server-id=68
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin
log_slave_updates
expire_logs_days=7
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
172.20.1.69 | CHANGED | rc=0 >>
# Template my.cnf for PXC
# Edit to your requirements.
[client]
socket=/var/lib/mysql/mysql.sock
[mysqld]
server-id=1
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin
log_slave_updates
expire_logs_days=7
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
172.20.1.79 | CHANGED | rc=0 >>
# Template my.cnf for PXC
# Edit to your requirements.
[client]
socket=/var/lib/mysql/mysql.sock
[mysqld]
server-id=1
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
log-bin
log_slave_updates
expire_logs_days=7
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
/etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf
root@ubuntu1904:~#ansible websrvs -a 'cat /etc/percona-xtradb-cluster.conf.d/mysqld_safe.cnf'
172.20.1.69 | CHANGED | rc=0 >>
#
# The Percona Server 5.7 configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
172.20.1.68 | CHANGED | rc=0 >>
#
# The Percona Server 5.7 configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
172.20.1.67 | CHANGED | rc=0 >>
#
# The Percona Server 5.7 configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
172.20.1.79 | CHANGED | rc=0 >>
#
# The Percona Server 5.7 configuration file.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
[mysqld_safe]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/lib/mysql/mysql.sock
nice = 0
root@ubuntu1904:~#ansible 172.20.1.79 -a 'ss -ntl'
172.20.1.79 | CHANGED | rc=0 >>
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 100 127.0.0.1:25 *:*
LISTEN 0 128 *:22 *:*
LISTEN 0 100 [::1]:25 [::]:*
LISTEN 0 128 [::]:22 [::]:*
step1:
root@ubuntu1904:~#ansible 172.20.1.79 -a 'grep "temporary password" /var/log/mysqld.log'
172.20.1.79 | CHANGED | rc=0 >>
2019-12-02T14:20:36.077034Z 1 [Note] A temporary password is generated for root@localhost: hjPM1k.n%bij
step2:
ss -ntul
systemctl start [email protected]
ss -ntul
step3:
mysql -uroot -p'hjPM1k.n%bij'
ALTER USER 'root'@'localhost' INDENTIFIED BY 'stevenux';
CREATE USER 'sstuser'@'172.20.54.15' IDENTIFIED BY 's3cretPass';
GRANT RELOADE, LOCK TABLES, PROCESS, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost';
SHOW VARIABLES LIKE 'wsrep%'\G
SHOW STATUS LIKE 'wsrep%'\G
wsrep_cluster_size 表示,该Galera集群中只有一个节点
wsrep_local_state_comment 状态为Synced,表示数据已同步完成(新加入集群的主机)
如果状态是Joiner, 意味着 SST 没有完成. 只有所有节点状态是Synced,才可以加新节点
wsrep_cluster_status | Primary 表示已经完全连接并准备好
eg:
mysql> SHOW STATUS LIKE '%wsrep_cluster%';
+--------------------------+--------------------------------------+
| Variable_name | Value |
+--------------------------+--------------------------------------+
| wsrep_cluster_weight | 4 |
| wsrep_cluster_conf_id | 4 |
| wsrep_cluster_size | 4 |
| wsrep_cluster_state_uuid | bb07538d-1570-11ea-a0fd-b3f3ba857a8d |
| wsrep_cluster_status | Primary |
+--------------------------+--------------------------------------+
5 rows in set (0.00 sec)
root@ubuntu1904:~#ansible 'websrvs:!172.20.1.79' -m shell -a 'systemctl start mysql'
172.20.1.67 | CHANGED | rc=0 >>
172.20.1.68 | CHANGED | rc=0 >>
172.20.1.69 | CHANGED | rc=0 >>
略略略略略
配置大同小异,官网有教程
安装:
yum install mariadb-server-galera -y
dnf install mariadb-server-galera -y
启动第一个节点:
galera_new_cluster
启动其它节点:
systemctl start mariadb
MariaDB Galera Cluster 参考
pingcap-TiDB-github
A-brief-introduction-of-TiDB-pdf
TiDB("Ti"表示 Titanium,n. [化学] 钛(金属元素))是一个开源的分布式 NoSQL 数据库;支持混合事务分析处理
工作负载。最初是 PingCAP 公司受 Google Spanner / F1 论文启发而设计,结合了传统的 RDBMS 和 NoSQL 的最
佳特性。TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性。TiDB 和 mysql 几乎完全兼容。它支
持水平弹性扩展、ACID 事务、标准 SQL、MySQL 语法和 MySQL 协议,具有数据强一致的高可用特性,是一个不仅
适合 OLTP 场景还适合 OLAP 场景的混合数据库。TiDB 的目标是为 OLTP(Online Transactional Processing)
和 OLAP (Online Analytical Processing) 景提供一站式的解决方案。
TiDB 核心特点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ziLv8537-1692948454614)(png/2019-12-07-16-36-33.png)]
TiDB Server
TiDB Server 负责接收 SQL 请求,处理 SQL 相关的逻辑,并通过 PD 找到存储计算所需数据的 TiKV 地址,与
TiKV 交互获取数据,最终返回结果。TiDB Server 是无状态的,其本身并不存储数据,只负责计算,可以无限水平
扩展,可以通过负载均衡组件(LVS、HAProxy 或 F5)对外提供统一的接入地址。
PD Server
Placement Driver(简称 PD)是整个集群的管理模块,其主要工作有三个:一是存储集群的元信息(某个 Key 存储
在那个 TiKV 节点);二是对 TiKV 集群进行调度和负载均衡(如数据的迁移、Raft groupleader 的迁移等);三是
分配全局唯一且递增的事务 ID;PD 是一个集群,需要部署奇数个节点,一般线上推荐至少部署 3 个节点。PD 在选举
的过程中无法对外提供服务,这个时间大约是 3 秒。
TiKV Server
TiKV Server 负责存储数据,从外部看 TiKV 是一个分布式的提供事务的 Key-Value 存储引擎。存储数据的基本单
位是 Region,每个 Region 负责存储一个 Key Range(从 StartKey 到 EndKey 的左闭右开区间)的数据,每个
TiKV 节点会负责多个 Region。TiKV 使用 Raft 协议做复制,保持数据的一致性和容灾。副本以 Region 为单位
进行管理,不同节点上的多个 Region 构成一个 Raft Group,互为副本。数据在多个 TiKV 之间的负载均衡由 PD
调度,这里也就是以 Region 为单位进行调度。物理上 TiKV 上的数据存储由 RocksDB 引擎负责。
1.mysqlslap
2.Sysbench:功能强大,Sysbench-github 官网
3.tpcc-mysql
4.MySQL Benchmark Suite
5.MySQL super-smack
6.MyBench
mysqlslap来自于 mariadb 包,测试的过程默认生成一个 mysqlslap 的 schema,生成测试表 t1,查询和插
入测试数据,mysqlslap 库自动生成,如果已经存在则先删除。用–only-print 来打印实际的测试过程,整个测试
完成后不会在数据库中留下痕迹
用法:
mysqlslap [options]
--auto-generate-sql, -a #自动生成测试表和数据,表示用mysqlslap工具自己生成的SQL脚本来测试并发压力
--auto-generate-sql-load-type=type #测试语句的类型。代表要测试的环境是读操作还是写操作还是两者混合的。取值包括:read,key,write,update和mixed(默认)
--auto-generate-sql-add-auto-increment #代表对生成的表自动添加auto_increment列,从5.1.18版本开始支持
--number-char-cols=N, -x N #自动生成的测试表中包含多少个字符类型的列,默认1
--number-int-cols=N, -y N #自动生成的测试表中包含多少个数字类型的列,默认1
--number-of-queries=N #总的测试查询次数(并发客户数×每客户查询次数)
--query=name,-q #使用自定义脚本执行测试,例如可以调用自定义的存储过程或者sql语句来执行测试
--create-schema #代表自定义的测试库名称,测试的schema
--commint=N #多少条DML后提交一次
--compress, -C #如服务器和客户端都支持压缩,则压缩信息
--concurrency=N, -c N #表示并发量,即模拟多少个客户端同时执行select。可指定多个值,以逗号或者--delimiter参数指定值做为分隔符,如:--concurrency=100,200,500
--engine=engine_name, -e engine_name #代表要测试的引擎,可以有多个,用分隔符隔开。例如:--engines=myisam,innodb
--iterations=N, -i N #测试执行的迭代次数,代表要在不同并发环境下,各自运行测试多少次
--only-print #只打印测试语句而不实际执行。
--detach=N #执行N条语句后断开重连
--debug-info, -T #打印内存和CPU的相关信息
#单线程测试
mysqlslap -a -uroot -pmagedu
#多线程测试。使用--concurrency来模拟并发连接
mysqlslap -a -c 100 -uroot -pmagedu
#迭代测试。用于需要多次执行测试得到平均值
mysqlslap -a -i 10 -uroot -pmagedu
mysqlslap ---auto-generate-sql-add-autoincrement -a
mysqlslap -a --auto-generate-sql-load-type=read
mysqlslap -a --auto-generate-secondary-indexes=3
mysqlslap -a --auto-generate-sql-write-number=1000
mysqlslap --create-schema world -q "select count(*) from City"
mysqlslap -a -e innodb -uroot -pmagedu
mysqlslap -a --number-of-queries=10 -uroot -pmagedu
#测试同时不同的存储引擎的性能进行对比
mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --iterations=5 --
engine=myisam,innodb --debug-info -uroot -pmagedu
#执行一次测试,分别50和100个并发,执行1000次总查询
mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --debug-info -uroot -
pmagedu
#50和100个并发分别得到一次测试结果(Benchmark),并发数越多,执行完所有查询的时间越长。为了准确起见,可以多迭代测试几次
mysqlslap -a --concurrency=50,100 --number-of-queries 1000 --iterations=5 --
debug-info -uroot -pmagedu
#打开独立表空间
innodb_file_per_table = 1
#MySQL 服务所允许的同时会话数的上限,经常出现Too Many Connections的错误提示,则需要增大此值
max_connections = 8000
#所有线程所打开表的数量
open_files_limit = 10240
#back_log 是操作系统在监听队列中所能保持的连接数
back_log = 300
#每个客户端连接最大的错误允许数量,当超过该次数,MYSQL服务器将禁止此主机的连接请求,直到MYSQL
服务器重启或通过flush hosts命令清空此主机的相关信息
max_connect_errors = 1000
#每个连接传输数据大小.最大1G,须是1024的倍数,一般设为最大的BLOB的值
max_allowed_packet = 32M
#指定一个请求的最大连接时间
wait_timeout = 10
# 排序缓冲被用来处理类似ORDER BY以及GROUP BY队列所引起的排序
sort_buffer_size = 16M
#不带索引的全表扫描.使用的buffer的最小值
join_buffer_size = 16M
#查询缓冲大小
query_cache_size = 128M
#指定单个查询能够使用的缓冲区大小,缺省为1M
query_cache_limit = 4M
# 设定默认的事务隔离级别
transaction_isolation = REPEATABLE-READ
# 线程使用的堆大小. 此值限制内存中能处理的存储过程的递归深度和SQL语句复杂性,此容量的内存在每次连接时被预留.
thread_stack = 512K
# 二进制日志功能
log-bin=/data/mysqlbinlogs/
#二进制日志格式
binlog_format=row
#InnoDB使用一个缓冲池来保存索引和原始数据, 可设置这个变量到物理内存大小的80%
innodb_buffer_pool_size = 24G
#用来同步IO操作的IO线程的数量
innodb_file_io_threads = 4
#在InnoDb核心内的允许线程数量,建议的设置是CPU数量加上磁盘数量的两倍
innodb_thread_concurrency = 16
# 用来缓冲日志数据的缓冲区的大小
innodb_log_buffer_size = 16M
在日志组中每个日志文件的大小
innodb_log_file_size = 512M
# 在日志组中的文件总数
innodb_log_files_in_group = 3
# SQL语句在被回滚前,InnoDB事务等待InnoDB行锁的时间
innodb_lock_wait_timeout = 120
#慢查询时长
long_query_time = 2
#将没有使用索引的查询也记录下来
log-queries-not-using-indexes
多租户技术或称多重租赁技术,是一种软件架构技术,它是在探讨与实现如何于多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。在云计算时代,多租户技术在共用的数据中心以单一系统架构与服务提供多数客户端相同甚至可定制化的服务,并且仍然可以保障客户的数据隔离。目前各种各样的云计算服务就是这类技术范畴,例如阿里云数据库服务(RDS)、阿里云服务器等等 ↩︎