主要介绍mysql的主从复制以及redis的主从复制
能由浅入深的明白原理以及如何操作
再者,在面试中能道道如来
主要参考了一些书籍,以及自我的理解
还有众多博客的学习链接等
关于mysql以及redis的一些知识点可看我之前的文章进行查询
java框架零基础从入门到精通的学习路线(超全)
redis在开头上主从复制,而mycat在接入点上主从复制,所以缺点是会导致延时性问题
指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点
关于主从复制的原理对应什么框架,在正文中有提及,此处就不提及
对于主从复制的优缺点如下:
优点:
做数据的热备。
(主数据库宕机,从数据库可继续工作,避免数据的丢失),更好的实现了负载均衡。降低磁盘I/O访问的频率,提高单个机器的I/O性能
读写分离,使数据库能支持更大的并发。
确保数据的安全(主从复制),提高了性能(主机宕机之后,从机也可以继续工作)
同步复制
master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回(比如在WEB前端页面上,用户增加了条记录,需要等待很长时间)
异步复制
如同AJAX请求一样。master只需要完成自己的数据库操作即可。不用理slaves是否收到二进制日志以及完成操作。(MYSQL的默认设置)。这种类似网络传输的udp
半同步复制
master只保证slaves中的一个操作成功,就返回,其他slave不管(由google为MYSQL引入)
关于增量复制和全量复制主要涉及到redis的框架:
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。(刚开始从机连接主机,主机一次给)
增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步 (主机修改了数据会给予从机修改的数据同步,叫做增量复制)
二进制日志(binary log)
。这些记录过程叫做二进制日志事件,binary log events;中继日志(relay log) ;
。MySQL复制是异步的且串行化的
,这样从节点不用一直访问主服务器来更新自己的数据关于主从复制的详细原理如下:
master将数据的改变
记录到二进制日志(binary log)
。这些记录过程叫做二进制日志事件,binary log events;当数据发生改变时,则将其改变写入二进制日志中;
slave会在一定时间间隔内对master二进制日志进行探测其是否发生改变
,如果发生改变,则开始一个I/OThread
请求master二进制事件
同时主节点为每个I/O线程启动一个dump线程
,用于向其发送二进制事件,并保存至从节点本地的中继日志中
,从节点将启动SQL线程
从中继日志中读取二进制日志,在本地重放
,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。
总的来说:
一个I/O线程,一个SQL线程;
请求主库的binlog
。主库会生成一个log dump线程,
用来给从库I/O线程传binlog。并将得到的binlog写到本地的relay-log(中继日志)
文件中;relay log文件中的日志,并解析成sql语句逐一执行;
复制的原则主要有:
关于mysql的主从复制的缺点
主要是延时
通过上面的机制,可以保证主从数据库数据一致,但是时间上肯定有延迟,即从机数据是滞后的。
由于sql thread也是单线程的,当主库的并发较高时,产生的DML数量超过slave的SQL thread所能处理的速度等的延时
解决方案如下:
1.业务的持久化层的实现采用分库架构,mysql服务可平行扩展,分散压力
2.单个库读写分离,一主多从,主写从读,分散压力。这样从库压力比主库高,保护主库
3.服务的基础架构在业务和mysql之间加入memcache或者redis的cache层。降低mysql的读压力
主从都配置在[mysqld]结点下,都是小写
具体的配置文件在window上是这么修改,主机修改my.ini
server-id=1
[必须]主服务器唯一ID
log-bin=自己本地的路径/mysqlbin
[必须]启用二进制日志
log-err=自己本地的路径/mysqlerr
[可选]启用错误日志
basedir=“自己本地路径”
[可选]根目录
tmpdir=“自己本地路径”
[可选]临时目录
datadir=“自己本地路径/Data/”
[可选]数据目录
binlog-ignore-db=mysql
[可选]设置不要复制的数据库
binlog-do-db=需要复制的主数据库名字
[可选]设置需要复制的数据库
linux上作为从机,从机修改my.cnf配置文件
在windows上授权 linux,只需要给予服务器ip等
GRANT REPLICATION SLAVE ON *.* TO ‘zhangsan’@‘从机器数据库IP’ IDENTIFIED BY ‘123456’;
show master status;
在linux中授权window的IP地址
CHANGE MASTER TO MASTER_HOST=’主机
IP’, MASTER_USER=‘zhangsan’, MASTER_PASSWORD=’123456’, MASTER_LOG_FILE='File名字’, MASTER_LOG_POS=Position数字;
start slave;
启动服务器的slaveshow slave status\G
stop slave;
停止如果主从都在linux上,具体详细配置如下:
gedit或者vim /etc/my.cnf
#主服务器唯一ID
server-id=1
#启用二进制日志
log-bin=mysql-bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
#设置logbin格式
binlog_format=STATEMENT
关于下面设置日志的格式
具体主要有三种
binlog_format=statement
,master写入执行的SQL语句到binlog中,从库读取这些SQL语句并执行,主机和从机的时间不一样,导致执行某些函数时可能造成主从不一致的情况binlog_format=row
,一行一句的复制,缺点执行 100 万次更新,会记录一百万次,效率更低binlog_format=mixed
, 它记录日志取决于修改的类型,选择合适的格式来记录该修改,缺点识别不了特定的名称[系统变量] 如 @@host name
从机的配置如下
# 从机服务器唯一 ID
server-id=2
# 启用中继日志
relay-log=mysql-relay
修改配置文件之后是要重启才可以使用
通过命令 service mysqld start
或者systemctl
等命令,以及关闭防火墙
查看其防火墙的状态 systemctl status firewalld
具体可看我防火墙这篇文章
主机的设置
主机上面创建一个用户,给从机,专门让从机来负责主从复制的权限
创建一个主从复制的权限 给slave用户,并且指定密码
GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123123';
查询master的状态,show master status;
显示日日志名称,接入点的位置开始复制,需要复制的数据库,以及不需要复制的数据库
从机配置
再从机输入的时候
如果之前有主从的一些,可以通过重新配置主从stop slave;
进行关闭服务器的复制,以及reset master;
重置主机
通过主机的配置,再从机中输入
主要是配置日志名称以及它的接入点位置等
CHANGE MASTER TO MASTER_HOST='主机的IP地址',
MASTER_USER='slave',
MASTER_PASSWORD='123123',
MASTER_LOG_FILE='mysql-bin.具体数字',MASTER_LOG_POS=具体值;
启动从服务器复制功能 start slave;
查看从服务器状态 show slave status\G;
,字段太多,可以通过列管理\G
的参数
有这两个参数代表成功了
主机增删改表格,从机可以查询到表格等信息
停止从服务复制功能 stop slave;
一个主机 m1 用于处理所有写请求,它的从机 s1 和另一台主机 m2 还有它的从机 s2 负责所有读请
求。当 m1 主机宕机后,m2 主机负责写请求,m1、m2 互为备机
双主机的一个配置
#主服务器唯一ID
server-id=1
#启用二进制日志
log-bin=mysql-bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
#设置logbin格式
binlog_format=STATEMENT
# 在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 .. 65535
auto-increment-increment=2
# 表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=1
第二个备份主机
#主服务器唯一ID
server-id=3 #启用二进制日志
log-bin=mysql-bin
# 设置不要复制的数据库(可设置多个)
binlog-ignore-db=mysql
binlog-ignore-db=information_schema
#设置需要复制的数据库
binlog-do-db=需要复制的主数据库名字
#设置logbin格式
binlog_format=STATEMENT
# 在作为从数据库的时候,有写入操作也要更新二进制日志文件
log-slave-updates
#表示自增长字段每次递增的量,指自增字段的起始值,其默认值是1,取值范围是1 .. 65535
auto-increment-increment=2
# 表示自增长字段从哪个数开始,指字段一次递增多少,他的取值范围是1 .. 65535
auto-increment-offset=2
从机的配置
#从服务器唯一ID
server-id=2
#启用中继日志
relay-log=mysql-relay
第二个从机的配置
#从服务器唯一ID
server-id=4 #启用中继日志
relay-log=mysql-relay
之后重启mysql的服务以及关闭防火墙的基本操作
在两台主机上建立帐户并授权 slave
执行sql的命令GRANT REPLICATION SLAVE ON *.* TO 'slave'@'%' IDENTIFIED BY '123123';
展示其状态,主要给从机使用以及备份的主机使用show master status;
第二个主机的查询状态同理
从机复制第一个主机的信息,第二个从机复制第二个主机的信息
CHANGE MASTER TO MASTER_HOST='主机的IP地址',
MASTER_USER='slave',
MASTER_PASSWORD='123123',
MASTER_LOG_FILE='mysql-bin.具体数字',MASTER_LOG_POS=具体值;
之后分别启动两个主机的复制功能start slave;
查看服务器的状态show slave status\G;
,出现俩个yes的状态代表已经可以实现
两个主机如何备份,和上面一样,主机复制备份主机的信息,备份主机输入主机的信息
start slave;
以及查看从服务器状态show slave status\G;
主机数据更新后根据配置和策略, 自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主
主要的功能有:
具体主从的复制原理:
从机主动发送
断开之后重新连接,只要是重新连接master,一次完全同步(全量复制)将被自动执行,rdb的数据就会给从机。
主机负责写,从机负责读
具体如何搭建
redis.conf文件
本身redis.conf文件中就有include的代码模块
所以在命令行中直接输入include 绝对路径
,就可引入
具体文件的内容修改如下
开启daemonize yes
后台启动
Appendonly 关掉或者换名字,也就是不要AOF的追加,只要RDB持久化
实现一主两从
步骤如下:
也就是3个配置文件
redis6379.conf
文件include /myredis/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
其他两个文件同理,只需要修改其pid进程号以及端口号,生成的rdb文件名
启动三台服务器
分别是redis-server 配置文件
以及登录进入redis-cli -p 端口号
登录进入之后,查看其主机运行的情况:info replication
其都是主机,而没有从机
为了显示一主两从
再登录进入的从机上输入:slaveof
在6380和6381上执行: slaveof 127.0.0.1 6379
情况1:一主两仆
主机挂掉,执行shutdown
从机info replication
还是显示其主机是挂掉的哪个
如果从机挂掉,执行shutdown
主机开始写数据,从机在开启的时候,恢复数据的时候是从主机从头开始追加的
情况2:薪火相传
上一个Slave可以是下一个slave的Master,Slave同样可以接收其他 slaves的连接和同步请求,那么该slave作为了链条中下一个的master, 可以有效减轻master的写压力,去中心化降低风险。
从机的大哥是另一台从机的意思
用 slaveof
,中途变更转向:会清除之前的数据,重新建立拷贝最新的
风险是一旦某个slave宕机,后面的slave都没法备份
主机挂了,从机还是从机,无法写数据了
情况3:反客为主
当一个master宕机后,后面的slave可以立刻升为master,其后面的slave不用做任何修改
可以使用命令:slaveof no one
将从机变为主机
主要是为了监控主机宕机之后,从机可以立马变为主机,就和上面的反客为主一样,不用手动设置
能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库
再目录中新建一个文件sentinel.conf
,文件格式不能出错
文件内容为
sentinel monitor mymaster 127.0.0.1 6379 1
代码的含义为 sentinel
哨兵,监控,一个id(别名),ip加端口号
其中mymaster为监控对象起的服务器名称, 1 为至少有多少个哨兵同意迁移的数量。
启动哨兵模式通过redis的bin目录下
命令如下:redis-sentinel /sentinel.conf
具体哪个从机会变成主机
其判定规则主要为
(顺序依次往下,优先级》偏移量》runid)
在这里也有个缺点就是复制会有延时
由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。
主要是ip端口号的连接
以及主机名称new JedisSentinelPool("mymaster",sentinelSet,jedisPoolConfig);
private static JedisSentinelPool jedisSentinelPool=null;
public static Jedis getJedisFromSentinel(){
if(jedisSentinelPool==null){
Set<String> sentinelSet=new HashSet<>();
sentinelSet.add("192.168.11.103:26379");
JedisPoolConfig jedisPoolConfig =new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(10); //最大可用连接数
jedisPoolConfig.setMaxIdle(5); //最大闲置连接数
jedisPoolConfig.setMinIdle(5); //最小闲置连接数
jedisPoolConfig.setBlockWhenExhausted(true); //连接耗尽是否等待
jedisPoolConfig.setMaxWaitMillis(2000); //等待时间
jedisPoolConfig.setTestOnBorrow(true); //取连接的时候进行一下测试 ping pong
jedisSentinelPool=new JedisSentinelPool("mymaster",sentinelSet,jedisPoolConfig);
return jedisSentinelPool.getResource();
}else{
return jedisSentinelPool.getResource();
}
}