对基于Spring MVC框架开发的Web项目,我们可以通过实现接口 org.springframework.web.servlet.HandlerExceptionResolver,来定制自己工程的全局异常处理类,做到异常统一捕获处理,避免服务器端敏感信息直接暴露到客户端,根据情况构造统一的Json结构返回前端,以错误提示的方式展示给用户。
1 | @Order(-1) |
对基于Spring MVC框架开发的Web项目,我们可以通过实现接口 org.springframework.web.servlet.HandlerExceptionResolver,来定制自己工程的全局异常处理类,做到异常统一捕获处理,避免服务器端敏感信息直接暴露到客户端,根据情况构造统一的Json结构返回前端,以错误提示的方式展示给用户。
1 | @Order(-1) |
简单来说就是保证主SQL(Master)和从SQL(Slave)的数据是一致性的,向Master插入数据后,Slave会自动从Master把修改的数据同步过来(有一定的延迟),通过这种方式来保证数据的一致性,就是主从复制
因为数据都是相同的,所以当Master挂掉后,可以指定一台Slave充当Master继续保证服务运行,因为数据是一致性的(如果当插入Master就挂掉,可能不一致,因为同步也需要时间),当然这种配置不是简单的把一台Slave充当Master,毕竟还要考虑后续的Salve同步Master,当然本文并不是将高可用的配置,所以这里就不多讲了
因为读写分离也算是负载均衡的一种,所以就不单独写了,因为一般都是有多台Slave的,所以可以将读操作指定到Slave服务器上(需要代码控制),然后再用负载均衡来选择那台Slave来提供服务,同时也可以吧一些大量计算的查询指定到某台Slave,这样就不会影响Master的写入以及其他查询
一般我们都会做数据备份,可能是写定时任务,一些特殊行业可能还需要手动备份,有些行业要求备份和原数据不能在同一个地方,所以主从就能很好的解决这个问题,不仅备份及时,而且还可以多地备份,保证数据的安全
可以一个业务模块读取一个Slave,再针对不同的业务场景进行数据库的索引创建和根据业务选择MySQL存储引擎
主从复制支持2种扩展方式
向上扩展或者纵向扩展,主要是提供比现在服务器更好性能的服务器,比如增加CPU和内存以及磁盘阵列等,因为有多台服务器,所以可扩展性比单台更大
向外扩展或者横向扩展,是指增加服务器数量的扩展,这样主要能分散各个服务器的压力
无可厚非的是搭建主从肯定会增加成本,毕竟一台服务器和两台服务器的成本完全不同,另外由于主从必须要开启二进制日志,所以也会造成额外的性能消耗
Slave从Master复制过来肯定是会有一定的数据延迟的,所以当刚插入就出现查询的情况,可能查询不出来,当然如果是插入者自己查询,那么可以直接从Master中查询出来,当然这个也是需要用代码来控制的
主从复制主要是针对读远大于写或者对数据备份实时性要求较高的系统中,因为Master在写中需要更多操作,而且只有一台写入的Master(因为我目前只会配置一台写入Master,最多就是有从Master的Slave,用来在Master挂掉后替换成Master,平时不对外进行服务),所以写入的压力并不能被分散,当然如果直接怎么解决这个问题的话,欢迎留言指教
MySQL5.6开始主从复制有两种方式:基于日志(binlog)、基于GTID(全局事务标示符)。
本文只涉及基于日志binlog的主从配置
1、Master将数据改变记录到二进制日志(binary log)中,也就是配置文件log-bin指定的文件,这些记录叫做二进制日志事件(binary log events)
2、Slave通过I/O线程读取Master中的binary log events并写入到它的中继日志(relay log)
3、Slave重做中继日志中的事件,把中继日志中的事件信息一条一条的在本地执行一次,完成数据在本地的存储,从而实现将改变反映到它自己的数据(数据重放)
1、主从服务器操作系统版本和位数一致
2、Master和Slave数据库的版本要一致
3、Master和Slave数据库中的数据要一致
4、Master开启二进制日志,Master和Slave的server_id在局域网内必须唯一
两台或两台以上安装了相同版本的MySQL(我没有试过不同版本会不会有问题,有兴趣的可以试试),当然这个可以用虚拟机或者Docker代替,个人推荐用Docker,比虚拟机消耗少太多了,当然用起来可能没有虚拟机那么方便,但是却不用挨个环境配置了
不同的系统my.cnf路径不同,所以我们只讲解牵扯修改的地方。添加配置
1 | [mysqld] |
1、在Master上过滤二进制日志中的事件
2、在Slave上过滤中继日志中的事件。
在Master上执行的SQL语句,在Slave上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。一旦发现没法精确复制时,会自动选着基于行的复制
把改变的内容复制到Slave,而不是把命令在Slave上执行一遍。从MySQL5.0开始支持
默认采用基于语句的复制,一旦发现基于语句的无法精确的复制时,就会采用基于行的复制
1 | CREATE USER 'slave'@'%' IDENTIFIED BY '123456'; |
这里主要是要授予用户REPLICATION SLAVE权限和REPLICATION CLIENT权限
1 | [mysqld] |
如果Slave为其它Slave的Master时,必须设置bin_log。配置完成后重启mysql
保证Master和Slave除不同步的数据库,其他库的数据一致
在Master中执行1
show master status;
记录下返回结果的File列和Position列的值
在Slave中执行1
change master to master_host='192.168.1.100', master_user='slave', master_password='123456', master_port=3306, master_log_file='edu-mysql-bin.000001', master_log_pos=1389, master_connect_retry=30;
上面执行的命令的解释:1
2
3
4
5
6
7
8
9
10
11
12
13master_host='192.168.1.100' ## Master的IP地址
master_user='slave' ## 用于同步数据的用户(在Master中授权的用户)
master_password='123456' ## 同步数据用户的密码
master_port=3306 ## Master数据库服务的端口
masterlogfile='edu-mysql-bin.000001' ##指定Slave从哪个日志文件开始读复制数据(Master上执行命令的结果的File字段)
masterlogpos=429 ## 从哪个POSITION号开始读(Master上执行命令的结果的Position字段)
masterconnectretry=30 ##当重新建立主从连接时,如果连接建立失败,间隔多久后重试。单位为秒,默认设置为60秒,同步延迟调优参数。
show slave status;
可看到SlaveIOState为空, SlaveIORunning和SlaveSQLRunning是No,表明Slave还没有开始复制过程。相反SlaveIORunning和SlaveSQLRunning是Yes表明已经开始工作了
1 | start slave; |
查询查看主从同步状态,会发现SlaveIORunning和SlaveSQLRunning是Yes了,表明开启成功
生产环境,往往需要更新/删除大量的数据,由于很可能消耗太多的IO资源,对于生产繁忙的系统,需要小心,以避免对生产环境造成影响。
删除大量数据还有一些副作用,比如主从延时、数据文件无法收缩、锁表等。
以下是一些要指引和规则:
1、批量删除,这样往往可以工作得更快,你可能需要在每次批量删除前sleep一段时间,控制删除的频率,这样的目的是减少对生产系统的IO冲击,把符合平均分布,避免从库滞后太多;
2、可以考虑分区表技术,我很少用分区表,但删除一个分区,显然比删除大量数据简单方便的多,这也是分区表清理/归档数据的优势所在;
3、按照主键的序列分批分批,或者基于时间分批分批,你总可以找到一种方式批量删除,如果实在没有批量删除的方式,可能你的表结构设计得不好;
4、基于硬件的性能,每批删除的记录数,可以选择几百到几千到几万的数据量,但不要太大,MySQL很难同时处理好大事务和随机小事务;
5、如果要删除大部分数据,那么可以考虑的方式是,创建一个新表,insert要保留的数据,然后切换表;
6、对于大表(InnoDB)删除大量数据,如果是一个很大的事务,中止删除数据的操作,可能需要几倍的时间用于回滚,导致严重的IO瓶颈,而批量删除可以让我们的回滚恢复得快得多。
7、需要留意空间的释放,选择独立表空间会更有利于释放空间。
1 | public class Cache { |
1 | public class CacheManager { |
1 | class Test { |
Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.
1 | $ hexo new "My New Post" |
More info: Writing
1 | $ hexo server |
More info: Server
1 | $ hexo generate |
More info: Generating
1 | $ hexo deploy |
More info: Deployment