一、主从复制结构

binlog dump --- io thread  ---  relay log ---- sql thread

1、总体讲解

主从复制时是异步的
半同步是在主从架构下安装插件来达到半同步的
半同步的优点:保证至少一个节点的数据和主节点的数据一致,缺点影响性能
导致主从不同步的原因是
现在的服务器都是单核多线程或者多核多线程,导致主节点可以同时执行多条读写操作,而记录二进制日志则必须按顺序有先后的记录,从节点在一条一条复制过去,生成中继日志,再执行语句。
多个库复制的话,可以复制过去生成中继日志,sql线程可以每个库生成一个线程,同时执行,增加性能,不能一个库多线程执行中继日志

2、工作原理

开启主的二进制日志
从节点从主节点复制二进制日志到本地生成中继日志,并执行中继日志命令,生成库和表
从节点开启中继日志,关闭二进制日志

3、复制实际场景

主从都是0数据开始
主节点上运行一段时间有不少数据
可以先备份,导入到从,在复制最近更新的二进制日志

4、主从实验

主从复制前提

主从复制实验环境准备

从节点版本高于主节点或者等于主节点以便于兼容

两节点都安装好mysql且能正常工作

node1 172.16.11.143
node2 172.16.11.144
注意权限问题
/mydata/data  mysql.mysql
/usr/local/mysql root.mysql
node1
vim /etc/mysql/my.cnf
二进制日志和mysql数据不能放在同一个磁盘上,最好的是做异地备份
[mysqld]
1、log-bin=/mydata/binlogs/master-bin 开启二进制日志
chown -R mysql.mysql /mydata/binlogs/master-bin
datadir = /mydata/data
2、保证主从的server-id = 1   不一致
3、创建有复制权限的账号
传统授权
grant all on *.* to 'tom'@'127.0.0.1' identified by '1234';
replication slave, replication client, 两种权限
grant replication slave, replication client on *.* to 'tom'@'172.16.%.%' indetified by '1234';
flush privileges;
4、查看日志起点
show master status;
连接主服务的命令的使用方法
MariaDB [(none)]> help change master to
Name: 'CHANGE MASTER TO'
Description:
Syntax:
CHANGE MASTER TO option [, option] ...
option:
    MASTER_BIND = 'interface_name'
  | MASTER_HOST = 'host_name'  #指明要连接的主节点,值类型字串
  | MASTER_USER = 'user_name'  #具有复制权限的账号,值类型为字串
  | MASTER_PASSWORD = 'password'#上述用户的密码,值类型为字串
  | MASTER_PORT = port_num
  | MASTER_CONNECT_RETRY = interval
  | MASTER_HEARTBEAT_PERIOD = interval
  | MASTER_LOG_FILE = 'master_log_name'
  | MASTER_LOG_POS = master_log_pos
  | RELAY_LOG_FILE = 'relay_log_name' #复制起点,主节点上二进制日志,值类型为字串(要加'')
  | RELAY_LOG_POS = relay_log_pos     #复制起点,主节点上二进制日志中起始事件的位置,值类型为数值
  | MASTER_SSL = {0|1}
  | MASTER_SSL_CA = 'ca_file_name'
  | MASTER_SSL_CAPATH = 'ca_directory_name'
  | MASTER_SSL_CERT = 'cert_file_name'
  | MASTER_SSL_KEY = 'key_file_name'
  | MASTER_SSL_CIPHER = 'cipher_list'
  | MASTER_SSL_VERIFY_SERVER_CERT = {0|1}
  | IGNORE_SERVER_IDS = (server_id_list)

node2

[mysqld]
1、#log-bin = /binglogs-bin
2、server-id = 11   确保与主节点不一致
datadir = /mydata/data
3、relay-log = /mydata/relaylogs/relay-log  启用中继日志
4、使用有复制权限的账号连接master
mysql
change master to master_host='172.16.11.143', master_user='tom', master_password='1234', master_log_file='master-bin.000001', master_log_pos=495;
验证查看是否生成中继日志
ls /mydata/relaylogs/
mysql
show slave status\G; #显示连接主节点的状态信息
Slave_IO_State:
                  Master_Host: 172.16.100.7
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 495
               Relay_Log_File: relay-log.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No

5、启动io thread 以及 sql thread

#help start slave;#获取start slave的帮助
#start slave to_io_thread;
#start slave sql_thread;
start slave #同时启用两个
show slave status\G;
Slave_IO_State:
                  Master_Host: 172.16.100.7
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: master-bin.000001
          Read_Master_Log_Pos: 530
               Relay_Log_File: relay-log.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: master-bin.000001
             Slave_IO_Running: yes
            Slave_SQL_Running: yes
也可以停止线程
stop slave
主从复制基本完成,验证是否成功
主节点
mysql
create database master;
show databases;
从节点查看
mysql
show databases;

6、主从复制的完善问题

1、如何限制从服务器只读,才能保持主从数据一致

show global variables like '%read%'
更改slave的全局服务器变量read_only为on
注意:此限制对于拥有的super权限用户无效
主节点
grant create,update,insert,delete,alter on master.* to testuser@'172.16.%.%' identified by '1234';
flush privileges;
从节点上授权只读
help  set;
set global read_only = 1;
如果要让它永久有效的话
vim /etc/mysql/my.cnf
[mysql]
read_only = 1
然后让testuser来管理master这个数据库,主库他能增删改查,从库他只能对此库进行读操作
flush tables with read lock;使全部用户不能修改,且此会话不能关闭

2、如何保证主从复制时的事物安全

如果mysql比较繁忙它会把二进制日志缓存在内存中,不繁忙时才会把他写到内存中 
前提:mysql对二进制日志事件数据会缓冲
在master上设置如下参数
???手动开启事物,默认out_canmake
sync_binlog = 1  事物一提交,就必须同步二进制日志,这样会降低性能,但是数据比较重要。
root 用户登录
主库设置
set global sync_binlog = 1;

3、半同步复制

主从复制是工作是异步的,会导致从节点得不到主节点的全部数据。
半同步:主节点必须要等待一个从节点把数据完整复制过去。
mysql 以前的版本不支持,到5.8以后的版本才支持,且以补丁方式提供
由goolgel提供,以插件方式提供
ls /usr/local/mysql/lib/plugin 中
主节点插件:semisync_master.so
从节点插件:semisync_slave.so

二、半同步配置

前提:在主从同步机制上实现

关闭从节点上的同步机制

#stop slave;

help install #获取命令帮助

node1

可以在配置文件中配置或者#mysql中

1、安装插件

install plugin rpl_semi_sync_master soname 'semisync_master.so';
show global variables like '%semi%; #查看安装后提供的变量
开启状态
等待时间
跟踪级别
没从节点 为关闭

2、开启插件并配置

set global rpl_semi_sync_master_enabled = 1;
set global rpl_semi_sync_master_timeout=1000;
要想永久有效要写到配置文件当中

node2

1、安装插件

install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
show global variables like '%rpl_semi%;#查看变量

2、开启插件功能

set global rpl_semi_sync_slave_enabled = 1;
开启同步
start slave;
验证半同步是否配置成功
主节点上  show global status like '%semi%;
如果有从节点的信息就说明半同步成功
!!!如果主节点联系不到从节点就会自动降级为同步模式;

4、复制过滤

让slave仅复制有限的几个数据库,甚至于仅复制某数据库内有限的几张表的机制

1、在主节点上过滤

在向二进制日志记录事件时,仅记录指定数据库或表的相关操作
优点节约带宽,提高性能,缺点基于二进制还原数据时较麻烦
binlog_do_db =  #数据库白名单
binlog_ignore_db = #数据库黑名单
只能在库级别

2、在从节点上过滤

仅从中继日志中读取指定的数据库或表的相关事件并应用于本地
replicate_do_db =
replicate_ignore_db =
replicate_do_table =
replicate_ignore_table =
正则表达式匹配的库和表
replicate_wild_do_table =
replicate_wild_ignore_table =

5、半道复制

从节点赶不上主节点

可以把从服务器的数据给删除,中继日志删除

主的也可以删除

但是要确保能正常工作

前提先配置好主从同步的框架,不让不行,这里就不说啦,上面有确保。。。。

导入一个数据库到主节点

主节点

mysql -u root -h 127.0.0.1 -p < hellodb.sql
/usr/local/mysql/bin/mysqldump --all-databases --lock-all-tables --master-data=2 > /tmp/all.sql
scp /tmp/all.sql 172.16.1.144:/root
grant replication slave, replication client on *.* to 'tom'@'172.16.%.%' indetified by '1234';
主节点
mysql -u root -h 127.0.0.1 -p > /root/all.sql
注意关闭二进制日志
cat /all.sql
change master to master_host='172.16.11.143', master_user='tom', master_password='1234', master_log_file='master-bin.000001', master_log_pos=7089;

6、数据库的动静分离软件

语句路由:(r/w splitter)读写分离器
amoeba 淘宝贡献的
mysql-proxy mysql官网提供(处于测试中)
atlas  360 提供
dbrelay 商业软件 淘宝使用
跨网络的复制
***
ssl

7、mysql的高可用方案

mysql的HA + 主从复制
corosync+pacemaker+crm+drbd(iscsi)+主从复制(一主多从,主的挂啦,从的直接提升为主,{注意数据同步的关系,可能要损失一部分数据})
mysql的高可用
master HA :切换一分钟
多主模型 :不变维护
GTID:快速提升其中某一个从节点为新的主节点
mysql cluster 不实用,太贵
建议
corosync+pacemaker+crm+drbd(iscsi)+主从复制(一主多从,主的挂啦,从的直接提升为主,{注意数据同步的关系,可能要损失一部分数据})
结构设置成环状M/S ?维护起来较麻烦
一主多从
实现负载均衡
lvs读写分离器
语句路由
反范式
以空间换时间
多表存储为提高性能改为单表存储
mmm的实现

三、主主复制结构

原理讲解

1、双方节点都得有创建具有复制权限的用户
2、双方都得启用中继日志和二进制日志
3、为保证具有自动增长功能的字段能正确生成ID,需要配置两个节点分别使用偶数或奇数ID号
4、都要把对方配置为自己的主节点
node1 172.16.11.143
node2 172.16.11.144
mariadb 5.10
前提
主主复制前提
主主复制实验环境准备
两节点版必须一致
初始化
mkdir /mydata/relaylogs -pv
mkdir /mydata/binlogs -pv
chown -R mysql.mysql /mydata/binlogs
chown -R mysql.mysql /mydata/relaylogs

node1

[mysqld]
server-id=
log-bin=
relay-log=
auto-increment-increment = 2
auto-increment-offset = 1

node2

[mysqld]
server-id=
log-bin=
relay-log=
auto-increment-increment = 2
auto-increment-offset = 2

实战操作
###################################################################################
node1
vim /etc/mysql/my.cnf
datadir = /mydata/data
log-bin=/mydata/binlogs/master1-bin
relay-log=/mydata/relaylogs/relay-log
server-id = 1
auto-increment-offset = 1
auto-increment-increment = 2
service mysqld restart
mysql
grant replication slave, replication client on *.* to 'tom'@'172.16.%.%' indetified by '1234';
change master to master_host='172.16.11.144', master_user='tom', master_password='1234', master_log_file='master-bin.000002', master_log_pos=495;
对方节点的 show master status\G;
start slave;
show slave status;
###################################################################################
node2
vim /etc/mysql/my.cnf
datadir = /mydata/data
log-bin=/mydata/binlogs/master2-bin
relay-log=/mydata/relaylogs/relay-log
server-id = 11
auto-increment-offset = 2
auto-increment-increment = 2
service mysqld restart
mysql
grant replication slave, replication client on *.* to 'tom'@'172.16.%.%' indetified by '1234';
show master status;
change master to master_host='172.16.11.143', master_user='tom', master_password='1234', master_log_file='master-bin.000001', master_log_pos=495;
start slave;
show slave status;
###################################################################################

验证可以分别在各个节点上创建库,创建表,去对方看

如果我们关闭其中一个节点,再启动,它会自动变为原来的模式,互为主从,或者双主

原因是

cat /mydata/data master.info  #账号信息

cat /mydata/data relay-log.info #复制二进制文件和文件的起点

保存了主从配置的具体信息,所于我们要保证这两个文件的安全


四、日志相关方面的信息

1、中继日志会自动清除

二进制日志则不会

show master logs;
flush logs; #滚动二进制日志
help purge; #清除二进制日志的帮助命令
show master logs;
purge master logs to 'masterl-bin.000002'; #清除masterl-bin.000002以前的二进制日志
最好用命令删除,不要去目录下删除,以免发生问题
二进制日志可以定义滚动内容
默认它是达到1G的容量才滚动,但是不会自动清除
show global variables like '%expire%';
可以设置默认二进制日志清除几天前的,最好不要改
我们备份好了,可以自动用purge来清理

2、mysql 的ssl实现

show global variables like '%ssl%';
have_openssl disabled maridb 在安装时不支持ssl,或者没有编译启用我们要想实现,必须的重新编译
have_ssl  disabled  我们可以手动启用
mysql 5.5 默认ssl启动
help  change master to;#获取帮助
具于行、具于语句复制
基于行可能为比较优的选择


五、复制的管理与维护

1、监控复制

主节点

show master status;
show binlog events;
show binary logs;

从节点

show slave status;

2、判断节点是否延迟

show slave status;
Seconds_Behind_Master:0
显示延迟
如果关闭线程
stop slave;
show slave status;
Seconds_Behind_Master:null
显示0不一定就是正常的,有时候其它地方或报错

3、如何确定master/slave节点数据是否一致

表自身的checksum
使用percona-tools中的pt-table-checksum

4、数据不一致时的修改方法

查看从服务器,中继日志跟得上主库,但是数据不一致,重复设定复制机制

使用mysqldump从master导出slave不同的数据,重新同步

5、为从库设定新的主库

在从库停止复制线程,而后重新设定change master to 命令即可提升一个从库为主库
1、停止向老的主库写入数据
2、让计划提升为主库的从库赶上从库
3、提升从库为主库
4、修改其他从库的指向

计划外提升一个从库为主库

1、确定那个从库的数据为最新最全

show slave status\G
master_log_file:
read_master_log_pos
2、等待所有的从库执行从从库那复制而来的生成的中继日志
3、在提升为主库的从库上stop slave,而后让各从库指向新的主库
4、再次比较主库和从库上的两个参数

6、推荐的复制配置

master
sync_binlog=1
确保每次事物提交之后都能将二进制日志同步到磁盘上
对于innodb存储引擎的场景
innodb_flush_logs_at_trx_commit = 1 #刷新事物
innodb_support_xa = 1 #支持分布式事物
slave:
read_only = 1 # 只读
磁盘io大就不开启下面的,小就开启
sync_master_info = 1 #避免从库意外崩溃,导致数据重复复制
syna_relay_log = 1
sync_relay_log_info = 1
同步主从信息的文件

7、复制场景中问题及解决方案

数据损坏或丢失
1、主库意外关闭
没有设置 sync_binlog=1 会导致数据不同步
2、从库意外关闭
1、sync_master_info = 1 #避免从库意外崩溃,导致数据重复复制
2、可以使用pt-slave-start来启动从库#procena提供的命令会自动修复
3、主库二进制日志文件损坏
二进制磁盘损坏:主库停下来,从库备份,恢复主库
二进制文件本身损坏:从新备份数据,从库恢复,删除主库二进制日志文件,重新记录
4、从库的中继日志文件损坏:查询当前同步点,关闭同步,删除中继日志,重新设定同步点,开启同步
5、server-id出现问题是现象
server-id
主从一致
不会启动
一主多从
从从一致
二进制日志错误
主主一致
二进制日志错误
mysql-5.6的新特性
gtid = uuid + 事物号
新特性主从复制利用gtid复制,不用指定复制起点
multi-threads

8、第三方解决复制的方案

galera cluster --- percona

非关系性数据库

redis  适合存储新闻、微博、跟新较多的
mongodb 反范式设计
durability  持久性
performance 性能
query API 查询接口
features  特性
complexity 复杂性
support 提供支持
mongodb 热区数据、新闻事件
redis 微博(blobs)
mysql 持久事物数据
sphinx 索引搜索
mmm   gtid  ssl  多源复制