数据的读写分离——主从同步 分析

前述

最近在研究redis,redis中提到了主从同步,而我常用的mysql数据库中也有主从同步的概念。
故而这次对数据的主从同步进行了了解

为何要读写分离?

访问量大、访问量大、访问量大

我们现在很多技术解决方案,都是为了解决:随着用户量增长,访问量越来越大,而原本的服务架构不足以支撑如此的访问量

而往往读操作是越大部分。我们以往单数据库,一个数据库负责了所有读写操作

所以就提出了一种解决方案——读写分离——由master(主数据库)负责数据的写操作,而slave(从数据库,可多台)只负责读操作

为何要主从同步?

在出现了读写分离的数据库架构设计后,便引出一个问题,slave既然负责读操作,那数据哪里来?

自然是同步master内的数据。

所以我们便将slave从master同步数据,称之为主从同步

高并发场景下,如何实现数据库主从同步?

如何主从同步?

先大致说下同步原理:在master上,主从同步事件会被写到特殊的log文件中(binary-log);在slave机器上,slave读取主从同步事件,并根据读取的事件变化,在slave库上做相应的更改

先说说主从同步事件的形式

  1. statement:会将对数据库操作的sql语句写入到binlog中。
  2. row:会将每一条数据的变化写入到binlog中。
  3. mixed:statement与row的混合。Mysql决定什么时候写statement格式的,什么时候写row格式的binlog。

在同步时执行操作

  1. master数据发生改变,改变事件(DDM、DML)会依次写入到binlog文件
  2. master会创建一条binlog dump线程,负责与slave联系,当binlog发生变化,dump线程通知slave,并将binlog信息发送给slave
  3. slave在开启主从同步后,会创建两条线程:
    1. I/O线程,负责与master的dump联系,接收binlog,并写入到本地的relaylog
    2. SQL线程,读取relaylog,根据relaylog操作slave数据库

主从同步引出的问题

延时——主从未同步

既然slave负责读,当master写操作后,在slave同步时,这中间必然存在时间间隔

那在这时间间隔中就存在了变数:

  1. 在slave同步时,用户去slave请求最新数据,却没有——主从不同步
  2. 在master写操作完成后成功返回,dump开始通知slave,但在这期间,如果master发生了crash,那slave便丢失了本次的写操作
  3. 在master写操作完成正在返回,且dump已通知slave,但这时,master发生了cash,那么主数据库回滚,但slave却保存了这次写操作
  4. ...

这该如何?

几种主从同步解决方案

1.异步同步

也是mysql默认的同步方式。

master在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,

但这样就会发生上面所说的第二中情况

2.全同步

顾名思义:

就是master完成写操作事物后不立刻返回,等!等所有slave完成从同步,再返回事物。

这样确实可以保证主从数据一致,但问题也是很明显的

每次master的写操作时间增大!如果一次写操作的数据量巨大,那....。如果在执行某个slave出现的select锁竞争,又要等待,甚至slave出现了死锁...

所以全同步虽然保证了主从同步一致性,但代价也是非常巨大,要慎重

3.半同步

介于异步与全同步之间。master写操作完成后事物不立即返回,至少等待一个slave接收到并写到relay log中,才返回事物。

但也造成了一定的延迟,至少是一个tcp/ip往返时间,所以此方式最好在低延迟环境中执行

其他解决方案

中间件

高并发场景下,如何实现数据库主从同步?

所有读写操作走中间件,由中间件,写操作路由到master,读操作路由到slave
如本次请求为写操作,在中间件记录该写操作的key,在主从同步时间段,有读操作请求中间件内的该key,则让本次读操作master,主从同步时间段完成后,读请求走slave

相关的中间件有:

  • canal:是阿里巴巴旗下的一款开源项目,纯Java开发,基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL
  • otter:也是阿里开源的一个分布式数据库同步系统,尤其是在跨机房数据库同步方面,有很强大的功能。它是基于数据库增量日志解析,实时将数据同步到本机房或跨机房的mysql/oracle数据库

区别:

  • otter目前嵌入式依赖canal,部署为同一个jvm,目前设计为不产生Relay Log。
  • otter目前允许自定义同步逻辑,解决各类需求

这样便可保证主从同步,且效率还可以

但中间件嘛,数据库成本也摆在那了

缓存记录写key法

高并发场景下,如何实现数据库主从同步?

其作用与思路与缓存中间件很类似

写流程:

1)要发生写操作,将key记录在cache里,并设置“主从同步时间”的cache超时时间

2)然后master执行写操作,并执行主从同步

读流程:

1)先到缓存查找key(key设置了失效时间)

2)如有数据,则缓存命中,说明该key刚发生过写操作,此时需要将请求路由到主库读最新的数据。

3)如果缓存没有命中,说明这个key上近期没有发生过写操作,此时将请求路由到从库,继续读写分离。

优点:相对数据库中间件,自然成本较低

缺点:多了一层缓存中间件,那在业务实现时,就要考虑多一些了

总结

以上就是我对读写分离——主从同步的了解与思考,当然是借鉴了其他文章,以前对数据库的读写分离处于只知其名的阶段

本次还是因为要系统了解redis知识体系,所以对主从同步进行了较为深入的了解

希望多多交流,如有疑惑与不足请及时留言交流

 

知识总要有体系的去学习,这样便可以让自己在脑子里建模,对该知识有个系统的认识,也更便于理解。知识它是什么,为什么有它,它来解决什么技术问题。

 

参考文档:
https://www.toutiao.com/a6762107909095555592/
https://www.toutiao.com/a6699310878136730115/
https://www.toutiao.com/a6754000358118261251/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值