mysql 数据同步
数据库扩展解决什么问题? -->单点问题
- 热备份
- 多活
- 故障切换
- 负载均衡
- 读写分离
常规复制架构(90%以上使用率): master-slave
- master接收写请求
- slave分布接收所有读请求
–>缺点:
–1) 单点master问题,
–2) slave过多,会影响master性能
–3) master机器维护时, 需要把某个slave提成master,选哪个是问题
–4) 某个slave提成master之后, 存在当前master和原master数据不一致情况,且原master与新master节点binlog和pos位置不一致
多主架构: master-master,主主复制
- 一个master用来写,另一个用来读—>读写必须分开,不能两个都写,否则会产生数据冲突
- 解决单点master问题
- 配合第三方工具(如keepalived)做到ip漂移,如果写master挂了,ip会漂到读master上,不影响
级联复制架构: master-slaves-slaves
- 如果读操作太多,可以做级联同步,即master下挂slave,slave下再挂N层slave,用于减少master在同步时的io,弊端:延时高
多主级联复制架构: master-master-slaves-slaves
- 解决级联架构里单点master问题,所有slaves挂在读master上进行数据同步
复制简析:
默认同步复制:master写完binlog后直接提交修改到engine,产生一个事件到master的dump thread,然后dumpthead异步通知slave来master拉数据
缺点:不知道slave是否复制成功,可能会丢数据
增强版半同步复制 :master写binlog后就等待,slave成功拉取到binlog信息并保存到relay-bin日志后会向master反馈ACK确认信息,master接收到ack信息后,再提交到engine,这样就可以很好的保证数据一致性
缺点:
- slave宕机时,master会在最大同步等待时间10s过后,半同步复制会转变成异步同步,因为等待时间很长,会导致大量事务堆积
- 事务提交后要等待slave复制完,才会执行,会消耗时间
docker 启动mysql
docker run --name mysql3307 -p 3307:3306 --privileged=true -ti -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=mall -e MYSQL_USER=syncUser -e MYSQL_PASSWORD=123456 -v /home/docker-data/mysql/3306/conf:/etc/mysql/conf.d -v /home/docker-data/mysql/3306/data/:/var/lib/mysql -v /home/docker-data/mysql/3306/logs/:/var/log/mysql -d mysql:5.7
master配置
server-id=10
#开启复制功能
log-bin=mysql-bin #必须要,表示开启复制
auto_increment_increment=2 # id自增步长(master数),为了防止多主情况下,id冲突
auto_increment_offset=1 #id从几开始自增
lower_case_table_names=1 #忽略大小写
#binlog-do-db=xxxx #要同步的数据库
#binlog- ignore-db=xxxx #要忽略的数据库
--创建从复制用户,赋值replication slave ,file,replication client
show master status; --查看binlog文件名和pos
slave中设置master信息
change master to
master_host='127.0.0.1' ,master_port='3307',master_user='xxxx',master_password='123456',
master_log_file='xxxxx.log',master_log_pos=654 ;
show slave status; --查看从库同步状态
start slave; --启动同步
show processlist; --查看用户进程列表,以查看同步启动情况
如果主库已经有数据了, 新建从库来复制?
- 备份master数据,使用mysqldump -uroot -p123456 --databases abc >backup.sql
- 锁表 flush table with read lock;
- 解锁 unlock tables;
- 数据导入到从库 mysql -uroot -p123456 <backup.sql;
- 从库重新change master信息,然后start slave
master监控binlog文件变化
- 进入mysql/data目录
- 查看mysql-bin.index文件, 查看最新的binlog文件是哪个
- tail -f binlog文件
slave监控relay-log文件变化
- 进入mysql/data目录
- 查看relay-log.info文件, 查看最新的relaylog文件是哪个;
查看master.info文件可以获得当前对应主机的binlog文件是哪个,当前同步pos是哪个 - tail -f 当前relay-log文件.
采用加强版半同步复制
-
主从都需要安装插件
主库:install plugin rpl_semi_sync_master soname ‘semisync_master.so’;
从库:install plugin rpl_semi_sync_slave soname ‘semisync_slave.so’;
查看插件安装情况: show plugins; -
查看主库半同步状态:show global status like “%sync%”;
-
先启用从库上的参数,最后启用主库的参数。
从库:set global rpl_semi_sync_slave_enabled = {0|1}; #1:启用,0:禁止
主库:
set global rpl_semi_sync_master_enabled = {0|1}; # 1:启用,0:禁止
set global rpl_semi_sync_master_timeout = 10000; # 单位为ms
注: slave的io_thread 必须先关闭再开启, 否则半同步不生效 -
查看半同步参数配置:show global variables like “%sync%”;
可以通过 set global xxxxxxx=xx 来修改配置
stop/start slave io_thread;
-
如果master等待slave返回ack超时(默认10s),会自动关闭半同步模式
主主配置
两台机器都开启binlog(注意配置自增步长和偏移,否则互相同步数据可能会主键冲突), 然后互相指为自己的master主机就行了,配置方式与主从配置一样
keepalived双活
keepalived 要对应具体的mysql主从建立多个实例, 实例间也有主从关系,只有master的keepalived 会虚拟出一个网卡对外提供服务,slave的keepalived不提供访问; 当keepalived检测到master库挂掉, master的keepalived会把自己杀掉,slave的keepalived检测到master已挂,会马上虚拟出同样的网卡ip来提供服务,这样外部访问是不知道内部这个切换过程的,依然正常使用服务,但是访问的已经变成了slave…
总结:一旦mkeep挂掉, ip会漂移到skeep; 如果mkeep再启动, ip会重新漂移回mkeep
PS: keepalived 通信方式
图片截自:https://blog.csdn.net/liuhuan_study/article/details/81603573