Mysql主从复制和Redis主从复制

MySql主从复制

MySQL主从复制是一个异步的复制过程, 底层是基于MySQL数据库自带的二进制日志功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制然后解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。MySQL主从复制是MySQL自带功能,无需借助第三方工具。

主库做增删改操作,从库做查操作。

MySQL复制过程分为三步:(master只能有一个,slave可以有多个)
1.master将记录改变到二进制日志(binary log)
2.slave将master的binary log 拷贝到它的中继日志(relay log)
3.slave重做中继日志中的事件,将改变应用到自己的数据库中

配置前置条件:

提前准备好两台服务器,分别安装mysql并启动服务成功
主库Master 192.168.138.100
从库slave 192.168.138.101

配置-主库master

第一步:修改MySql数据库的配置文件/etc/my.cnf
[mysql]
log-bin=mysql-bin #[必须]启用二进制文件
server-id=100 #[必须]服务器唯一ID

第二步:重启mysql服务
systemctl restart mysqld

第三步:登录mysql数据库,执行下面SQL
GRANT REPLICATION SLAVE ON . to ‘xiaoming’@‘%’ identified by ‘Root@123456’;
注:上面SQL的作用是创建一个用户xiaoming,密码为Root@123456,并且给xiaoming用户授予REPLICATION SLAVE权限。常用于
建立复制时所需要用到的用户权限,也就是slave必须被master授权具有该权限的用户,才能通过该用户复制。

第四步:登录mysql数据库,执行sql,记录下结果中File和Position的值
show master status;//File的值是slave第三步sql中的master_log_file,Position是slave第三步sql中的master_log_pos
注:上面SQL的作用是查看master的状态,执行完SQL后不要执行任何操作

配置-从库slave

第一步:修改MySql数据库的配置文件/etc/my.cnf
[mysql]
server-id=101 #[必须]服务器唯一ID

第二步:重启mysql服务
systemctl restart mysqld

第三步:登录mysql数据库,执行下面SQL
change master to
master_host=‘192.168.138.100’,master_user=‘xiaoming’,master_password=‘Root@123456’,master_log_file=‘mysql-bin.000001’,master_log_pos=439;

start slave;

第四步:登录mysql数据库,执行sql,查看从数据库的状态
show slave status;//很多,重点看Slave_IO_Running、Slave_SQL_Running的值是否是Yes

读写分离案例

主库负责处理事务性的增删改操作,从库负责处理查询操作,能够有效的避免由数据更新导致的行锁,使得整个系统的查询性得到极大的改善。

Sharding-JDBC介绍
使用Sharding-JDBC可以轻松实现数据库读写分离。
1.适用于任何基于JDB的CORM框架。如:JPA、Hibernate、Mybatis;
2.支持任何第三方数据库连接池。如:DBCP、C3P0、Druid;
3.支持任何实现JDBC规范的数据库。

使用Sharding-JDBC实现读写分离步骤:

1.导入maven坐标
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.0-RC1</version>
</dependency>
2.在配置文件中配置读写分离规则
spring:
  shardingsphere:
    datasource:
      names:
        master,slave
      #主数据源
      master:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.138.100:3306/rw?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: root
      #从数据源
      slave:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.138.101:3306/rw?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
        username: root
        password: root
    masterslave:
      #读写分离配置
      load-balance-algorithm-type: round_robin #轮询
      #最终数据源名称
      name: dataSource
      #主数据源名称
      master-data-source-name: master
      #从数据源名称列表,多个逗号分隔
      slave-data-source-names: slave
    props:
      sql:
        show: true #开启sql显示,默认为false

3.在配置文件中配置运行bean定义覆盖配置项
spring:
  main:
    allow-bean-definition-overriding: true

Redis主从复制

主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主可以读,Slave只能读,不能写。

主要功能:读写分离,性能扩展;容灾快速恢复。

以一主二从为例:有三台服务器192.168.1.1(主) 192.168.1.2 192.168.1.3 分别装了redis。

如何搭建(一主二从):
redis.conf文件修改:
daemonize yes 开启后台启动
Appendonly no 关闭AOF持久化,只用RDB持久化
实现一主二从(不配主机只配从机):这种配置方式只在本次连接有效,如果redis断开连接就失效了。
分别启动redis并登录。
登录进入之后,查看其主机运行的情况:info replication。这个时候三台都是主机,没有从机。
登录从机输入:slaveof <主机ip> <主机端口> 就是服务器2和3 输入:slaveof 192.168.1.1 6379。

永久的配置方式:修改从机(2、3)的配置文件,找到主从配置部分,配置文件搜索replication,大概在配置文件的第386行 replicaof 把注释去掉,这是配置主机的地址和端口。
如果主机有密码,大概在配置文件393行,注释去掉,masterauth 这是配置主机的password。

一主二从

1.当主机断电宕机(可以手动执行shutdown来模拟),默认情况下从机的角色不会发生改变(从机2、3的主机仍然是1),当主机恢复之后,又会连接上从机恢复原状(可以多使用info replication来查看状态)。
2.当从机断电宕机,若不是使用配置文件配置的从机,再次启动后作为主机(从机变成了主机)是无法获取之前主机的数据的,若此时重新配置成为从机,又可以获取到主机的所有数据。

复制原理

slave启动成功后给master发送一个sync(同步)命令。
主数据收到命令之后会开始在后台保存快照(即RDB持久化过程)。并将保存快照期间接受到的修改命令缓存起来,当快照完成后,redis会将快照文件(rdb文件)发给从服务器,从服务器读rdb文件执行命令。
全量复制:slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。(刚开始从机连接主机,主机一次给,是全量复制的过程)。
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步 (主机修改了数据会给予从机修改的数据同步,叫做增量复制)。

薪火相传

上一个Slave(2)可以是下一个slave(3)的Master,Slave(2)同样可以接收其他 slave(3)的连接和同步请求,那么该slave(2)作为了链条中下一个的master, 可以有效减轻master(1)的写压力,去中心化降低风险。

slave(3)用 slaveof ,(slaveof 192.168.1.2)中途变更转向:会清除之前的数据,重新建立拷贝最新的。
风险是一旦中间链条某个slave宕机,后面的slave都没法备份,主机挂了,从机还是从机,无法写数据了。

反客为主(默认情况下使用slaveof命令配置)

(薪火相传模式下)当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改。
可以使用命令:slaveof no one 将从机变为主机。
(一主二从模式下),master宕机,一台主机(2)执行slaveof no one 变为主机,其他主机(3)执行命令重新连接主机(2)。

哨兵模式

主要是为了监控主机宕机之后,从机可以立马变为主机,就和上面的反客为主一样(但是是在一主多从里使用),不用手动设置。
能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。

如何实现:
在redis的配置文件所在的文件夹下,创建一个哨兵文件sentinel.conf。
sentinel.conf:

# 哨兵 监视 【名称】 监视的主机地址 端口 ; 
# 最后一位 11 为至少有多少个哨兵同意迁移的数量
sentinel monitor mysentinel 127.0.0.1 6379 1

在 Redis 启动目录有一个哨兵文件redis-sentinel
启动命令:redis-sentinel /sentinel.conf

具体哪个从机会变成主机,其判定规则主要为:(优先级>偏移量>runid)
优先级在redis.conf中默认:slave-priority 100,值越小优先级越高;
偏移量是指获得原主机数据最全的,也就是数据越多,变主机的机会越大;
每个redis实例启动后都会随机生成一个40位的runid.

哨兵模式的优缺点:
哨兵集群,基于主从复制模式,所有主从复制的优点,它都有;主从可以切换,故障可以转移,系统的可用性更好;哨兵模式是主从模式的升级,手动到自动,更加健壮。
Redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦;实现哨兵模式的配置其实是很麻烦的,里面有很多配置项。

完整的哨兵模式配置文件 sentinel.conf

# Example sentinel.conf
 
# 哨兵sentinel实例运行的端口 默认26379
port 26379
 
# 哨兵sentinel的工作目录
dir /tmp
 
# 哨兵sentinel监控的redis主节点的 ip port 
# master-name  可以自己命名的主节点名字 只能由字母A-z、数字0-9 、这三个字符".-_"组成。
# quorum 当这些quorum个数sentinel哨兵认为master主节点失联 那么这时 客观上认为主节点失联了
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 127.0.0.1 6379 1
 
# 当在Redis实例中开启了requirepass foobared 授权密码 这样所有连接Redis实例的客户端都要提供密码
# 设置哨兵sentinel 连接主从的密码 注意必须为主从设置一样的验证密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster MySUPER--secret-0123passw0rd
 
 
# 指定多少毫秒之后 主节点没有应答哨兵sentinel 此时 哨兵主观上认为主节点下线 默认30秒
# sentinel down-after-milliseconds <master-name> <milliseconds>
sentinel down-after-milliseconds mymaster 30000
 
# 这个配置项指定了在发生failover主备切换时最多可以有多少个slave同时对新的master进行 同步,
这个数字越小,完成failover所需的时间就越长,
但是如果这个数字越大,就意味着越 多的slave因为replication而不可用。
可以通过将这个值设为 1 来保证每次只有一个slave 处于不能处理命令请求的状态。
# sentinel parallel-syncs <master-name> <numslaves>
sentinel parallel-syncs mymaster 1
 
 
 
# 故障转移的超时时间 failover-timeout 可以用在以下这些方面: 
#1. 同一个sentinel对同一个master两次failover之间的间隔时间。
#2. 当一个slave从一个错误的master那里同步数据开始计算时间。直到slave被纠正为向正确的master那里同步数据时。
#3.当想要取消一个正在进行的failover所需要的时间。  
#4.当进行failover时,配置所有slaves指向新的master所需的最大时间。不过,即使过了这个超时,slaves依然会被正确配置为指向master,但是就不按parallel-syncs所配置的规则来了
# 默认三分钟
# sentinel failover-timeout <master-name> <milliseconds>
sentinel failover-timeout mymaster 180000
 
# SCRIPTS EXECUTION
 
#配置当某一事件发生时所需要执行的脚本,可以通过脚本来通知管理员,例如当系统运行不正常时发邮件通知相关人员。
#对于脚本的运行结果有以下规则:
#若脚本执行后返回1,那么该脚本稍后将会被再次执行,重复次数目前默认为10
#若脚本执行后返回2,或者比2更高的一个返回值,脚本将不会重复执行。
#如果脚本在执行过程中由于收到系统中断信号被终止了,则同返回值为1时的行为相同。
#一个脚本的最大执行时间为60s,如果超过这个时间,脚本将会被一个SIGKILL信号终止,之后重新执行。
 
#通知型脚本:当sentinel有任何警告级别的事件发生时(比如说redis实例的主观失效和客观失效等等),将会去调用这个脚本,
#这时这个脚本应该通过邮件,SMS等方式去通知系统管理员关于系统不正常运行的信息。调用该脚本时,将传给脚本两个参数,
#一个是事件的类型,
#一个是事件的描述。
#如果sentinel.conf配置文件中配置了这个脚本路径,那么必须保证这个脚本存在于这个路径,并且是可执行的,否则sentinel无法正常启动成功。
#通知脚本
# sentinel notification-script <master-name> <script-path>
  sentinel notification-script mymaster /var/redis/notify.sh
 
# 客户端重新配置主节点参数脚本
# 当一个master由于failover而发生改变时,这个脚本将会被调用,通知相关的客户端关于master地址已经发生改变的信息。
# 以下参数将会在调用脚本时传给脚本:
# <master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
# 目前<state>总是“failover”,
# <role>是“leader”或者“observer”中的一个。 
# 参数 from-ip, from-port, to-ip, to-port是用来和旧的master和新的master(即旧的slave)通信的
# 这个脚本应该是通用的,能被多次调用,不是针对性的。
# sentinel client-reconfig-script <master-name> <script-path>
sentinel client-reconfig-script mymaster /var/redis/reconfig.sh

你可能感兴趣的:(mysql,redis)