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.修改完畢,還得修改配置文件,永久生效
    
複製代碼
相關文章
相關標籤/搜索