主从同步过程
MySQL主从同步由主节点dump线程、从节点 I/O 线程、从节点SQL线程三个线程配合完成。
1、从节点上的 I/O 进程主从去连接主节点,并带上同步的开始位置即指定日志文件的位置之后的日志内容
2、主节点接收到来自从节点的 I/O 请求后,通过主节点dump线程读取指定日志位置之后的日志信息,返回给从节点。同时也返回binlog file的以及binlog position
3、从节点的 I/O 线程接收到内容后,将接收到的日志内容写到本地的relay log中,并将读取到的binlog文件名和位置保存到master-info文件中
4、从节点的SQL线程检测到relay log中新增加了内容后,将relay log回放写入到数据库中
主从复制模式
1、异步模式
主库写入binlog完成后提交事务。
2、半同步模式
保证至少有从库将日志写入relay log后应答成功才提交事务。
3、全同步模式
MySQL 主从复制默认是异步的模式
主从延迟问题
从上文可知主从同步无论哪种模式都是先写入从库的relay日志后再有SQL线程回放写入从库,所以或多或少的都会出现主从延迟问题。所以会导致一定时间内主从的不一致问题,开发中常见的读写分离存在主从延迟问题就是这个原因导致。
主从延迟问题解决
1、mysql层面。可以增加机器性能、减少网络延迟、降低数据安全措施例如关闭从节点binlog日志或者刷盘策略放开等增加从库写入的速度、还可以配置多个SQL线程等。
2、业务层面。可以使用缓存后双写避免马上去读从库,也可以加延迟读取以减少延迟带来的业务问题,也可以直接读取主库。
开头问题解决方案
1、修改sql,增加一个判断条件兜底,保证不多发,update code set state=已领取 where state=未领取,这样可以确保一条号码不会被多次领取,但是需要处理领取失败的情况。可以在读取未领取号码时多读取几条,一条领取失败就领取下一条直到成功或者领完。
2、使用缓存,将数据预读到缓存中,读的时候从缓存中读取,这样就可以避免去读从库,但是需要处理缓存和主库一致性问题。将号码放到redis队列中,每次从队列里去一条,用完后再读取到redis。