多读少写
,如:微博、微信、淘宝电商,按照28原则
,阅读流量比例甚至可以达到90%读写分离
加工流程:
客户端将集成SDK。每次执行SQL时都会判断是写入
还是读取
并操作
如果写入
SQL,请求将发送到主数据库
主数据库执行SQL。交易提交后,会生成binlog
并同步到从库
从库
通过SQL线程回放binlog
,并在从库表
如果是读
SQL,请求会经过负载均衡
策略,选择一个从库
来处理用户请求
看似很有道理,但仔细一想,又不是那么回事
主数据库
和从数据库
使用异步数据复制。如果两者之间的数据还没有同步怎么办?
主库刚刚写完数据,从库还没来得及拉取最新的数据,读
请求就来了,给用户的感觉是,数据丢失了? ? ?
针对这个问题,今天我们就来讨论一下有哪些解决方案?
A。强行进入主库
区别对待不同的业务需求
场景1:
如果是数据的实时性
,要求不是很高。比如说,一个拥有千万粉丝的大V,发了一条微博,粉丝几秒后才收到消息,就不会发生这种情况。影响特别大。这个时候你就可以从图书馆去。
场景2:
如果对数据的实时性
要求很高,比如金融服务。我们可以强制查询到客户端代码标签下的主数据库。
B。从数据库查询延迟
由于主从数据库之间的数据同步需要一定的时间间隔,因此一种策略是延迟从从数据库查询数据。
例如:
select sleep(1)select * from order where order_id=11111;
正式业务查询时,首先执行一条sleep语句,为从库预留一定的数据同步缓冲期。
因为是一刀切的解决方案,所以面对高并发的业务场景时,性能会大幅下降。一般不推荐这种解决方案。
C。判断master和slave是否有延迟?决定选择主库还是从库选项1:
在从库中执行命令show Slave status
查看 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操作时,首先判断是否已经从数据库同步了最新的数据。这决定了是操作主库还是从库。
缺点:
无论采用以上哪种方案,如果主库的写操作频繁且连续,那么从库的值永远跟不上主库的值,进而导致读流量总是会到达主库。
这个问题有什么解决办法吗?
这个问题和MQ消息队列一样,既需要高吞吐量,又需要有序性。从全球角度来看,确实没有解决办法,但缩小范围就容易多了。我们可以确保分区中的消息是有序的。
回到主从库之间的数据同步问题
。从从库查询哪条记录?我们只需要保证对应写入的binglog之前已经同步过数据即可,不需要担心主从库的问题。所有事务binlog是否同步。
问题是不是简单多了
D。从仓库节点
确定主仓库位置在从库中执行以下命令,返回值为正整数M,表示从参数节点开始从库已经执行了多少个事务
select master_pos_wait(file, pos[, timeout]);
file和pos代表主库上的文件名和位置
timeout是可选的,表示该函数最多等待N秒
缺点:
master_pos_wait
返回结果无法与具体操作的数据行关联,所以每次收到读请求
,从库仍然无法确认数据是否已经同步,而且该解决方案不太实用。
E,比较GTID
执行以下查询命令
阻塞并等待,直到从库执行的事务包含gtid_set,返回0
超时,返回1
select wait_for_execulated_gtid_set(gtid_set, 1);
处理流程:
发起写入
SQL操作。主库执行成功后,返回本次交易的GTID
发起read
SQL操作时,首先执行select wait_for_execulated_gtid_set(gtid_set, 1)
如果返回0,则表示数据已从从库同步,可以在从库中执行。 查询
操作
否则在主库执行查询
操作
缺点:
与上面的master_pos_wait
类似。如果写操作
和读操作
没有上下文,那么GTID就无法传递。该解决方案不太实用。
F。引入缓存中间件
在高并发系统中,缓存是性能优化的有力工具,应用非常广泛。我们可以考虑引入缓存作为缓冲介质
加工流程:
客户端编写
SQL并操作主数据库
同步删除缓存中的数据
客户端读取数据时,先从缓存加载
如果缓存中没有,则强制查询主库预热数据
缺点:
K-V存储,适合一些简单的查询条件场景。如果查询比较复杂,还是需要查询从库。
G,数据分片
参考Redis集群模式。集群网络拓扑通常是3主3从。主节点负责写入和读取。
通过水平分片支持数据的水平扩展。由于每个节点都是独立的服务器,因此可以提高整个集群的吞吐量。
转换为数据库
常见的解决方案是分库分表。 读写
每次操作主库的一个子表,从库仅用于数据备份。当主库故障时,主从切换保证集群的高可用性。
mysql视频教程