疑惑解答

为什么需要主从架构?

  • 读写分离,使数据库能支撑更大的并发
  • 数据库热备,故障切换

为什么不采用多主或者多主多从?

在主主模式下,两个主库都提供读写服务,如果应用通过两个主库操作相同数据,则会发生冲突导致数据覆盖(使用语句模式复制)或复制异常(使用行模式复制),因此需要对读写服务进行控制: 1、基于自主主键控制,通过设置自增属性auto_increment_offset和auto_increment_increment来控制每个主节点生产不同的自增值,并根据不同自增值访问不同主节点。 2、基于库级别或表级别控制,如应用APP1访问节点node1上的DB1库,而应用APP2访问节点node2上的DB2库,两个主节点间不会操作相同表的数据,因此不会存在事务冲突。

存在数据丢失,维护难度极高,因此不在考虑主主同步。

主从架构原理简单说明

MySQL的主从复制都是单线程的操作,主库对所有DDL和DML产生的日志写进binlog,由于binlog是顺序写,所以效率很高,slave的sql thread线程将主库的DDL和DML操作事件在slave中重放。

DML和DDL的IO操作是随机的,不是顺序,所以成本要高很多,另一方面,由于sql thread也是单线程的,当主库的并发较高时,产生的DML数量超过slave的SQL thread所能处理的速度,或者当slave中有大型query语句产生了锁等待,那么延时就产生了。

  1. 业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力。
  2. 单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库。
  3. 服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力。
  4. 不同业务的mysql物理上放在不同机器,分散压力。
  5. 使用比主库更好的硬件设备作为slave,mysql压力小,延迟自然会变小。
  6. 使用更加强劲的硬件设备

如何热更新云上(阿里云/腾讯云)数据库做热备?

当然我们是不推荐这么做的,因为云上数据库也有存在超牛的备份流程。 如果非要在本地热备云上数据库可以如下操作:

  1. 在同机房创建一个ECS服务器, 配置不低于数据库配置
  2. 安装同版本数据库
  3. 通过内网建立主从同步,并开启binlog
  4. 将ECS的从节点开放外网
  5. 本地安装数据库并同步ECS服务器的数据库

因为直接同步云上数据库binlog会有网络延迟,导致主服务器会性能明显下降,因此不降低主数据库情况下只能内网创建主从让后做 主服务-> 第一代从服务器(仅做中转因此即使性能下降也没关系) -> 第二代从服务器

搭建主从数据库

安装数据库

我已经在《MySQL 二进制安装以及不同安装方式区别》说明了数据库的基本安装
我已经在《MySQL 用户与角色》说明了数据库用户与角色

配置数据库

  1. # 停止数据库运行
  2. # 我通过我之前的文档, 已经安装好了二个不同目录的数据库 端口分别是3306和3307
  3. # 我们先查看my.cnf 文件
  4. # 你必须先检查自己的my.cnf中
  5. # socket basedir datadir pid-file log_error 字段的指定的路径正确
  6. # 在my.cnf 中修改如下配置
  7. # Mysql服务的唯一编号 每个mysql服务Id需唯一
  8. server-id = 1
  9. #开启bin log 功能并指定存放路径
  10. log-bin=/opt/mysql8/mysql-bin
  11. #binlog 记录内容的方式,记录被操作的每一行
  12. binlog_format=ROW
  13. #对于binlog_format = ROW模式时,FULL模式可以用于误操作后的flashBack。
  14. #如果设置为MINIMAL,则会减少记录日志的内容,只记录受影响的列,但对于部分update无法flashBack
  15. binlog_row_image=FULL
  16. #不同步的数据库
  17. binlog-ignore-db=mysql
  18. #启动数据库的运行
  19. nohup ./mysql8/bin/mysqld --defaults-file=/opt/mysql8/my.cnf >/dev/null 2>&1 &
  20. nohup ./mysql8s/bin/mysqld --defaults-file=/opt/mysql8s/my.cnf >/dev/null 2>&1 &

同步数据

# 这个时候就需要将主数据库新建的数据库同步到从数据库

# 我是为了开发测试只是将数据库的目录复制了一遍
# 你们可以通过任何工具任何方法同步数据就可以了, 也可以参看后面的数据库备份恢复章节

测试数据库连接

# 分别打开二个ssh 窗口连接数据库
./mysql8/bin/mysql -uroot -p --socket=/opt/mysql8/mysql.sock 

./mysql8s/bin/mysql -uroot -p --socket=/opt/mysql8s/mysql.sock 

# 查看一下端口别连接错了
show variables like 'port';

建立同步 (容易出错,请反复阅读)

# 创建同步用户 主从都要执行, 根据自己的安全规则修改限制IP以及密码
CREATE USER IF NOT EXISTS 'xsql'@'%' IDENTIFIED WITH mysql_native_password BY 'lxsqaz123!@#';
GRANT ALL PRIVILEGES ON *.* TO 'xsql'@'%' WITH GRANT OPTION;
flush privileges;

# -----------------------------

# 显示主节点状态
show master status;
# File                                 Position
# mysql-bin.000001        855

# 显示从节点状态
show slave status \G

# -----------------------------
# 开始建立同步

# 停止从节点同步
stop slave;

# 重置从节点同步状态
reset slave all;

# 建立同步
CHANGE MASTER TO MASTER_HOST='127.0.0.1', MASTER_PORT=3306, MASTER_USER='xsql', MASTER_PASSWORD='lxsqaz123!@#', MASTER_LOG_FILE='mysql-bin.000001',  MASTER_LOG_POS=855;


# 开始同步
start slave;

# 查看状态中
show slave status \G

#下面字段都表示Yes 才是成功
#Slave_IO_Running: No
#Slave_SQL_Running: Yes

# 我没有成功, 查看下错误日志
#  Last_IO_Error : Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. 
# 原来是我的server-id 相同了 修改一下, 重新执行 16行开始
# 还是不对, 原来我是复制的数据库导致UUID一样
# 删除数据库的auto.cnf文件
# rm -rf /opt/mysql8s/auto.cnf, 重新执行 16行开始

# 然后就正常了
#Slave_IO_Running: No
#Slave_SQL_Running: Yes

如果主从成功, 从节点应该如下:

image.png

成果

主数据库

image.png

从数据库已经有同步的数据了

image.png