最后
这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)
1.2.4.3、创建一个用于slave和master通信的用户账号
mstser数据库操作:
MySQL [(none)]> grant replication slave on *.* to 'myslave'@'192.168.1.9' identified by 'pwd123';
Query OK, 0 rows affected, 1 warning (0.01 sec)
MySQL [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]>
这条sql是授权1.9这台主机,也就是slave,通过myslave这个用户,通过密码pwd123来链接主mysql的操作
1.2.4.4、查看master正在使用的二进制以及位置编号
MySQL [(none)]> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000007 | 602 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
file表示mysql目前正在使用的二进制日志的文件,position
记录了当前执行二进制日志位置。 这两个值需要做保留,从服务器会通过链接到主mysql
,与主的二进制文件的日志进行同步,同时从哪里开始同步是由 Position
来决定。
1.2.4.5、slave数据库进行连接操作
change master to
master_host='192.168.1.8',
master_user='myslave',
master_password='pwd123',
master_port=3306,
master_log_file='mysql-bin.000007',
master_log_pos=602
;
change master to
连接matser数据库master_host
master数据库的地址master_user master
创建slave与master连接的用户名master_password
master创建slave与master连接用户名的密码master_port master
数据库的端口master_log_file
matser数据库正在使用的二进制文件master_log_pos
master数据库执行二进制日志位置
操作:
MySQL [(none)]> change master to
-> master_host='192.168.1.8',
-> master_user='myslave',
-> master_password='pwd123',
-> master_port=3306,
-> master_log_file='mysql-bin.000007',
-> master_log_pos=602;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
MySQL [(none)]>
1.2.4.6、slave数据库启动同步
start slave;
命令
MySQL [(none)]> start slave;
Query OK, 0 rows affected (0.00 sec)
MySQL [(none)]> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.8
Master_User: myslave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000007
Read_Master_Log_Pos: 602
Relay_Log_File: 192-relay-bin.000003
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000007
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 602
Relay_Log_Space: 1230
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 691ede37-7085-11ec-bbac-000c298a92c4
Master_Info_File: /data/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
Slave_IO_Running: Yes
: IO线程开启成功
Slave_SQL_Running: Yes
: SQL线程开启成功
1.2.4.7、验证数据同步
到此刻matser数据库创建,删除,增加,改动,从数据库都会进行实时同步数据. 到此mysql主从复制已实现。
1.3、MySQL主从复制测试
1.3.1、测试主master宕机
主数据库发生停止的情况下,slave的IO线程向master发出请求未能链接成功报错信息如下:
当matser宕机后slave 状态显示error reconnecting to master 'myslave@192.168.1.8:3306' - retry-time: 60 retries: 1
重新连接到主服务器时出错myslave@192.168.1.8:3306’-重试时间:60
1.3.2、测试master主服务器网络连接断开
断开前:
断开后:
查看错误信息:
一旦发生IO发生:error reconnecting to master 'myslave@192.168.1.8:3306' - retry-time: 60 retries: 1
错误问题以下几个方式解决:
- 网络不通,尝试ping测试,检查网络通信问题是否能到达master
- 配置给与权限slave连接主配置的用户名密码错误问题
- 主防火墙以及从数据库防火墙配置限制问题,检查端口出入配置
IO进程去连接主mysql发送请求,如果出现非yes的情况则检查双方服务器数据库的连接问题。包括配置问题,确保网络,配置无误。如果配置无误则检查网络问题,当网络恢复之后,slave IO会重新链接运行。
1.3.3、测试slave数据库宕机,master数据库正常写入,slave还原场景
例如:在一个数据量写入非常庞大的环境当中,主从复制正在运行,突然从数据库意外宕机关机,主数据库还在不断的写入数据。如下:
正常运行复制当中
IO SQL正常读写
slave强制关机
主服务器无法到达从
master使用批量插入10万行数据脚本
此脚本为创建了一个test_yanzan的库创建了一张tb1_db的表,在其中插入10万行数据.
# 批量插入:
#!/bin/bash
HOSTNAME="localhost"
PORT="3306"
USERNAME="root"
PASSWORD="123123"
DBNAME="test\_yanzan"
TABLENAME="tb1\_db"
#create database
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "drop database if exists ${DBNAME}"
create\_db\_sql="create database if not exists ${DBNAME}"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e"${create\_db\_sql}"
#create table
create\_table\_sql="create table if not exists ${TABLENAME}(stuid int not null primary key,stuname varchar(20) not null,stusex char(1)
not null,cardid varchar(20) not null,birthday datetime,entertime datetime,address varchar(100)default null)"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e"${create\_table\_sql}"
#insert data to table
i="1"
while [ $i -le 100000 ]
do
insert\_sql="insert into ${TABLENAME} values($i,'zhangsan','1','21276387261874682','1999-10-10','2017-10-24','beijingchangpingqu')"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e"${insert\_sql}"
let i++
done
#select data
select\_sql="select count(\*)from${TABLENAME}"
mysql -h ${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} ${DBNAME} -e"${select\_sql}"
总计插入时长:10分钟 配置低谨慎使用!
启动slave服务器
slave数据库启动后自动连接到主sql,读取新增日志信息进行同步操作。
正常同步成功:
1.3.4、测试master&slave同时宕机
master & slave 启动后:
可完全正常链接。
1.3.5、MySQL主从复制的致命!操作!
slave开启IO线程后向master发出请求,master为IO线程开启一个dump 线程用来传输二进制日志,随后IO线程将收到的日志信息以及节点信息存放到中继日志当中,SQL线程读取中继日志进行解析写入实现主从同步。 但当slave数据库上例如有db_users
的库文件,此时当主创建slave已存在的db_users
库会发生什么如下:
查看从库slave状态
Error 'Can't create database 'db_users'; database exists' on query. Default database: 'db_users'. Query: 'create database db_users'
错误“无法创建数据库”db_users”;查询中存在“数据库”。默认数据库:“db_用户”。查询:“创建数据库db\u用户”.
以上直接中断SQL线程的结果,提示已经存在某数据库,当我们没有设置mysql主从复制异常脚本时,如果出现此类现象没有任何报警,那么主数据库目前还正在写入数据,比如在此情况下继续在主数据库创建数据。
发现从数据库报错信息没有改变,并且没有同步新的数据,这是因为刚刚主master创建的数据库与slave的数据库相互冲突的结果。 流程是:slave已经存在db_users的库,当master创建db_users库,通过传输最后到中继日志,随后sql线程读取中继日志中的create database db_users
发现已经存在此库,于是报出已经存在的结果,这样的结果导致后续中继日志中的语句不断增加,因为IO线程正常运行不断接收binlog日志写入中继日志,但sql线程断开从此无法同步数据。
解决办法:
以上情况sql线程在执行中继日志中的创建db_users的命令冲突,有一个指令是可以让sql线程跳过此冲突指令如下:
set GLOBAL sql_slave_skip_counter=1;
重新启动slave
或者也可以 stop slave 执行语句 然后开启slave即可。
同步成功
如果执行完之后还是没有解决,或者继续报错,那就一直执行这条语句就可以了,直到解决问题。
1.4、主从复制并不能减轻对数据库的压力
slave并不能提高数据库的效率问题,当并发量写入数据读取数据比较庞大千万级别所有的压力都在master服务器上,master数据库一边要处理写入的数据,一边还要处理读取的数据,还要将binlog日志节点发送到slave的IO线程。太忙了… 因此主从复制是为了读写分离提供服务,这样就可以大大提高数据库的效率问题。
二、MySQL读写分离|应用场景及原理
2.1、应用场景
当用户在应用层创建了一篇文章,通常是以insert
插入形式,代表写入
操作。调度中介服务器检测到用户是写入
操作时,将用户的写入操作请求分发到master
主数据库中,当用户要查询
文章时,中介检测到查询
操作,将查询操作
分配到slave
从数据库中运行。这样就实现了主从读写分离。
中间的分配分发的服务器软件可以通过mysql-proxy来实现。
2.2、MySQL-proxy
mysql-proxy是mysql官方提供的mysql中间件服务,上游可接入若干个mysql-client,后端可连接若干个mysql-server。它使用mysql协议,任何使用mysql-client的上游无需修改任何代码,即可迁移至mysql-proxy上。mysql-proxy最基本的用法,就是作为一个请求拦截
,请求中转
的中间层
:将客户端的请求分发到不同的数据库当中。
2.3、MySQL-proxy部署安装
master | 192.168.1.8 |
---|---|
slave | 192.168.1.7 |
mysqlproxy | 192.168.1.6 |
2.3.1、下载mysql-proxy
官网:https://downloads.mysql.com/archives/proxy/#downloads
或者:
wget https://downloads.mysql.com/archives/get/p/21/file/mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
我的mysqlproxy是centos7.2的操作系统
2.3.2、解压mysql-proxy压缩包
解压操作:
[root@192 ~]# tar zxvf mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/glib-2.16.6-license.txt
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/libffi-3.0.12-license.txt
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/pcre-7.4-license.txt
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/glib-2.16.6/
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/glib-2.16.6/glib-2.16.6-ia64-atomic.patch
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/glib-2.16.6/glib-2.16.6.tar.gz
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/glib-2.16.6/glib-2.16.6-win-cmake.patch
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit/licenses/glib-2.16.6/glib-2.16.6-no-circular-dep.pat
将解压出来的mysql-proxy-0.8.5-linux-glibc2.3-x86-64bi目录copy一份改名为,mysql-proxy.
[root@192 ~]# ls
anaconda-ks.cfg mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
[root@192 ~]# tar zxf mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
[root@192 ~]# ls
anaconda-ks.cfg mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit.tar.gz
mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit
[root@192 ~]# mv mysql-proxy-0.8.5-linux-glibc2.3-x86-64bit /usr/local/mysql-proxy
[root@192 ~]#
2.3.3、配置mysqlproxy
打开/etc/mysql-proxy.cnf
文件输入以下信息:
[mysql-proxy]
# 运行mysql-proxy用户
user=root
# mysql-proxy连接后端mysql服务器的用户
admin-username=mysql_proxy_user
# mysql-proxy连接后端mysql服务器的密码
admin-password=pwd123
# 代理的监听地址端口,默认端口4040
proxy-address=0.0.0.0:4040
#指定后端主master写入数据
proxy-backend-addresses=192.168.1.8:3306
#指定后端从slave读取数据
proxy-read-only-backend-addresses=192.168.1.9:3306
#指定读写分离配置文件位置
proxy-lua-script=/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
#日志位置
log-file=/usr/local/mysql-proxy/logs/mysql-proxy.log
#定义log日志级别,由高到低分别有(error|warning|info|message|debug)
log-level=debug
#以守护进程方式运行
daemon=true
#mysql-proxy崩溃时,尝试重启
keepalive=true
以上设置了写入sql的服务器地址以及读取sql服务器地址信息. 在/usr/local/mysql-proxy/logs
这个logs目录如果没有需要手动创建!
打开/usr/local/mysql-proxy/share/doc/mysql-proxy/rw-splitting.lua
文件修改以下信息:
原:
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 4,
max_idle_connections = 8,
is_debug = false
}
end
改后:
if not proxy.global.config.rwsplit then
proxy.global.config.rwsplit = {
min_idle_connections = 1,
max_idle_connections = 1,
is_debug = false
}
end
# min_idle_connnections参数表示最少多少个连接,才开始读写分离
主从数据库添加授权用户;
给予mysql-proxy.cnf 文件权限,开启mysql-proxy代理
最后
关于面试刷题也是有方法可言的,建议最好是按照专题来进行,然后由基础到高级,由浅入深来,效果会更好。当然,这些内容我也全部整理在一份pdf文档内,分成了以下几大专题:
- Java基础部分
- 算法与编程
- 数据库部分
- 流行的框架与新技术(Spring+SpringCloud+SpringCloudAlibaba)
这份面试文档当然不止这些内容,实际上像JVM、设计模式、ZK、MQ、数据结构等其他部分的面试内容均有涉及,因为文章篇幅,就不全部在这里阐述了。
作为一名程序员,阶段性的学习是必不可少的,而且需要保持一定的持续性,这次在这个阶段内,我对一些重点的知识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。
31)]
- 流行的框架与新技术(Spring+SpringCloud+SpringCloudAlibaba)
[外链图片转存中…(img-N4IU2efR-1715458703531)]
这份面试文档当然不止这些内容,实际上像JVM、设计模式、ZK、MQ、数据结构等其他部分的面试内容均有涉及,因为文章篇幅,就不全部在这里阐述了。
作为一名程序员,阶段性的学习是必不可少的,而且需要保持一定的持续性,这次在这个阶段内,我对一些重点的知识点进行了系统的复习,一方面巩固了自己的基础,另一方面也提升了自己的知识广度和深度。