目录

1、读写分离解决了什么问题

2、读写分离与业务的架构

3、实际案例

4、解决方案


模拟binlog协议   延迟消费

1、读写分离解决了什么问题

读写分离其实将数据库分离一个主库,多个从库,主从库之前通过某种机制(如binlog)进行数据同步,这是一种常见的数据库架构。在大多数互联网业种中,都是读多写少的业务,为了能够线性提升数据库的读性能,消除读写冲突并提升写的性能,一般可以采用读写分离的思想(当然还有其他解决方案:如复本集,缓存策略等等)。其实,用一句话来概括,读写分离基本原理就是将数据库的读写操作路由到不同的节点上,用来解决数据库的读性能瓶颈的。

2、读写分离与业务的架构

在实际的项目中,读写分离与业务架构如下图所示。应用程序A通过执行事件(事务执行)成功后,发送消息队列通知应用程序C。应用程序C通过上游应用程序B获取数据。其中,应用程序A主要是写操作,连接master库,应用程序B主要是读操作连接slave库。master与slave通过某种机制进行数据同步。

在这样一个简单的架构中,其实存在一个主要的问题,也是本文将着重探讨及解决的——应用程序B获取的数据可能是还未同步到从库的数据。

3、实际案例

下面首先我结合案例介绍一下遇到的问题(数据库为innodb)。

在**年初,有商家反馈**写操作后数据没有生效,实际的业务视图与上面的保持一致。其实原因现在来看已经很清楚了,但定位问题还是花费了几天,首先排查代码(有事务,并且通过TSM的afterCommit后再发送的消息队列,当然缓存的设置也是没有问题【如先del还是直接set】,这里就不表了),单中代码层面上是没有问题的,接着就从系统级别排查问题,并且对比数据库的写时间,调用从库获取的数据等日志综合定位——由数据同步延迟导致的。

于主库来说,事务成功提交后,该数据一定对另一个事务可见(本文所讨论的数据库在没有特殊说明下,都指Innodb, 隔离级别为RR)。接口则是从从库获取数据。这里简单梳理下一条数据写入数据库的整个过程:对于update/insert/delete等操作,依次会产生undo log, redo log,在2PC下,当redolog prepare(是否落盘则根据innodb_flush_log_at_trx_commit控制)ok后,接着进行binlog(是否落盘则根据sync_binlog控制)的commit及redo log的commit; 当然在整个过程中,会读取相关的page到内存中进行更改,也即所谓的dirty page。当事务commit后,其实仅仅代表日志已经落盘,最终内存中的dirty page什么时候刷新到磁盘,这则是checkpoint的事儿了,其间会经历checksum,double write等等,这不是本文的重点,点到为止。 先保证redolog/binlog/undolog成功,这就是有名的WAL(为啥要WAL呢?redolog与binlog共存的意义何在?留个思考题吧)。整个过程,主库就完成了数据的写入;

接着mysql就利用binlog进行数据同步,从库上一般会有IO线程,从主库中获取binlog日志存放在从库的内存中,即relay log,假设消耗时间为T1;然后利用sql线程进行回放数据,假设消耗时间为T2。目前线上,我们使用的mysql版本号为5.5(貌似在5.6的哪个版本是支持binlog的多线程复制,不过在5.5一定是单线程),binlog的复制方式是RBR(另外两种是SBR,MBR),从库使用的数据库存储引擎也是Innodb。假设业务上的时间(如发送mq,下游接收mq并调用接口)的时间为T3。很显示,当T3<T1+T2时,是不是意味着获取到的数据是上一次发布的数据呢?没错,下游获取数据没有更新就是这种情况导致的。这是当时线上获取的binlog同步到从库相对主库的延迟监控图,从图中可以看到,在某些时刻,主从同步最大有甚至有1s,此时主库的CPU消耗也是挺高的。

4、解决方案

解决数制库读写分离下的数据同步思路其实相当简单——确保从库与主库的数据已经同步即可。如轮询从库数据(当然这个不是很优雅的解决方案),订阅从库的binlog日志(当生成binlog日志时)。接下来我们对后面一种方案进行简单的描述。

目前,已经有很多成熟的工具来模拟从库获取数据库实例的binlog日志并对其解析,如阿里的canal,京东的binlake等。他们可以按需过滤部分的binlog日志(如某个table的某些操作),然后发送到消息队列中,应用程序程序订阅该消息后,然后进行业务逻辑处理(如通过已经有工具解析binlog日志,然后进行业务逻辑处理,并按需发送消息给下游)。这里虽然解决了读写分离因同步延迟导致的业务不正确的问题,但并不完美,因此并没有彻底解决该问题。具体原因如下:

在2PC中,分为两个阶段:第一阶段是redo/undo log的sync落盘, 第二阶段包含两步:前一步骤为binlog的sync操作,当这个阶段完成时,binlog已经写入,此时就可以发送给订阅者然后进行消费,后一步骤是commit操作[如释放mutex锁],只有commit全部完成之后,其他事务才能查询binlog日志所对应的事务产生的数据变更(这里有可能网友有疑问,如果binlog落盘了数据库崩溃了,能否恢复数据?答案当然是能够的)。因此在实际的项目中,我是通过延迟消费500ms的策略解决的,这里就完美的解决了数据同步的问题。

binog日志落盘到整个2PC提交结束这个时间差可能导致数据不同步,要特别感谢该博文:https://www.jiqizhixin.com/articles/2018-12-05-14, 在这里我才意识到可能存在这个问题,并在实际的项目中与小伙伴一起验证,通过连接7天的数据验证,终于发现了一条这样的数据。

数据库读写分离下的数据同步解决方案相关推荐

  1. 简单好用!利用Spring AOP技术10分钟实现一个数据库读写分离方案

    前言 最近我们的APP在线用户越来越多,接口的响应速度也是越来越慢,经过运维排查发现是由于并发查询太多导致的数据库压力比较大,架构师经过调研给出了数据库读写分离的解决方案,为了快速解决问题,我们最终采 ...

  2. 17.sql server数据库使用规则、二八原则、数据库查询集群--数据库读写分离多种实现、数据库配置读写分离(by-朝夕)

    Database 课程目标 环境准备: 一.二八原则 二.数据库读写分离 好处: 绝大部分的企业内部应用,可能不需要上图那么庞大的架构,一台主数据库服务器和一台查询服务器通常能满足读写分离的要求.而且 ...

  3. ceph集群和数据库到底是储存数据_Python开发之:Django基于Docker实现Mysql数据库读写分离、集群、主从同步详解 | 原力计划...

    作者 | Pythonicc责编 | 王晓曼出品 | CSDN博客简介1.什么是数据库读写分离读写分离,基本的原理是让主数据库处理事务性增.改.删操作(INSERT.UPDATE.DELETE),而从 ...

  4. 数据库读写分离数据延迟解决方案

    一.数据库系统架构发展 1.主备架构 业务发展的前期,数据访问量小,这时我们可以直接采用单库的架构. 不过我们一般不使用的上面的架构,因为存在单点的问题.若数据库出现故障,这段期间业务将会不可用.我们 ...

  5. .net core发布 正在发现数据上下文_使用EF Core实现数据库读写分离

    以下文章来源于朝夕Net社区 ,作者Eleven 朝夕Net社区 朝气.丰富.活跃的.Net社区,朝夕教育携百万粉丝共同打造!有技术,有感悟,有新闻,有照片,有故事,还有梦想! [精选转载]| 作者/ ...

  6. Python开发之:Django基于Docker实现Mysql数据库读写分离、集群、主从同步详解 | 原力计划...

    作者 | Pythonicc 责编 | 王晓曼 出品 | CSDN博客 简介 1.什么是数据库读写分离 读写分离,基本的原理是让主数据库处理事务性增.改.删操作(INSERT.UPDATE.DELET ...

  7. 数据库读写分离,主从同步实现方法

    前言 众所周知,随着用户量的增多,数据库操作往往会成为一个系统的瓶颈所在,而且一般的系统"读"的压力远远大于"写",因此我们可以通过实现数据库的读写分离来提高系 ...

  8. phalapi 数据库锁_[7.11]-phalapi-进阶篇5(数据库读写分离) | PhalApi(π框架) - PHP轻量级开源接口框架...

    phalapi-进阶篇5(数据库读写分离以及多库使用) 前言 先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个优秀的开源框架. 读写分离是我们常用的一种解决方案,它可以解决大 ...

  9. Spring - 数据库读写分离

    文章目录 Spring - 数据库读写分离 1.读写分离解决方案 1.1 应用层解决 1.2 中间件解决 2.Mysql主从配置 2.1 Mysql主从复制原理 2.2 Master主库配置 2.3 ...

  10. phalapi 数据库锁_phalapi-进阶篇5(数据库读写分离以及多库使用)

    #phalapi-进阶篇5(数据库读写分离以及多库使用)# ##前言## 先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个优秀的开源框架. 读写分离是我们常用的一种解决方案, ...

最新文章

  1. 如何给Lombok Builder提供默认值
  2. windows 技术篇-将本地主机加入域的方法实例演示
  3. flex属性值----弹性盒子布局
  4. java jdbc 登录_java web JDBC 判断用户登录问题!
  5. 记录一次@Transactional问题处理
  6. Setimer和Ontimer的使用
  7. 面向对象课程第四单元作业总结
  8. C++查找一个目录下所有特定扩展名的文件
  9. JavaScript设计一个框架
  10. datagrid--新增
  11. nginx利用geo模块做限速白名单以及geo实现全局负载均衡的操作记录
  12. word wrap java控制台_word wrap 解惑
  13. UZCMS镜像站群-v5.4旗舰版
  14. 网络概念- VXLAN技术详解
  15. 张宇高数 第二讲 一元函数微分学(思维导图)
  16. 运维工程师那些尴尬的瞬间
  17. H77、Z75、Z77主板有什么区别?
  18. 考研要求过英语四六级!这些大学有明确规定!
  19. 财报发布前获多家投行认可,借商流+物流闭环效应达达估值可期
  20. 浙江财经大学第十四届程序设计竞赛命题感想

热门文章

  1. 隐马尔可夫模型python_隐马尔可夫模型HMM及Python实现
  2. 非线性方程的数值解法:二分法的MATLAB实现
  3. 基于vlmcsd搭建KMS服务器
  4. 计算机中英文打字文章,中英文混合打字文章
  5. 图文二维码怎么制作?如何将图文变成二维码?
  6. 斐讯K2P B1 博通TTL刷机方法
  7. linux系统svn安装教程,Linux下SVN安装配置
  8. STM32F4xx固件库分析
  9. MPS的DCDC国产代换件
  10. MATLAB/Simulink 基础入门讲解(一)