这篇文章主要介绍了分享MySQL?主从延迟与读写分离的七种解决方案,常见的解决方式是分库分表,每次读写都是操作主库的一个分表,从库只用来做数据备份。当主库发生故障时,主从切换,保证集群的高可用性,下面
前言:
我们都知道互联网数据有一个特点。大部分场景是看的多写的少,比如:微博,微信,淘宝电商。按照二八原则,阅读流量甚至可以达到90%。
结合这一特性,我们将相应地调整底层数据库架构。采用读写分离。
处理过程:
客户端会集成 SDK,每次执行 SQL 时,会判断是 写 或 读 操作。如果是 写 SQL,请求会发到 主库。主数据库执行SQL,事务提交后,会生成 binlog ,并同步给 从库。从库 通过 SQL 线程回放 binlog ,并在从库表中生成相应数据。如果是 读 SQL,请求会通过 负载均衡 策略,挑选一个 从库 处理用户请求。
看起来很有道理,但仔细想想却不是这么回事。
主库和从库异步复制数据。它们之间的数据不同步怎么办?
主库刚写完数据,从库还没来得及拉最新数据,读请求就来了,给用户数据丢失的感觉?
要解决这个问题,今天,我们来讨论一下有哪些解决方法。
一、强制走主库
区别对待未使用的业务需求。
场景一:
如果对数据的实时性要求不是很高,比如:大V有几千万粉丝,发布一条微博,粉丝几秒钟后收到这条消息,不会造成特别大的影响。这时候你可以从图书馆走。
场景二:
如果对数据的实时性要求非常高,比如金融业务。我们可以强制查询到客户机代码标签下的主库。
二、从库延迟查询
因为主库和从库之间的数据同步需要一定的时间间隔,所以有一种延迟从库的数据查询的策略。
例如:
select sleep(1)select * from order where order_id=11111;
在正式的业务查询中,首先执行一条sleep语句,为从数据库预留一定的数据同步缓冲期。
因为是一刀切,所以面对高并发的业务场景时,性能会下降的很厉害。一般来说,不推荐这种方案。
三、判断主从是否延迟?决定选主库还是从库
之前写过一篇文章《JD的一面。COM:MySQL主备延迟有哪些坑?”主备切换策略。
主要待机延迟是多少?主备延迟的常见原因有哪些?
选项1:
从库中执行命令显示从状态。
检查seconds_behind_master的值,单位为秒。如果为0,则表示主库和辅助库之间没有延迟。
选项2:
比较主库和从库的文件点。
或者执行show slave status,在响应结果中有关键参数。
Master_Log_File 读到的主库最新文件。Read_Master_Log_Pos 读到的主库最新文件的坐标位置。Relay_Master_Log_File 从库执行到的最新文件。Exec_Master_Log_Pos 从库执行到的最新文件的坐标位置。
两个比较,以上参数是否相等。
选项3:
比较GTID集合。
Auto_Position=1 主从之间使用 GTID 协议。Retrieved_Gtid_Set 从库收到的所有binlog日志的 GTID 集合。Executed_Gtid_Set 从库已经执行完成的 GTID 集合。
比较Retrieved_Gtid_Set和Executed_Gtid_Set的值是否相等。
在执行业务SQL操作时,首先判断从数据库是否同步了最新的数据。以便决定是运行主库还是从库。
缺点:
无论采用以上哪种方案,如果主库的写操作频繁,那么从库的值永远跟不上主库的值,那么读流量就永远打主库。
1.针对这个问题,有什么解决方案?
这个问题和MQ消息队列一样,都需要高吞吐量和高顺序。从全局的角度来看,确实没有解决方案,但是缩小范围要容易得多,我们可以确保一个分区中的消息是有序的。
回到主库和从库的数据同步问题,从库中查询哪些记录,我们只需要保证对应的写binlog之前已经同步了数据,不管主库和从库的所有事务binlog是否同步。
问题就简单多了。
四、从库节点判断主库位点
从库中执行下面的命令,返回的是正整数M,表示从参数节点开始,从库中执行了多少个事务。
select master_pos_wait(file, pos[, timeout]);file 和 pos 表示主库上的文件名和位置。timeout 可选, 表示这个函数最多等待 N 秒。
缺点:
master_pos_wait返回的结果无法与具体操作的数据线关联,所以每次收到读请求时,从库仍然无法确认数据是否已经同步,方案的实用性不高。
五、比较 GTID
执行以下查询命令:
阻塞等待,直到从库执行的事务中包含gtid_set,返回 0。超时,返回 1。select wait_for_executed_gtid_set(gtid_set, 1);
MySQL版本5.7.6启动,允许更新事务的GTID在执行后返回给客户端。具体来说,参数session_track_GTIDs设置为OWN_GTID,调用API接口mysql_session_track_get_first返回结果并解析GTID。
处理流程:
发起 写 SQL 操作,在主库成功执行后,返回这个事务的 GTID。发起 读 SQL 操作时,先在从库执行 select wait_for_executed_gtid_set (gtid_set, 1)。如果返回 0,表示已经从库已经同步了数据,可以在从库执行 查询 操作。否则,在主库执行 查询 操作。
缺点:
类似于上面的master_pos_wait,如果写操作和读操作之间没有上下文,那么GTID就无法传递。该方案的实用性不高。
六、引入缓存中间件
高并发系统中,缓存被广泛用作性能优化的工具。我们可以考虑引入缓存作为缓冲介质。
处理过程:
客户端 写 SQL ,操作主库。同步将缓存中的数据删除。当客户端读数据时,优先从缓存加载。如果 缓存中没有,会强制查询主库预热数据。
缺点:
K-V存储适用于一些简单的查询条件。如果查询很复杂,您仍然需要查询从属库。
七、数据分片
参考Redis集群模式,集群网络拓扑通常是三主三从,主节点同时负责写和读。
通过水平切片,支持数据的水平扩展。因为每个节点都是独立的服务器,所以可以提高整个集群的吞吐量。
1.转换到数据库方面
常见的解决方案是将数据库分成多个表。每次读写都是主数据库的一个表,从数据库只用于数据备份。当主库出现故障时,主从切换保证集群的高可用性。
关于分享MySQL主从延迟和读写分离的七种解决方案的这篇文章到此为止。关于MySQL主从延迟读写分离解决方案的更多信息,请搜索搜源网之前的文章或者继续浏览下面的相关文章。希望大家以后能多支持源搜网!
查看更多关于分享MySQL,主从延迟和读写分离的方案的详细内容...