谈谈个人网站的建立(六)—— 数据库同步

先来回顾一下上一篇的小集群架构,tomcat集群,nginx进行反向代理,服务器异地:

由上一篇讲到,部署的时候,将war部署在不同的服务器里,通过spring-session实现了session共享,基本的分布式部署还算是完善了点,但是想了想数据库的访问会不会延迟太大,毕竟一个服务器在北京,一个在深圳,然后试着ping了一下:

果然,36ms。。。看起来挺小的,但是对比一下sql执行语句的时间:

大部分都能在10ms内完成,而最长的语句是insert语句,可见,由于异地导致的36ms延时还是比较大的,捣鼓了一下,最后还是选择换个架构,每个服务器读取自己的数据库,然后数据库底层做一下主主复制,让数据同步。最终架构如下:

一、MySql的复制

数据库复制的基本问题就是让一台服务器的数据与其他服务器保持同步。MySql目前支持两种复制方式:基于行的复制和基于语句的复制,这两者的基本过程都是在主库上记录二进制的日志、在备库上重放日志的方式来实现异步的数据复制。其过程分为三步: (1)master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events); (2)slave将master的binary log events拷贝到它的中继日志(relay log); (3)slave重做中继日志中的事件,将改变反映它自己的数据。

该过程的第一部分就是master记录二进制日志。在每个事务更新数据完成之前,master在二日志记录这些改变。MySQL将事务串行的写入二进制日志,即使事务中的语句都是交叉执行的。在事件写入二进制日志完成后,master通知存储引擎提交事务。 下一步就是slave将master的binary log拷贝到它自己的中继日志。首先,slave开始一个工作线程——I/O线程。I/O线程在master上打开一个普通的连接,然后开始binlog dump process。Binlog dump process从master的二进制日志中读取事件,如果已经跟上master,它会睡眠并等待master产生新的事件。I/O线程将这些事件写入中继日志。 SQL slave thread处理该过程的最后一步。SQL线程从中继日志读取事件,更新slave的数据,使其与master中的数据一致。只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志的开销很小。 此外,在master中也有一个工作线程:和其它MySQL的连接一样,slave在master中打开一个连接也会使得master开始一个线程。复制过程有一个很重要的限制——复制在slave上是串行化的,也就是说master上的并行更新操作不能在slave上并行操作。 MySql的基本复制方式有主从复制、主主复制,主主复制即把主从复制的配置倒过来再配置一遍即可,下面的配置则是主从复制的过程,到时候可自行改为主主复制。其他的架构如:一主库多备库、环形复制、树或者金字塔型都是基于这两种方式,可参考《高性能MySql》。

二、配置过程

2.1 创建所用的复制账号

由于是个自己的小网站,就不做过多的操作了,直接使用root账号

2.2 配置master

接下来要对mysql的serverID,日志位置,复制方式等进行操作,使用vim打开my.cnf。

[client]default-character-set=utf8[mysqld]character_set_server=utf8init_connect= SET NAMES utf8datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.socksymbolic-links=0log-error=/var/log/mysqld.logpid-file=/var/run/mysqld/mysqld.pid# masterlog-bin=mysql-bin# 设为基于行的复制binlog-format=ROW# 设置server的唯一idserver-id=2# 忽略的数据库,不使用备份binlog-ignore-db=information_schemabinlog-ignore-db=clusterbinlog-ignore-db=mysql# 要进行备份的数据库binlog-do-db=myblog

重启Mysql之后,查看主库状态,show master status。

其中,File为日志文件,指定Slave从哪个日志文件开始读复制数据,Position为偏移,从哪个POSITION号开始读,Binlog_Do_DB为要备份的数据库。

2.3 配置slave

从库的配置跟主库类似,vim /etc/my.cnf配置从库信息。

[client]default-character-set=utf8[mysqld]character_set_server=utf8init_connect= SET NAMES utf8datadir=/var/lib/mysqlsocket=/var/lib/mysql/mysql.socksymbolic-links=0log-error=/var/log/mysqld.logpid-file=/var/run/mysqld/mysqld.pid# slavelog-bin=mysql-bin# 服务器唯一idserver-id=3# 不备份的数据库binlog-ignore-db=information_schemabinlog-ignore-db=clusterbinlog-ignore-db=mysql# 需要备份的数据库replicate-do-db=myblog# 其他相关信息slave-skip-errors=allslave-net-timeout=60# 开启中继日志relay_log         = mysql-relay-bin# log_slave_updates = 1# 防止改变数据read_only         = 1

重启slave,同时启动复制,还需要调整一下命令。

mysql> CHANGE MASTER TO MASTER_HOST = '119.23.46.71', MASTER_USER = 'root', MASTER_PASSWORD = 'helloroot', MASTER_PORT = 3306, MASTER_LOG_FILE = 'mysql-bin.000009', MASTER_LOG_POS = 346180;

可以看见slave已经开始进行同步了。我们使用show slave status\G来查看slave的状态。

其中日志文件和POSITION不一致是合理的,配置好了的话,即使重启,也不会影响到主从复制的配置。

某天在Github上漂游,发现了阿里的canal,同时才知道上面这个业务是叫异地跨机房同步,早期,阿里巴巴B2B公司因为存在杭州和美国双机房部署,存在跨机房同步的业务需求。不过早期的数据库同步业务,主要是基于trigger的方式获取增量变更,不过从2010年开始,阿里系公司开始逐步的尝试基于数据库的日志解析,获取增量变更进行同步,由此衍生出了增量订阅&消费的业务。下面是基本的原理:

原理相对比较简单:

1.canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送dump协议 2.mysql master收到dump请求,开始推送binary log给slave(也就是canal) 3.canal解析binary log对象(原始为byte流)

其中,配置过程如下:https://github.com/alibaba/canal,可以搭配Zookeeper使用。在ZKUI中能够查看到节点:

一般情况下,还要配合阿里的另一个开源产品使用otter,相关文档还是找找GitHub吧,个人搭建完了之后,用起来还是不如直接使用mysql的主主复制,而且异地机房同步这种大企业才有的业务。

公司又要996了,实在是忙不过来,感觉自己写的还是急躁了点,困==

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术

使用Spring AOP实现MySQL数据库读写分离案例分析

分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量。

712
来自专栏文渊之博

SQL 扩展事件

    在本篇,我通过使用新建“Session ”对话框来创建新的扩展事件会话。定义一个自己的扩展事件,动作和谓词,并且发布一个以收集事件数据为目的的会话。 首...

1907
来自专栏大数据

开始使用Kafka

我们来看一个使用Kafka命令行的生产者和消费者的简单例子。

2591
来自专栏技术翻译

Kubernetes Demystified:Java应用程序资源的限制

随着容器技术变得越来越复杂,越来越多的企业客户选择Docker和Kubernetes作为其应用平台的基础。但是,这些客户在实践中遇到许多问题。本系列文章介绍了阿...

400
来自专栏「3306 Pai」社区

MySQL中sync_relay_log选项对I/O thread的影响分析

搭建好的一套从库,发现延迟很高,一直追不上,从库的bin_log没开,flush_log_at_trx_commit设置为0,简化的状态如下:

991
来自专栏吴伟祥

Linux Partition scheme 分区方案(一)

根分区包含Linux系统所有的目录。如果在安装系统时只分配了/分区,那么上面的/boot、/usr和/var将都包含在根分区中,也就是这些分区将占用根分区的空间...

1102
来自专栏BeJavaGod

ZooKeeper 一二事 - 搭建ZooKeeper伪分布式及正式版集群 提供集群服务

集群真是好好玩,最近一段时间天天搞集群,redis缓存服务集群啦,solr搜索服务集群啦,,,巴拉巴拉 今天说说zookeeper,之前搭建了一个redis集...

2674
来自专栏大魏分享(微信公众号:david-share)

如何构建一个安全的Glusterfs分布式文件系统集群?

1484
来自专栏PHP在线

3种web会话管理的方式

http是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的。当然它知道是哪个客户端地址发过来的,但是对于我们的应用来...

923
来自专栏Ryan Miao

SpringCloud学习1-服务注册与发现(Eureka)

前言 Oracle转让Java,各种动态语言的曝光率上升,Java工程师的未来在哪里?我觉得Spring Cloud让未来有无限可能。拖了半年之久的Spring...

8957

扫码关注云+社区