分布式部署方案
部署多个 Tomcat 服务器,这个就可以用 Nginx 来分发请求给各个服务器,而为了防止单个 Nginx 挂了,这时就可以用热备来再准备个 Nginx,这两个 Nginx 同时去抢请求,没抢到的Nginx就会去监听另一个Nginx(采用心跳监测,就是疯狂Ping它,没返回值的时候就是挂掉了,然后它就可以上位了)。
性能优化
一、构建二级缓存(本地缓存+Redis)
二、通过Redis + RocketMQ 异步处理持久化操作
部署图:
MySQL 读写分离
就是数据库层面为了提高性能,可以采用主从模式(基于bin log 与 relay log 实现 )来构建读写分离,即主数据库只进行写操作,从数据库只进行读操作。同时这个从数据库对主数据库起一个备份的作用,以防意外。
这两个主从数据库怎么进行数据同步呢?
首先,当执行DML语句时,主数据库会以事务为单位来存一个 bin log
(记录SQL的日志)。这时从数据库就会根据 bin log
来同步与主数据库的数据(这个同步操作由从数据库的 IO线程 去写入自己的 relay log
,然后再由 SQL线程 去写会数据库完成同步)。
并且,从数据库还会拍摄快照,以防止主数据库被破坏了导致数据丢失。
示意图:
MySQL 的分布式事务
多个数据库(可以是不同的数据库类型)之间如何保证事务呢?就比如,你从农行转账到工行,如何保证两边银行的数据不会出问题?
这时就需要一个协调者(事务管理器)。首先,应用程序会告诉协调者开始事务,这时协调者给数据库发个 start 命令,然后数据库就会去执行他们的SQL语句。执行完后,协调者会来发送一个 end 命令,start - end 期间数据库执行了什么就会被协调者记录下来。
重点,这时该提交事务了。由协调者来采用二阶段提交方式来提交事务。它会先给数据库发一个 prepare 命令来确认下数据库是否准备好提交事务了(即SQL是否执行完了)。都可以提交了的话,它就会提交事务完成操作,如果有其中一个数据库不能提交的话,就会回滚,全都不能提交。
那如果事务管理器这个协调者挂了呢?所以,这个机制不是一个100%能保证事务的机制。当然也可以采用重试机制,由程序自己去检查事务管理器挂了没(采用心跳检验),或者自己去看数据库之间的状态。
MySQL 的内部分布式事务
主服务器会先写自己的 bin log
,这时可能从服务器就会同步到自己的 relay log
里。而 InnoDB 引擎为了保证持久性,会去存 redo log
,如果这时第三步挂了那就会出问题。因为第一步与第三步必须保证事务!
那么为了解决这问题,就要采用分布式事务。这时第一步 InnoDB 会先在存数据前prepare下(先打个标记),然后再去写 bin log
和 redo log
。如果这时 redo log
没写成功,由于第一步记录了的,发现没写成功,就会去从 bin log
里恢复 redo log
。这样就解决了!
当然,面试官刨根问底,刨到这程度也就差不多了,再刨那我真吐了…