# (七)MYSQL读写分离

#### 1.为什么进行读写分离

这个，高并发这个阶段，那肯定是需要做读写分离的，啥意思？因为实际上大部分的互联网公司，一些网站，或者是app，其实都是读多写少。所以针对这个情况，就是写一个主库，但是主库挂多个从库，然后从多个从库来读，那不就可以支撑更高的读并发压力了吗？

#### 2.如何实现mysql读写分离

其实很简单，就是基于主从复制架构，简单来说，就是搞一个主库，挂多个从库，然后我们就只是写主库，然后主库自动把数据同步到从库，读数据全都走从库。

#### 3.MYSQL主从复制原理

主库将数据操作指令写到binlog日志，然后从库连接主库之后，从库有一个IO线程，将主库的binlog日志拷贝到自己本地，写入一个中继日志中。接着从库中有一个SQL线程会从中继日志中读取binlog，然后执行binlog日志中的内容，也就是在自己本地再执行一遍SQL，这样就可以保证自己跟主库的数据是一致的。

![image.png](https://180380256-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LfcT-GVQPkfuHPeol1x%2F-LfjzQ1jH0zzzEjeoanv%2F-LfjzRV3RnQ0JOvh8tj_%2F5-1%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E5%8E%9F%E7%90%86.png?generation=1558804549834668\&alt=media)

这里有一个非常重要的一点，就是从库同步主库数据的过程是串行化的，也就是说主库上并行的操作，在从库上会串行执行。所有在高并发场景下，从库的数据一定会别主库慢一些，，是有延时的。所以经常出现，刚写入的数据可能是读不到的问题，要经过几十毫秒，甚至几百毫秒才能读取到。

还有一个问题，就是如果一个数据已写入主库，但是这时候binlog从库还没有来得及复制。主库这时候宕机了，那么有些数据可能在从库上是没有的，有些数据就会丢失。

#### 4.解决主库数据丢失问题

mysql有一个机制叫做半同步复制，这个机制就可以解决主库数据丢失问题。\
这个所谓半同步复制，semi-sync复制，指的是主库写入binlog日志之后，就会将数据立即强制将数据同步到从库。从库将日志写入自己本地的relay log之后，接着会返回一个ack给主库，主库接收到至少一个从库的ack之后才会认为写操作完成了。

#### 5.解决主从同步延迟

mysql可以在复制binlog文件时并行复制，减轻延迟问题。\
这个所谓并行复制，指的是从库开启多个线程，并行读取relay log中**不同库** 的日志，然后并行重放不同库的日志，这是库级别的并行。

#### 6.mysql主从延时问题

show status，Seconds\_Behind\_Master，你可以看到从库复制主库的数据落后了几ms。

其实这块东西我们经常会碰到，就比如说用了mysql主从架构之后，可能会发现，刚写入库的数据结果没查到，结果就完蛋了。。。。

所以实际上你要考虑好应该在什么场景下来用这个mysql主从同步，建议是一般在**读远远多于写** ，而且读的时候一般对数据时效性要求没那么高的时候，用mysql主从同步。

所以这个时候，我们可以考虑的一个事情就是，你可以用mysql的并行复制，但是问题是那是库级别的并行，所以有时候作用不是很大

所以这个时候通常来说，我们会对于那种写了之后立马就要保证可以查到的场景，采用强制读主库的方式，这样就可以保证你肯定的可以读到数据了吧。其实用一些数据库中间件是没问题的。

一般来说，如果主从延迟较为严重

1、分库，将一个主库拆分为4个主库，每个主库的写并发就500/s，此时主从延迟可以忽略不计。

2、打开mysql支持的并行复制，多个库并行复制，如果说某个库的写入并发就是特别高，单库写并发达到了2000/s，并行复制还是没意义。28法则，很多时候比如说，就是少数的几个订单表，写入了2000/s，其他几十个表10/s。

3、重写代码，写代码的同学，要慎重，不要做插入之后立即查询操作，插入数据之后，直接就更新，不要查询。

4、如果确实是存在必须先插入，立马要求就查询到，然后立马就要反过来执行一些操作，对这个查询设置直连主库。不推荐这种方法，你这么搞导致读写分离的意义就丧失了
