mysql主从复制、redis基础、持久化和主从复制

1、mysql(mariadb)基础

一、基础命令(centos7操做系统下)

复制代码
1.启动mysql
systemctl start mariadb 

2.linux客户端链接本身 
mysql -uroot -p -h 127.0.0.1
    -u 用户
    -p 密码验证
    -h 链接的主机地址

3.远程连接mysql服务端
mysql -uroot -p -h 192.168.3.115

4.修改mysql密码
# 修改当前用户的密码
set password = PASSWORD('mariadb123');

# 修改其余用户的密码
set password for 'username'@'host' = PASSWORD('newpassword') 

5.建立mysql用户
create user xiaoming@'%' identified by 'xm666';

6.查询mysql库中的用户信息
use mysql;  # mysql是默认存在的库,储存着用户的信息,密码之类的
select host,user,password from  user;

7.受权语句
给小明这个用户,授予建立数据库的权限
mysql中使用grant命令对帐户进行受权,grant命令常见格式以下

grant 权限 on 数据库.表名 to 帐户@主机名          对特定数据库中的特定表受权
grant 权限 on 数据库.* to 帐户@主机名             对特定数据库中的全部表给与受权
grant 权限1,权限2,权限3 on *.* to 帐户@主机名    对全部库中的全部表给与多个受权
grant all privileges on *.* to 帐户@主机名      对全部库和全部表受权全部权限

# 授予小明建立的权限,对于全部的库表生效
grant create  on *.* to xiaoming@"%";

# 建立用户并授予用户只有建立test数据库的权限
grant create  on test.* to xiaoming2@"%"  identified by 'xm2666';

# 授予用户最大的权限,全部的权限
grant all privileges on *.* to username@'%' identified by 'password';

# 刷新权限
flush privileges;  # 刷新使受权当即生效

# 查看用户权限
show grants for 'xiaoming'@'%';

8.移除权限
revoke all privileges on *.* from xiaoming@"%";
复制代码

 

二、数据库的备份与恢复

复制代码
# 备份
mysqldump -u root -p --all-databases > /tmp/db.sql

# 数据导入,方式有几种
第一种
source /tmp/db.sql;

第二种
mysql -uroot -p < /tmp/db.sql 

第三种
使用navicat工具

第四种,若是你数据量特别大的话
使用第三方工具 xtrabackup
复制代码

 

2、mysql主从复制

一、mysql主从复制背景

1.若是你是单点数据库,数据库挂了,你整个项目就挂了mysql

2.若是你是主备数据库,挂了一台主库,我可能还有千千万万个备用的数据库linux

3.原理
MySQL数据库的主从复制是其自带的功能,主从复制并非复制磁盘上的数据库文件,而是经过主库的binlog日志复制到须要同步的从服务器上。
在复制的过程当中,一台服务器充当主服务器(Master),接收来自用户的内容更新,而一个或多个其余的服务器充当从服务器(slave),接收来自Master上binlog文件的日志内容,解析出SQL,从新更新到Slave,使得主从服务器数据达到一致。redis

主从复制的逻辑有如下几种
一主一从,单向主从同步模式,只能在Master端写入数据
sql

 

一主多从数据库

 

 

双主主复制逻辑架构,此架构能够在Master1或Master2进行数据写入,或者两端同时写入(特殊设置)
json

 

4.应用场景
利用复制功能当Master服务器出现问题时,咱们能够人工的切换到从服务器继续提供服务,此时服务器的数据和宕机时的数据几乎彻底一致。
复制功能也可用做数据备份,可是若是人为的执行drop,delete等语句删除,那么从库的备份功能也就失效了vim

 

二、mysql主从复制主库的配置步骤

复制代码
1.在matser(192.168.3.115)主库上的操做,开启主库功能
# 先把主数据库停了
systemctl stop mariadb 

# 编辑数据库的配置文件 /etc/my.cnf ,写入以下信息
[mysqld]
server-id=6  # 这个server-id只要与你从库的server-id不同便可
log-bin=master-logbin  # 生成二进制日志,记录数据的变化

# 重启数据库
systemctl start mariadb

2.在主库建立用户,用于同步数据
create user xiaoming@'%' identified by 'xm666';

授予用户,slave从库的身份
grant replication slave on *.* to 'xiaoming'@'%';


3.锁定数据库的库表,禁止写入
这个命令是全局读锁定,执行了命令以后全部库全部表都被锁定只读。通常都是用在数据库联机备份,这个时候数据库的写操做将被阻塞,读操做顺利进行。 
解锁语句是:UNLOCK TABLES;
flush table with read lock;

记录下主库的状态,记录下,日志文件的名字,和位置
show master status; 

4.导出主库的数据
mysqldump -u root -p --all-databases > /tmp/db.sql


5.确保数据导出后,没有数据插入,完毕再查看主库状态centos

 
  

  show master status;缓存

6.远程传输主库的数据,给从库,进行导入
scp /tmp/db.sql  root@192.168.3.27:/tmp/


7.解锁主库的锁,写入数据,查看从库是否同步
unlock tables;
复制代码

 

三、从库slave(192.168.3.27)机器的配置步骤

复制代码
1.在从库的 /etc/my.cnf中添加参数,添加只读参数
[mysqld]
server-id=3
read-only=true


2.重启数据库
systemctl restart mariadb 

在从库中导入主库的数据
mysql -uroot -p  <  /tmp/db.sql 


3.一条语句,开启主从之间的复制关系
用root用户,进入mysql数据库,输入命令:
change master to master_host='192.168.3.115',  # 主数据库的ip
master_user='xiaoming',  # 普通用户的用户名
master_password='xm666', # 普通用户的密码
master_log_file='master-logbin.000002',  # 主库show master status;日志文件的名字
master_log_pos=492;  # 主库show master status;记录的位置

4.开启slave同步功能
start slave;

5.检查slave机器的主从是否正确
show slave status\G  查看主从同步是否正确

确保以下两条参数,是yes,即主从复制正确
Relay_Master_Log_File: master-logbin.000002
     Slave_IO_Running: Yes
    Slave_SQL_Running: Yes


6.此时mariadb数据库,请退出root用户,使用普通用户配置,由于root身份权限太大,没法达到read-only效果
6.此时mariadb数据库,请退出root用户,使用普通用户配置,由于root身份权限太大,没法达到read-only效果
6.此时mariadb数据库,请退出root用户,使用普通用户配置,由于root身份权限太大,没法达到read-only效果


7.登陆一个普通用户
mysql -u xiaoming -p 8.此时在主库写入数据,查看从库是否正确同步 9.从库没法写入数据,即为正常 10.完成主从同步,读写分离实验
复制代码

 

3、redis基础

redis是一种高级的key:value存储系统,其中value支持五种数据类型
String: 字符串
Hash: 散列
List: 列表
Set: 集合
Sorted Set: 有序集合安全

 

一、strings类型

操做

复制代码
set    设置key
get      获取key
append   追加string
mset     设置多个键值对
mget     获取多个键值对
del      删除key
incr     递增+1
decr     递减-1
复制代码

 

示例

复制代码
127.0.0.1:6379> set name 'dog'  # 设置key
OK
127.0.0.1:6379> get name  # 获取value
"dog"
127.0.0.1:6379> set name 'BigDog'  # 覆盖key
OK
127.0.0.1:6379> get name  # 获取value
"BigDog"
127.0.0.1:6379> append name ' is you'  # 向name这个key追加
(integer) 13
127.0.0.1:6379> get name   # 获取value
"BigDog is you"
127.0.0.1:6379> mset age 18 hight 180 long 18.8  # 一次性设置多个键值对
OK
127.0.0.1:6379> mget age hight long  # 一次性获取多个键的值
1) "18"
2) "180"
3) "18.8"
127.0.0.1:6379> get age  # 获取value
"18"
127.0.0.1:6379> keys *  # 找到全部key
1) "long"
2) "hight"
3) "age"
4) "name"
127.0.0.1:6379> del name  # 删除key
(integer) 1
127.0.0.1:6379> get name  # 获取不存在的value,为nil
(nil)
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> get num
"10"
127.0.0.1:6379> incr num  # 递增+1
(integer) 11
127.0.0.1:6379> get num
"11"
127.0.0.1:6379> decr num  # 递减-1
(integer) 10
127.0.0.1:6379> get num
"10"
复制代码

 

二、list类型

操做

复制代码
lpush           从列表左边插
rpush           从列表右边插
lrange          获取必定长度的元素  lrange key  start stop(至关于获取切片的内容)
ltrim           截取必定长度列表
lpop            删除最左边一个元素
rpop            删除最右边一个元素
lpushx/rpushx   key存在则添加值,不存在不处理
复制代码

 

示例

复制代码
127.0.0.1:6379> lpush list1 'a' 'b' 'c' 'd'  # 新建一个list1,从左边放入四个元素
(integer) 4
127.0.0.1:6379> llen list1  # 查看list1的长度
(integer) 4
127.0.0.1:6379> lrange list1 0 -1  # 查看list全部元素
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> rpush list1 'haha'  # 从右边插入haha
(integer) 5
127.0.0.1:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "haha"
127.0.0.1:6379> lpushx list3 'xixi'  # list3存在则添加元素,不存在则不做处理
(integer) 0
127.0.0.1:6379> ltrim list1 0 3  # 截取队列的值,从索引0取到3,删除其他的元素
OK
127.0.0.1:6379> lrange list1 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
127.0.0.1:6379> lpop list1  # 删除左边的第一个
"d"
127.0.0.1:6379> lrange list1 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> rpop list1  # 删除右边的第一个
"a"
127.0.0.1:6379> lrange list1 0 -1
1) "c"
2) "b"
复制代码

 

三、set集合类型

redis的集合,是一种无序的集合,集合中的元素没有前后顺序,且集合成员是惟一的。

操做

复制代码
sadd/srem   添加/删除 元素
sismember   判断是否为set的一个元素
smembers    返回集合全部的成员
sdiff       返回一个集合和其余集合的差别
sinter      返回几个集合的交集
sunion      返回几个集合的并集
复制代码

 

示例

复制代码
127.0.0.1:6379> sadd school class1 class2  # 添加一个名叫school的集合,有2个元素,不加引号就当作字符串处理
(integer) 2
127.0.0.1:6379> smembers school  # 查看集合school成员
1) "class1"
2) "class2"
127.0.0.1:6379> srem school class1  # 删除school的class1成员
(integer) 1
127.0.0.1:6379> smembers school
1) "class2"
127.0.0.1:6379> sismember school class1  # 是不是school的成员,不是返回0,是返回1
(integer) 0
127.0.0.1:6379> sadd school class3  # 给school添加一个新成员
(integer) 1
127.0.0.1:6379> smembers school
1) "class3"
2) "class2"
127.0.0.1:6379> sadd school2 class3 class4  # 添加一个名叫school2的集合,有2个元素
(integer) 1
127.0.0.1:6379> smembers school2
1) "class3"
2) "class4"
127.0.0.1:6379> sdiff school school2  # 找出集合school中有的,而school2中没有的元素
1) "class2"
127.0.0.1:6379> sdiff school2 school  # 找出集合school2中有的,而school中没有的元素
1) "class4"
127.0.0.1:6379> sinter school school2  # 找出school和school2的交集
1) "class3"
127.0.0.1:6379> sunion school school2  # 找出school和school2的并集(自动去重)
1) "class3"
2) "class4"
3) "class2"
复制代码

 

四、哈希数据结构

hashes即哈希。哈希是从redis-2.0.0版本以后才有的数据结构。

hashes存的是字符串和字符串值之间的映射,好比一个用户要存储其全名、姓氏、年龄等等,就很适合使用哈希。

操做

复制代码
hset    设置散列值
hget    获取散列值
hmset   设置多对散列值
hmget   获取多对散列值
hsetnx  若是散列已经存在,则不设置(防止覆盖key)
hkeys   返回全部keys
hvals   返回全部values
hlen    返回散列包含域(field)的数量
hdel    删除散列指定的域(field)
hexists 判断是否存在
复制代码

 

注意

Hash不支持屡次嵌套,即
"key": {'field': '不能再对应字典'}

"key": {'field': {...}}   --> 错误 
若想嵌套字典,能够json.dumps后存入,取出数据的时候能够json.loads

 

语法

复制代码
hset key field value
结构以下
    key: {
        field1: value1,
        field2: value2,
    }
复制代码

 

示例

复制代码
127.0.0.1:6379> hset school name 'ChinaSchool'  # 建立一个key为school的哈希数据
(integer) 1
127.0.0.1:6379> hget school name  # 获取school的name的值
"ChinaSchool"
127.0.0.1:6379> hmset school age 100 area 2000  # 给school批量设置键值对
OK
127.0.0.1:6379> hmget school name age area  # 批量获取school的键对应的值
1) "ChinaSchool"
2) "100"
3) "2000"
127.0.0.1:6379> hkeys school  # 获取school的全部key
1) "name"
2) "age"
3) "area"
127.0.0.1:6379> hvals school  # 获取school的全部值
1) "ChinaSchool"
2) "100"
3) "2000"
127.0.0.1:6379> hlen school  # 获取school的长度
(integer) 3
127.0.0.1:6379> hexists school name  # 判断school中是否有name这个键,有就返回1,没有就返回0
(integer) 1
127.0.0.1:6379> hdel shcool area  # 删除school中的area键值对
(integer) 1
复制代码

 

五、额外的危险操做(慎用)

复制代码
获取redis数据库中全部的键(这个不危险)
keys *

删除全部Key,可使用Redis的flushdb和flushall命令(危险慎用)
# 删除当前数据库中的全部Key
flushdb

# 删除全部数据库中的key
flushall
复制代码

 

4、redis发布者订阅者

复制代码
发布者:
PUBLISH channel msg
    将信息 message 发送到指定的频道 channel
    
频道  channel  
    自定义频道的名字

订阅者:
SUBSCRIBE channel [channel ...]
    订阅频道,能够同时订阅多个频道

UNSUBSCRIBE [channel ...]
    取消订阅指定的频道, 若是不指定频道,则会取消订阅全部频道

PSUBSCRIBE pattern [pattern ...]
    订阅一个或多个符合给定模式的频道(正则匹配),每一个模式以 * 做为匹配符,
    好比 it* 匹配全部以 it 开头的频道( it.news 、 it.blog 、 it.tweets 等等), 
    news.* 匹配全部以 news. 开头的频道( news.it 、 news.global.today 等等),诸如此类

PUNSUBSCRIBE [pattern [pattern ...]]
    退订指定的规则, 若是没有参数则会退订全部规则

PUBSUB subcommand [argument [argument ...]]
    查看订阅与发布系统状态

注意:使用发布订阅模式实现的消息队列,当有客户端订阅channel后只能收到后续发布到该频道的消息,以前发送的不会缓存,必须Provider和Consumer同时在线
复制代码

 

5、redis数据持久化

redis的缺点:
  redis数据放在内存中
  重启服务器丢失数据
  重启redis服务丢失数据
  断电丢失数据

为了防止redis数据丢失,进行持久化,将数据,写入到一个文件中

 

一、redis持久化之RDB

redis提供了RDB持久化的功能,这个功能能够将redis在内存中的的状态保存到硬盘中,它能够手动执行。
也能够再redis.conf中配置,按期执行。
RDB持久化产生的RDB文件是一个通过压缩的二进制文件,这个文件被保存在硬盘中,redis能够经过这个文件还原数据库当时的状态。

RDB的原理是
  基于内存的数据快照
  按期执行数据快照
  手动触发数据快照
  Redis会将数据集的快照dump到dump.rdb文件中
  能够经过配置文件来修改Redis服务器dump快照的频率

RDB优势:
  速度快,适合作备份,主从复制就是基于RDB持久化功能实现
  rdb经过在redis中使用save命令触发 rdb

 

1. 配置rdb数据持久化

复制代码
1.在配置文件中,添加rdb持久化参数 
vim redis-6379.conf 
写入以下配置
port 6379           
daemonize yes           
pidfile /data/6379/redis.pid
loglevel notice        
logfile "/data/6379/redis.log"
protected-mode yes
dir /data/6379  # 定义持久化文件存储位置(rdb和aof)

dbfilename  dbmp.rdb  # rdb持久化文件
save 900 1  # rdb机制 每900秒 若是至少有1个key发生变化,则dump内存快照(至关于手动save触发rdb持久化文件)
save 300 10 # 在300秒(5分钟)以后,若是至少有10个key发生变化,则dump内存快照。
save 60 10000  # 在60秒(1分钟)以后,若是至少有10000个key发生变化,则dump内存快照。

2.触发rdb持久化,能够手动save命令,生成 dump.rdb持久化文件

3.重启redis,数据再也不丢失

4. 测试
进入redis客户端
redis-cli

127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> save
OK

5.进入/data/6379查看是否生成了 dbmp.rdb 持久化文件
注意:rdb数据文件是二进制文件,人为的看不懂

6.kill掉redis进程,再重启,进入redis   keys * 查看数据是否还在
复制代码

 

二、redis持久化之aof

AOF(append-only log file)
记录服务器执行的全部变动操做命令(例如set del等),并在服务器启动时,经过从新执行这些命令来还原数据集


AOF 文件中的命令所有以redis协议的格式保存,新命令追加到文件末尾。
优势:最大程序保证数据不丢
缺点:日志记录很是大

 

1. 配置方式

 

复制代码
1,在配置文件中,添加aof参数
参数解释:
appendonly yes  # 开启aof功能

# appendfsync选择一个策略写入配置文件便可,这里使用每分钟
appendfsync everysec # 每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync always   # 每次有数据修改发生时都会写入AOF文件。
appendfsync no       # 从不一样步。高效可是数据不会被持久化

配置以下:
port 6379
daemonize yes
pidfile /data/6379/redis.pid
loglevel notice
logfile "/data/6379/redis.log"
protected-mode yes
dir /data/6379
dbfilename  dbmp.rdb
save 900 1
save 300 10
save 60 10000

appendonly yes
appendfsync everysec


2,重启redis数据库,加载aof功能
会在/data/6379目录下生成 appendonly.aof 文件


3,appendonly.aof 文件是人能够看懂的记录了sql操做的文件

4,测试
进入redis客户端
redis-cli

127.0.0.1:6379> set long 18
OK

5,进入/data/6379查看appendonly.aof 文件的内容

6,kill掉redis进程,再重启,进入redis   keys * 查看数据是否还在
复制代码

 

 

三、在不重启redis的状况下,切换rdb数据到aof数据中

 

复制代码
1.配置redis支持rdb持久化

2.启动redis客户端,经过命令,临时切换到aof模式
127.0.0.1:6379> CONFIG set appendonly yes  # 开启AOF功能
OK
127.0.0.1:6379> CONFIG SET save ""  # 关闭RDB功能
OK

3.检查此时的数据持久化方式是rdb,仍是aof,检查appendonly.aof文件,数据变更
tail -f appendonly.aof

4.此时aof还未永久生效,写入参数到配置文件
编辑redis-6379.conf 添加以下参数
appendonly yes
appendfsync everysec
复制代码

 

四、redis持久化方式有什么区别

rdb:基于快照的持久化,速度更快,通常用做备份,主从复制也是依赖于rdb持久化功能

aof:以追加的方式记录redis操做日志的文件。能够最大程度的保证redis数据安全,相似于mysql的binlog

 

6、redis主从同步实现

原理:
1. 从服务器向主服务器发送 SYNC 命令。
2. 接到 SYNC 命令的主服务器会调用BGSAVE 命令,建立一个 RDB 文件,并使用缓冲区记录接下来执行的全部写命令。
3. 当主服务器执行完 BGSAVE 命令时,它会向从服务器发送 RDB 文件,而从服务器则会接收并载入这个文件。
4. 主服务器将缓冲区储存的全部写命令发送给从服务器执行。

小知识:
1. 在开启主从复制的时候,使用的是RDB方式的,同步主从数据的
2. 同步开始以后,经过主库命令传播的方式,主动的复制方式实现
3. 2.8之后实现PSYNC的机制,实现断线重连

 

一、使用配置文件进行redis主从同步配置

准备三个redis数据库,redis支持多实例
三个配置文件,仅仅是端口的不一样

在三个配置文件中,添加主从同步的参数,
三个配置文件参数是同样的,惟一不一样的是,
在从库中须要指定它的主库是谁便可,
例如6380的配置
slaveof 127.0.0.1 6379 表明这个redis库是6379的从库

 

复制代码
1. 三个配置文件参信息以下
# redis-6379.conf(主redis)
port 6379           
daemonize yes           
pidfile /data/6379/redis.pid
loglevel notice        
logfile "/data/6379/redis.log"
dir /data/6379            
protected-mode yes 
dbfilename  dbmp.rdb
save 900 1
save 300 10 
save 60 10000


# redis-6380.conf(从redis)
port 6380           
daemonize yes           
pidfile /data/6380/redis.pid
loglevel notice        
logfile "/data/6380/redis.log"
dir /data/6380            
protected-mode yes 
dbfilename  dbmp.rdb
save 900 1
save 300 10 
save 60 10000
slaveof  127.0.0.1 6379


# redis-6381.conf(从redis)
port 6381           
daemonize yes           
pidfile /data/6381/redis.pid
loglevel notice        
logfile "/data/6381/redis.log"
dir /data/6381            
protected-mode yes 
dbfilename  dbmp.rdb
save 900 1
save 300 10 
save 60 10000
slaveof  127.0.0.1 6379


2.启动三个redis实例
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf

3.查看主从同步身份
1,redis-cli -p 6379  info replication 
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6380,state=online,offset=28,lag=1
slave1:ip=127.0.0.1,port=6381,state=online,offset=28,lag=1


2,redis-cli -p 6380  info replication 
# Replication
role:slave
master_host:127.0.0.1
master_port:6379


3,redis-cli -p 6381  info replication 
# Replication
role:slave
master_host:127.0.0.1
master_port:6379

4.测试
# 在6379主库
redis-cli -p 6379

127.0.0.1:6379> set uzi good
OK

# 在6380从库
redis-cli -p 6380

127.0.0.1:6380> get uzi
"good"

# 在6381从库
redis-cli -p 6381

127.0.0.1:6381> get uzi
"good"
复制代码

 

二、使用命令行进行redis主从同步配置

复制代码
1. 6380/6381命令行
redis-cli -p 6380
127.0.0.1:6380> SLAVEOF 127.0.0.1 6379  #指明主库的地址

redis-cli -p 6381
127.0.0.1:6381> SLAVEOF 127.0.0.1 6379  #指明主库的地址


2. 检查主从状态
主库:
127.0.0.1:6379> info replication

从库:
127.0.0.1:6380> info replication
127.0.0.1:6381> info replication
复制代码

 

三、若是我主库挂了怎么办

复制代码
解决方案:手动切换主从身份,选举一个新的主库
1.干掉6379主库
redis-cli -p 6379 shutdown

2.在6380上关闭本身的slave身份
127.0.0.1:6380> slaveof no one 

3.在6381上给与新的主人身份
127.0.0.1:6381> salveof  127.0.0.1  6380 

4.修改完毕,还得修改配置文件,永久生效
    
复制代码
相关文章
相关标签/搜索