• mysql 主从复制与读写分离


    主从复制概念

    主mysql上的数据,新增,修改库,表,表里的数据,都会同步到mysql上,查不在此类

    主从复制是单向的,只能从主复制到从,从数据库无法复制到主数据库器

    主从复制的工作过程

    1主节点的数据记录发生变化都会记录在二进制日志
    2Slave节点会在一定时间内对主库的二进制文件进行探测,看其是否发生变化,如果发生变化,从库他会开启一个I/O的线程请求master主库的二进制事件
    3主库会给每一个I/O的线程启动一个dump,用于发送二进制事件给从库,从库通过I/O线程获取更新,slave_sql负责将更新写入到从库本地,实现主从一至。

    Mysql的主从复制的模式

    异步复制

    异步复制:mysql的默认复制就是异步复制(不管发送结果),只要执行完之后,客户端提交事务,主mysql会立即把结果返回从服务器,主mysql并不关心mysql是否已经接收,并且处理。

    主一旦崩溃,主mysql的事务可能没有传到从mysql,这个时候强行把从服务器提升为主,可能到新的主mysql,数据不完整(很少见,工作当中都是异步复制)

    全同步复制全同步复制:主库执行完成一个事务,要等待所有的从库都执行了该事务之后才会返回客户端,因为需要等待所有从库全部执行完成,性能必然下降。(对数据一致性,和数据完整要求很好的场景)
    半同步复制

    半同步复制:介于异步复制和全同步复制之间,主库执行完一个客户端提交的事务之后,至少等待一个从库接收并处理完成之后,才会返回客户端。半同步在一定程度上提高了数据的安全性,也会有一定的延迟。

    这个延迟一般是一个tcp/ip的往返时间。(从发送到接收的时间,单位是毫秒),半同步复制最好在低延时的网络中使用。

    这边会有一个专业名词:时间<1ms:  round-trip time RTT

    mysql主从复制延迟如何解决

    硬件方面

    主库一般不需要动的太多,从库配置要更好,提升它的随机写能力性能,比如硬盘可以换成固态

    升级cpu核数,扩大下内存,尽量使用物理机(不要用云服务器)

    网络层面主从服务器都配置在一个局域网内,尽量避免跨网段和跨机房
    架构方面读写分离,把写入控制在主库,从库负责读,降低从库的压力
    配置方面mysql配置从配置文件的角度实现性能最大化

    追求安全性的双一设置

    追求安全性的配置

    innodb_flush_log_at_trx_commit=1

    1每次提交事务时都会刷新事务日志,以确保持久性,这是最高级别的数据安全性,但是会影响性能,默认就是1
    00就是事务提交时不会立刻刷新,而是每秒刷新一次,可以提性能,但是发生故障会导致数据丢失。
    22事务提交时,事务日志不会写入硬盘而是保存在系统缓存,也不会进行刷新,提供了一定的安全性能,但要求内存要求比较高
    Sync_binlog=1
    11也是默认值,每次提交事务之后,直接把二进制日志刷新到磁盘,以确保日志的持久性,但会占用比较高的性能,但是安全性高
    0会把日志写入到缓存,也不会刷新日志,故障发生也会丢失数据,内存的要求也提高了
    N每提交了N次事务执行一次刷新到磁盘,提高性能,但是一旦崩溃,数据会大量丢失

    追求性能化

    sync_binlog=0
    0设置为0表示二进制日志(binary log)写入操作系统缓存,但不进行物理刷新。
    这提供了较高的性能,但在系统崩溃或断电时可能会导致未刷新的二进制日志数据的丢失
    2innodb_flush_log_at_trx_commit=2:
    设置为2表示事务提交时将事务日志写入操作系统缓存,但不进行物理刷新。
    这提供了一定的性能提升,但在系统崩溃或断电时可能会导致未刷新的事务日志数据的丢失。
    logs-slave-updates=0:
    如果设置为0,表示不将从库的更新写入二进制日志。
    这对于避免在主从复制中引入循环复制(circular replication)很有用

    增大 innodb_buffer_pool_size
    innodb_buffer_pool_size 控制 InnoDB 存储引擎的缓冲池大小。增大这个值可以提高 InnoDB 的性能,
    因为更多的数据和索引可以缓存在内存中,减少了对磁盘的访问次数。但要注意,
    设置得太大可能导致系统内存不足。

    Innodb_buffer_pool_size 300M 500G

    Innodb 存储引擎的缓存池大小,设置的s数值越高,可以提高innodb的性能

    主从复制的问题

    1只能在主库上发生变化,然后同步到从
    2复制过程是串行化过程,在从库上复制是串行的,主库的并行更新不能再slave从库上并行操作
    3核心意义:主从复制的设计目的就是为了实现读写分离,也就是在主库上写,在从库上查,读写分离,实现高可用

    读写分离概念

    1要实现读写分离,必须要先实现主从复制
    2读写分离:所有的写入操作都在主库,从库只负责读(select)。如果有更新,是从主库复制到从库

    为什么要有读写分离

    1数据库在写入数据时比较耗时(mysql写1w条数据要3分30秒)
    2数据库在读的时候,速度很快(读1w条只需要4.96秒)
    读写分离之后,数据库的写入和读取是分开的,哪怕写入的数据量比较大,但是不影响查询的效率。

    什么场景需要读写分离

    1数据库不是一定需要读写分离的,只有在某些程序在使用过程中,更新很少,查询较多,这种情况可以考虑读写分离,读和查的需求差不多,也可以考虑读写分离
    2生产库一般都会做读写分离
    3测试库一般不管
    4在工作当中,数据库的读写不会在同一个库中完成。既不安全也不满足高可用,也不能实现高并发。工作中都会做读写分离

    Mysql读写分离的原理,如何实现的

    根据脚本实现在代码当中实现路由分类,select insert 进行路由分类,这类方法是最多的
    特点性能好,在代码中就可以实现,不需要额外的硬件设备
    缺点开发实现的,跟我们无关,如果大型的应用复杂的应用,设计改动的代码非常多
    基于中间层代理实现Mysql-proxy:自带的开源项目,基于自带的lua脚本,这些lua脚本不是现成的,要自己写,如果你不熟悉他的内置变量写不出来
    Atlas360内部自己使用的代理工具,每天的读写请求承载量可以到几十亿条,还支持事务,还支持存储过程
    Amoeba阿米巴 :陈思儒,之前在阿里就职,由java开发的一个开源团建,他不支持事务,也不支持存储过程,但是amoeba 还是用的最多的,功能比较强大的软件

    出现Slave_IO_Running: NO 原因

    1网络问题
    2My.cnf 配置文件写错了
    3配置文件  CHANGE master to。。。   要么是文件名错了 ,要么是配置文件错了
    4防火墙策略问题

    主从复制延迟问题

    1网络问题
    2主从硬件问题(cpu主频频率也就是性能不够,内存IO,硬件IO)
    3同步复制而不是异步复制

    面试题

    主从复制原理

    开发可以说脚本

    运维一般用amoeba或者mycat

    如何查看主从复制是否成功

    show salve status\G 两个yes就ok

    在主库创建表或库,看能否同步到从库

    如果slave_IO_running no 排查思路是什么85%配置文件
    show slave STATUS\G 能看到的信息有哪些

    IO和sql线程的状态信息

    Master的服务器的ip地址,端口,事务开始的位置

    最近一次的错误信息和错误的位置

    最近一次的IO报错信息

    最近一次sql报错的信息

    主从复制的延迟如何解决

    主从复制数据库 show slave status\G内容解释

    slave_IO_State:Waiting for master to send event等待接收主数据库的操作与变化
    master_host:192.168.233.88指定主服务器ip地址是谁
    masteruser:myslave登录主服务器的名称为myslave
    master_port:3306主服务器的端口是3306
    connect_retry:60连接重试60秒
    master_log_file:master-bin.000001指定master
    read_master_log_pos每个起始位置开始指定604
    relay_log_file:relay-log-bin.000002从服务器自己的起始位置日志
    relay_master_log_file=master-bin.000001一切变化都指向主的000001来

    架构主从复制和读写分离

    主从复制

    1. #Mysql1为主,Mysql2为从,Mysql3为从,Test1作为读写分离的服务器,Test2作为客户端
    2. #时间必须要同步
    3. 主mysql
    4. systemctl stop firewalld
    5. setenforce 0
    6. yum -y install ntp
    7. vim /etc/ntp.conf
    8. #最后一行添加
    9. server 127.127.233.0
    10. #233为自己ip地址所在网段
    11. fudge 127.127.233.0 stratum 8
    12. #从本地获取时间源同步,不走网络,设置层级,数字越小,时间精确度越高,设置fudge 8,最高到15
    13. wq!
    14. systemctl restart ntpd
    15. #时间同步完成之后的操作
    16. vim /etc/my.cnf
    17. log-bin=master-bin
    18. #打开二进制日志,它是根据二进制日志进行同步的
    19. binlog_format=MIXED
    20. #如果并发量变高,会自动切换高并发
    21. log-slave-updates=true
    22. #允许从数据库复制数据时,可以从主数据库的二进制日志写到自己的二进制日志当中
    23. wq!
    24. systemctl restart mysqld
    25. mysql -u root -p123456
    26. grant replication slave on *.* to 'myslave'@'192.168.233.%' identified by '123456';
    27. #给从数据库授权,从库能够访问主数据库,给他定义一个用户名为myslave,从233这个网段中来,密码是123456
    28. flush privileges;
    29. show master status;
    30. #最主要的就是看master-bin.000001,position下的604,看系统显示每个人可能都不一样
    31. 从mysql(1)
    32. systemctl stop firewalld
    33. setenforce 0
    34. yum -y install ntp
    35. systemctl restart ntpd
    36. /usr/sbin/ntpdate 192.168.233.88
    37. #两台从数据库的时间源指向主数据库的
    38. crontab -e -u root
    39. #生产当中会加一个定时任务,随时进行同步
    40. */30 * * * * /usr/sbin/ntpdate 192.168.233.88
    41. #每三十分钟执行一次与主数据库进行时间同步
    42. wq!
    43. #同步完成之后可以多重执行 date 查看时间是否同步成功
    44. vim /etc/my.cnf
    45. server-id = 2
    46. #id不能重复
    47. relay-log=relay-log-bin
    48. #名称可以自定义
    49. relay-log-index=slave-relay-bin.index
    50. relay_log_recovery=1
    51. #默认是0,1表示开启中继日志的恢复,如果从数据库出现异常或者崩溃时,从数据库会从主数据库二进制日志正确读取和应用中继日志,主要是为了同步,如果不开启,需要手动添加。
    52. wq!
    53. systemctl restart mysqld
    54. mysql -u root -p123456
    55. CHANGE master to
    56. master_host='192.168.233.88',master_user='myslave',master_password='123456',master_log_file='master-bin.000002',master_log_pos=604;
    57. #指向主数据库,之前创建的用户myslave,它的密码是123456,指定它的二进制日志文件为000002,主的position是多少就输入多少,这边是604
    58. start slave;
    59. #开启从服务器
    60. show slave status\G;
    61. #看slave_IO_Running:Yes
    62. #负责和主库的IO通信
    63. #slave_SQL_Running:Yes 是否都为yes
    64. #负责自己的slave mysql 进程
    65. 从mysql(2)
    66. systemctl stop firewalld
    67. setenforce 0
    68. yun -y install ntp
    69. systemctl restart ntpd
    70. /usr/sbin/ntpdate 192.168.233.88
    71. crontab -e -u root
    72. */30 * * * * /usr/sbin/ntpdate 192.168.233.88
    73. wq!
    74. vim /etc/my.cnf
    75. server-id = 3
    76. #id不能相同
    77. relay-log=relay-log-bin
    78. relay-log-index=slave-slave-relay-bin,index
    79. relay_log_recovery = 1
    80. #与从数据库2一样
    81. wq!
    82. systemctl restart mysqld
    83. mysql -u root -p123456
    84. CHANGE master to
    85. master_host='192.168.233.88',master_user='myslave',master_password='123456',master_log_file='master-bin.000002',master_log_pos=604;
    86. start slave;
    87. show slave status\G;

    amoeba读写分离

    1. 读写分离基于主从复制,要实现读写分离,必须要先实现主从复制
    2. 主数据库
    3. mysql -u root -p123456
    4. grant all on *.* to 'amoeba'@'192.168.233.%' identified by '123456';
    5. #开放权限给amoeba给,233整个网段,密码123456
    6. flush privileges;
    7. vim /etc/my.cnf
    8. general_log=on
    9. general_log_file=/usr/local/mysql/data/mysql_general.log
    10. #最下面加上开启日志
    11. systemctl restart mysqld
    12. tail -f /usr/local/mysql/data/mysql_general.log
    13. 从数据库1
    14. mysql -u root -p123456
    15. grant all on *.* to 'amoeba'@'192.168.233.%' identified by '123456';
    16. flush privileges;
    17. vim /etc/my.cnf
    18. general_log=on
    19. general_log_file=/usr/local/mysql/data/mysql_general.log
    20. #最下面加上开启日志
    21. systemctl restart mysqld
    22. tail -f /usr/local/mysql/data/mysql_general.log
    23. 从数据库2
    24. mysql -u root -p123456
    25. grant all on *.* to 'amoeba'@'192.168.233.%' identified by '123456';
    26. flush privieges;
    27. vim /etc/my.cnf
    28. general_log=on
    29. general_log_file=/usr/local/mysql/data/mysql_general.log
    30. #最下面加上开启日志
    31. systemctl restart mysqld
    32. tail -f /usr/local/mysql/data/mysql_general.log
    33. amoeba
    34. java -version
    35. #看一下版本,推荐1.6
    36. cp jdk-6u14-linux-x64.bin /usr/local
    37. cd /usr/local
    38. chmod +x jdk-6u14-linux-x64.bin
    39. ./jdk-6u14-linux-x64.bin
    40. #执行完成之后直接yes,然后回车就行,之后会有提示需要...直接否就行
    41. mv jdk-6u14-linux-x64.bin jdk1.6
    42. #方便之后的环境变量好配置
    43. vim /etc/profile
    44. #最后一行添加
    45. export JAVA_HOME=/usr/local/jdk1.6
    46. export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
    47. export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
    48. export AMOEBA HOME=/usr/local/amoeba
    49. export PATH=$PATH:$AMOEBA_HOME/bin
    50. wq!
    51. source /etc/profile
    52. #立即生效
    53. java -version
    54. #看一下版本1.6就可以了
    55. mkdir /usr/local/amoeba
    56. tar -xf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
    57. chmod -R 755 /usr/local/amoeba/
    58. /usr/local/amoeba/bin/amoeba
    59. #出现amoeba start|stop就说明amoeba安装完毕了
    60. #主从数据库开放amoeba权限之后操作
    61. cd /usr/local/amoeba/conf/
    62. #amoeba.xml是配置用户信息,dbServer.xml配置数据库信息,改配置文件之前最好先备份一下,看个人意愿不强制
    63. vim amoeba.xml
    64. #amoeba默认的端口是3306
    65. "user">amoeba
    66. #第30行将root改成amoeba,之前给的权限是给amoeba的所以不能用root
    67. "password">123456
    68. #第32行密码可以自定义
    69. "defaultPool">master
    70. #第115行指定主
    71. "writepool">master
    72. "readpool">saves
    73. #第117行和120行的注释 ,取消掉,写指定master写,读指定slaves,slaves表示有多个从服务器
    74. vim dbServer.xml
    75. #将22行23行注释掉,默认会往test库,如果myql没有test库就会报错,把22行右边注释删除掉,24行加上-->
    76. "user">amoeba
    77. #26行改一下名字改成amoeba
    78. "password">123456
    79. #28行删除掉,30行注释也删除掉,29行密码改成123456
    80. "master" parent="abstractServer">
    81. #45行先指定主,48行指定主的ip地址192.168.233.88
    82. "slave1" parent="abstractServer">
    83. #52行指定从,55行指定从ip地址192.168.233.89
    84. #再从52行yy复制6行在57行p插入,要把slave1改成2,ip地址也要改成19.168.233.90
    85. "slaves" virtual="true">
    86. #65行指定从服务器
    87. "poolNames">slave1,slave2
    88. #71行对应slave1和slave2
    89. wq!
    90. /usr/local/amoeba/bin/amoeba start &
    91. netstat -antp | grep java
    92. #看一下端口起来没
    93. 客户端
    94. yum -y install mariadb-server mariadb
    95. #安装需要epel源
    96. systemctl restart mariadb.service
    97. netstat -antp | grep 3306
    98. mysql -u amoeba -p123456 -h192.168.233.66 -P8066
    99. show databases;
    100. insert into test values('test2')
    101. select * from test;
    102. select * from test;
    103. #可以实现轮询

    mycat读写分离

  • 相关阅读:
    C++基础知识(一)
    Redis主从复制
    二、鼎捷T100之MDS(Master Demand Schedule)计算
    Digester解析xml原理
    ROS2报错 AttributeError: type object ‘type‘ has no attribute ‘_TYPE_SUPPORT‘
    CUDA优化之LayerNorm性能优化实践
    设计模式 | 工厂模式
    如何在centos上安装nvidia驱动
    Warmup小记
    爬虫 — Js 逆向案例一英汉互译
  • 原文地址:https://blog.csdn.net/2301_79410672/article/details/134374863