前 言
订单缓存方案上线之后,我们以为又开启了岁月安好的日子,但是,在一周后的某一天,DBA直接跑来了,DBA直接说:“leader让我直接找你,是这样的,上次加了缓存优化后,效果确实不错,但是我发现订单查询sql在今天的12:00至12:05之间有大量的慢sql,查询时间超过了2.5s。”
这个时候,我们立马开启了排查问题模式,首先,check了一下上次加的缓存,发现缓存正常,然后接着根据DBA提供的信息搜索日志,此时,发现在这个时间段订单请求量突增,大概是平常订单请求量的2到3倍,然后经过了解,发现在这个时间段内,营销系统那边做了一些活动,导致订单请求量突增。
说白了就是做了促销活动后,大量下单的用户会不断刷新订单来查询订单的信息,比如看一下订单是否开始配送,此时大量的请求会打到了MySQL上去,此时单库又抗不了这么读请求,就导致了数据库负载很高,从而严重降低了MySQL的查询效率。
现在我们缓存也加过了,但是数据库负载还是很高,此时该怎么办呢?
其实也很简单,既然单个库扛不住,那就搞2个库一起来抗呗,因为对于外卖订单来说是典型的读多写少的场景,所以,在这个场景下,我们可以搞个一主两从的架构来进行优化,就像这样:
也就是写数据走主库,而读数据走从库,可以看到,此时由于我们搞了2个从库,这2个从库可以一起来抗大量的读请求。
非常关键的一点就是,从库会通过主从复制,从主库中不断的同步数据,以此来保证从库的数据和主库是一模一样的,所以想要实现读写分离,那么,就先要了解主从复制是怎么玩儿的。
主从复制的原理是什么?
我们以mysql一主两从架构为例,也就是一个master节点下有两个slave节点,在这套架构下,写请求统一交给master节点处理,而读请求交给slave节点处理。
为了保证slave节点和master节点的数据一致性,master节点在写入数据之后,同时会把数据复制一份到自己的各个slave节点上。
在复制的过程中一共会使用到三个线程,一个是binlog dump线程,位于master节点上,另外两个线程分别是I/O线程和SQL线程,它们都分别位于slave节点上,如下图:
结合图片,我们一起来看下主从复制的核心流程:
(1)当master节点接收到一个写请求时,这个写请求可能是增删改操作,此时会把写请求的操作都记录到binlog日志中。
(2)master节点会把数据复制给slave节点,如图中的slave01节点和slave02节点,这个过程,首先得要每个slave节点连接到master节点上,当slave节点连接到master节点上时,master节点会为每一个slave节点分别创建一个binlog dump线程,用于向各个slave节点发送binlog日志。
(3)binlog dump线程会读取master节点上的binlog日志,然后将binlog日志发送给slave节点上的I/O线程。
(4)slave节点上的I/O线程接收到binlog日志后,会将binlog日志先写入到本地的relaylog中,relaylog中就保存了binlog日志。
(5)slave节点上的SQL线程,会来读取relaylog中的binlog日志,将其解析成具体的增删改操作,把这些在master节点上进行过的操作,重新在slave节点上也重做一遍,达到数据还原的效果,这样就可以保证master节点和slave节点的数据一致性了。
主从复制的有几种模式?
mysql的主从复制,分为全同步复制、异步复制、半同步复制和增强半同步复制 这四种。
全同步复制
首先,全同步复制,就是当主库执行完一个事务之后,要求所有的从库也都必须执行完该事务,才可以返回处理结果给客户端;因此,虽然全同步复制数据一致性得到保证了,但是主库完成一个事物需要等待所有从库也完成,性能就比较低了。
异步复制
而异步复制,当主库提交事物后,会通知binlog dump线程发送binlog日志给从库,一旦binlog dump线程将binlog日志发送给从库之后,不需要等到从库也同步完成事务,主库就会将处理结果返回给客户端。
因为主库只管自己执行完事务,就可以将处理结果返回给客户端,而不用关心从库是否执行完事务,这就可能导致短暂的主从数据不一致的问题了,比如刚在主库插入的新数据,如果马上在从库查询,就可能查询不到。
而且,当主库提交事物后,如果宕机挂掉了,此时可能binlog还没来得及同步给从库,这时候如果为了恢复故障切换主从节点的话,就会出现数据丢失的问题,所以异步复制虽然性能高,但数据一致性上是较弱的。
mysql主从复制,默认采用的就是异步复制这种复制策略。
半同步复制
半同步复制,顾名思义就是在同步和异步中做了折中选择,我们可以结合着MySQL官网来看下是半同步主从复制的过程,来看下这样图:
当主库提交事务后,至少还需要一个从库返回接受到binlog日志,并成功写入到relaylog的消息,这个时候,主库才会将处理结果返回给客户端。

相比前2种复制方式,半同步复制较好地兼顾了数据一致性以及性能损耗的问题。
同时,半同步复制也存在以下几个问题:
当主库成功提交事物并处于等待从库确认的过程中,这个时候,从库都还没来得及返回处理结果给客户端,但因为主库存储引擎内部已经提交事务了,所以,其他客户端是可以到从主库中读到数据的。
但是,如果下一秒主库突然挂了,就像这样图一样:
此时,下一次请求过来,因为主库挂了,就只能把请求切换到从库中,因为从库还没从主库同步完数据,所以,从库中当然就读不到这条数据了,和上一秒读取数据的结果对比,就造成了幻读的现象了。
增强半同步复制
最后,增强半同步复制,是mysql 5.7.2后的版本对半同步复制做的一个改进,原理上几乎是一样的,主要是解决幻读的问题。
主库配置了参数 rpl_semi_sync_master_wait_point = AFTER_SYNC 后,主库在存储引擎提交事物前,必须先收到从库数据同步完成的确认信息后,才能提交事务,以此来解决幻读问题。
可以参考下MySQL官网是怎么描述增强半同步主从复制过程的:
主从延迟问题和常规解决方案
主库写入的速度是很快的,因为主库是多线程并发写入的,但是,从库是单线程从主库拉取数据的,所以从库从主库复制数据的速度,就比较慢了,从而产生了主从延迟的问题。
mysql 从 5.6版本开始,就支持多线程复制,但是5.6版本是基于库级别去操作,也就是说会给每个数据库开启一个线程,不同库处理时在同一时间内是互不影响的;但是,当业务的压力集中到一个库时,又会回到和单线程复制一样的状况了。
直到mysql 5.7版本,开始引入了基于组提交(group_commit)的概念,这个时候才 真正 支持多路复制功能,官方称为enhanced multi-threaded slave(简称MTS),所以,推荐大家尽可能选择MySQL 5.7之后的版本。
而主库挂载的从库数量过多,也会导致主从复制延迟的问题,一般我们是建议一个主库挂载从库的数量,在3~5个比较合适。
另外,我们执行的SQL语句中,如果慢SQL语句过多,也会导致主从复制延迟,比如,我们工作中会遇到批量插入的场景,如果一批插入的数据量过大,就容易造成执行时间过长。
假如,从执行完一份 批量插入数据的SQL语句开始,到在从库上能查到这些数据的这个过程中,如果耗费了10秒,就导致主从库之间就延迟10秒了;所以,SQL优化会是一个常态化的工作,可以通过慢SQL日志或监控平台监控慢SQL,如果单个数据写入时间过长的话,可以将一批数据分片分批次写入。
最后,如果出现网络延迟或者机器的性能比较差,也会导致主从复制延迟的问题,这种情况没什么可说的,及时优化网络提升机器性能就行了。
读写分离实战
读写分离配置核心组件流程图:
| 读写分离配置步骤

(1)配置文件中配置主从库连接信息
(2)注入数据源
(3)数据源切换上下文,其中使用了ThreadLocal保存当前线程的数据源
(4)继承AbstractRoutingDataSource类重写determineCurrentLookupKey方法实现数据源动态切换
(5)创建读库的自定义注解
(6)切面类
(7)需要走读库的业务方法上添加@ReadOnly注解,那么执行这些业务方法时就会被切面拦截修改数据源从而走读库进行查询。
(8)写主库、读从库的效果
1)生成订单
2)查询订单
看图猜成语,第三个字兴,怎么读
成败兴废【成语】:成败兴废【拼音】:chéng bài xīng fèi【解释】:成功或失败,兴起或衰退。 【出处】:汉·荀悦《汉纪·成帝纪二》:“道家者流盖出于史官,有明成败兴废,然后知秉要持权,故尚无为也。 ”【示例扼腕兴嗟【成语】:扼腕兴嗟【拼音】:è wàn xīng jiē【解释】:扼腕:用手握腕;嗟:感叹。 用手握腕,长声叹息。 形容情绪激动发出叹息的神态。 【出处】:蔡东藩《民国通俗演义》第101回:“于是吏民俱困,都累得除害兴利【成语】:除害兴利【拼音】:chú hài xīng lì【解释】:根除对人民有害的事,兴办对人民有利的事业。 【出处】:《管子·治国》:“善为民除害兴利,故天下之民归之。 ”【示例】:【近义词】:兴利除害、兴拨乱兴治【成语】:拨乱兴治【拼音】:bō luàn xīng zhì【解释】:平定乱世,并着手治理。 【出处】:晋·常璩《华阳国志·先贤士女总赞》:“为会稽太守,拨乱兴治,立文学,学徒以千数。 ”抚髀兴嗟 【成语】:抚髀兴嗟【拼音】:fǔ bì xīng jiē【解释】:髀:股部,大腿;嗟:嗟叹。 抚摩大腿,发出长长的叹息。 指久处安逸而无所作为发出的慨叹。 【出处】:蔡东藩《民国通俗演义》第96回:“急得宗祥抚髀顾景兴怀【成语】:顾景兴怀【拼音】:gù jǐng xīng huái【解释】:看见眼前的景物而产生某种情怀。 【出处】:宋·周密《武林旧事记》卷五:“石间波纹水迹,亦不知何时有之。 其间唐宋游人提名,不可殚记,览者顾景�睹物兴悲 【成语】:睹物兴悲【拼音】:dǔ wù xīng bēi【解释】:见到与故人有关的东西而引起悲伤。 【出处】:明·朱鼎《玉镜台记·新亭流涕》:“猛然间睹物兴悲,早不觉潸然涕流。 ”【示例】:【近义词】:睹物伤情盛衰兴废 【成语】:盛衰兴废【拼音】:shèng shuāi xīng fèi【解释】:盛:兴盛;衰:衰败;兴:兴旺;废:废弃。 指人与事变化发展的各种情况。 【出处】:宋·王安石《祭欧阳文忠文》:“呜呼!盛衰兴废之理,自�继绝兴亡【成语】:继绝兴亡【拼音】:jì jué xīng wáng【解释】:绝:断绝;亡:灭亡。 恢复已灭亡的国家,延续断绝了的世家。 【出处】:《晋书·刘琨传》:“如蒙录召,继绝兴亡,则陛下更生之恩,望古无二。 ”【示薏苡兴谤【成语】:薏苡兴谤【拼音】:yì yǐ xīng bàng【解释】:薏苡:多年生草本植物,果实可供食用酿酒,并入药。 薏米被进谗的人说成了明珠。 比喻被人诬谄,蒙受冤屈。 【出处】:《后汉书·吴佑传》:“今大人逾越�
竿头日上打一生肖 bb
竿头日上打一生肖——答案:鸡。 竿头日上gān tóu rí shàng【解释】竿头:竹竿尖头;上:上升。 比喻学业进步很快。 【出处】《秉烛谈》:“招贤大师赠一偈曰:百丈竿头不动人,虽然得人未为真。 百丈竿头须进步,十方世界是全身。 ”【结构】紧缩式【用法】作谓语、宾语;指学业等【近义词】竿头日进【反义词】每况愈下【成语故事】宋朝时期长沙高僧景岑佛学造诣高深,时常到各地去传道讲经,他讲得深入浅出,娓娓动听,听众与他谈论有关佛教的最高境界。 他拿出偈帖给大家念道:“百丈竿头不动人,虽然得人未为真。 百丈竿头须进步,十方世界是全身。 ”
形容人很快乐的成语有那些?
得意忘形
发表评论