1.为什么基于Docker搭建?
-
资源有限
-
虚拟机搭建对机器配置有要求,并且安装mysql步骤繁琐
-
一台机器上可以运行多个Docker容器
-
Docker容器之间相互独立,有独立ip,互不冲突
-
Docker使用步骤简便,启动容器在秒级别
2.利用Docker搭建主从服务器
首先拉取docker镜像,我们这里使用5.7版本的mysql:
docker pull mysql:5.7
然后使用此镜像启动容器,这里需要分别启动主从两个容器
Master(主):
docker run -p 3339:3306 --name master -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
Slave(从):
docker run -p 3340:3306 --name slave -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
注:Master对外映射的端口是3339,Slave对外映射的端口是3340。因为docker容器是相互独立的,每个容器有其独立的ip,所以不同容器使用相同的端口并不会冲突。这里我们应该尽量使用mysql默认的3306端口,否则可能会出现无法通过ip连接docker容器内mysql的问题。(华为云防火墙)详细参考:华为云服务器无法正常访问端口
3.配置Master和slave
通过docker exec -it 627a2368c865 /bin/bash
命令进入到Master和Slave容器内部,cd /etc/mysql
切换到/etc/mysql目录下,然后vi my.cnf
对my.cnf进行编辑。此时会报出bash: vi: command not found
,需要我们在docker容器内部自行安装vim。使用apt-get install vim or yum install vim
命令安装vim
master(主)
[mysqld] ## 同一局域网内注意要唯一 server-id=100 ## 开启二进制日志功能,可以随便取(关键) log-bin=mysql-bin
重启docker容器docker stop master docker start master
安装脚本
yum install initscripts -y
进入mysql: mysql -u root -p,输入密码;
1. create user 'slave'@'%' identified by '123456'; 2. grant replication slave,replication client on *.* to 'slave'@'%'; 3. flush privileges;刷
Slave(从)
[mysqld] ## 设置server_id,注意要唯一 server-id=101 ## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用 log-bin=mysql-slave-bin ## relay_log配置中继日志 relay_log=edu-mysql-relay-bin
重启docker容器docker stop slave docker start slave
4.连接Maste和Slave
master(主)
进入mysql: mysql -u root -p,输入密码;
执行命令:show master status;
slave(从)
执行命令: change master to master_host='172.17.0.3',master_user='slave', master_password='123456',master_port=3306, master_log_file='mysql-bin.000005', master_log_pos=0,master_connect_retry=10, get_master_public_key=1; 注意:记得加上get_master_public_key=1,因为mysql8.0以上需要使用RSA加密来传输密码。
master_host:Master的地址,是容器的对立IP,可以通过以下命令查看
docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称|容器id
5.查看主从同步状态
进入Slave中的mysql终端执行命令:show slave status \G;
-
正常情况下,SlaveIORunning和SlaveSQLRunning都是No,因为还没开启主从复制过程。使用以下命令,即可开启主从复制:
start slave # 此外 若想关闭则 stop slave;即可
在Master创建一个数据库,然后检查Slave是否存在此数据库,如果同步就说明成功了
Slave_SQL_Running: No
Slave_IO_Running: No
1.程序可能在slave上进行了写操作
2.可能是slave机器重起后事务回滚造成的,一般是事务回滚造成的
解决办法: mysql> stop slave ; mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1; mysql> start slave ;
详情参考:MySQL主从同步故障:Slave_SQL_Running:No 两种解决办法_slave_sql_running: no_Lucky@Dong的博客-CSDN博客
理论:
1.什么时候用读写分离
1、 你的系统写入数据不多但是存在大量的读取数据功能。 2、读写分离并不取决于你的数据量还是取决于你的并发量,访问用户多才需要类似的 功能。 3、读写分离其实是个比较低端的处理读取并发量的操作,因为还是有对数据库的访问 操作的,但是读写分离相对于其它处理方式而言的好处在于时效性比较高和对系统要求 比较低。 4、读写分离在效率上是低于页面静态化和缓存服务的,但是好处是不用改动系统代码, 因为都是连接数据库。 5、数据量大的情况下使用的技术不是读写分离,是分表和分库,或者使用分布式存储 引擎,读写分离不能解决数据量大的问题。 6、系统写入操作并发量大不适合使用读写分离,至于需要什么技术看你的具体业务需 求,而且大量写入操作本身就是个难以处理的大数据问题,但是读写分离从一定程度上 减轻写入操作的负担。
2.MySQL主从复制原理
1. master 将操作语句记录到 binlog 日志中 2. salve 服务器会在一定时间间隔内对 master 二进制日志进行探测其是否发生改变,如 果发生改变 3. salave 开启两个线程:IO 线程和 SQL 线程 1)IO 线程:负责读取 master 的 binlog 内容到中继日志 relay log 里; 2)SQL 线程:负责从 relay log 日志里读出 binlog 内容,并更新到 slave 的数据库里 (保证数据一致) 这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的, 也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要 的点了,由于从库从主库拷贝日志以及串行执行 SQL 的特点,在高并发场景 下,从库的数据一定会比主库慢一些,是有延时的。所以经常出现,刚写入主 库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。 如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。所以 MySQL 实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题。这个所谓半同步复制,也叫 semi-sync 复制,指的就是主库写入 binlog 日志之后,就会强制立即将数据同步到从库,从库将日志写入自己本地 的 relay log 之后,接着会返回一个 ack 给主库,主库接收到至少一个从库 的 ack 之后才会认为写操作完成了。所谓并行复制,指的是从库开启多个线程,并行读取 relay log 中不同库 的日志,然后并行重放不同库的日志,这是库级别的并行。
3.解决主从复制延迟有几种常见的方法
1. 写操作后的读操作指定发给数据库主服务器 例如,注册账号完成后,登录时读取账号的读操作也发给数据库主服务器。这种方式和业务 强绑定,对业务的侵入和影响较大,如果哪个新来的程序员不知道这样写代码,就会导致一 个 bug。 2. 读从机失败后再读一次主机 这就是通常所说的“二次读取”,二次读取和业务无绑定,只需要对底层数据库访问的 API 进 行封装即可,实现代价较小,不足之处在于如果有很多二次读取,将大大增加主机的读操作 压力。例如,黑客暴力破解账号,会导致大量的二次读取操作,主机可能顶不住读操作的压 力从而崩溃。 3. 关键业务读写操作全部指向主机,非关键业务采用读写分离 例如,对于一个用户管理系统来说,注册 + 登录的业务读写操作全部访问主机,用户的介 绍、爱好、等级等业务,可以采用读写分离,因为即使用户改了自己的自我介绍,在查询时 却看到了自我介绍还是旧的,业务影响与不能登录相比就小很多,还可以忍受。
4.造成 mysql 同步延迟常见原因
1)网络:如主机或者从机的带宽打满、主从之间网络延迟很大,导致主上的 binlog 没有 全量传输到从机,造成延迟。 2)机器性能:从机使用了烂机器?比如主机使用 SSD 而从机还是使用的 SATA。 3)从机高负载:有很多业务会在从机上做统计,把从机服务器搞成高负载,从而造成从 机延迟很大的情况 4)大事务:比如在 RBR 模式下,执行带有大量的 delete 操作,这种通过查看 processlist 相关信息以及使用 mysqlbinlog 查看 binlog 中的 SQL 就能快速进行确认 5)锁: 锁冲突问题也可能导致从机的 SQL 线程执行慢,比如从机上有一些 select .... for update 的 SQL,或者使用了 MyISAM 引擎等。
def __init(): self.conn = .... 主 self.con= pymsql.connect.... 重 def findAll(): self.con1 def innser_to(): self.conn insert update delete select