mysql-3

第十一天


備份恢復(fù)

mysql數(shù)據(jù)損壞類型

  • 物理損壞
    • 磁盤損壞:硬件,磁道壞丐箩,dd损趋,格式化
    • 文件損壞:數(shù)據(jù)文件損壞崖面,redo損壞
  • 邏輯損壞
    • drop
    • delete
    • truncate
    • update

DBA運(yùn)維人員在備份、恢復(fù)的職責(zé)

  • 設(shè)計(jì)備份另萤、容災(zāi)策略
    • 備份策略
      • 備份工具選擇
      • 備份周期設(shè)計(jì)
      • 備份監(jiān)控方法
    • 容災(zāi)策略
      • 備份:什么備份
      • 架構(gòu):高可用湃密,延遲從庫诅挑,災(zāi)備庫
  • 定期的備份、容災(zāi)檢查
  • 定期的故障恢復(fù)演練
  • 數(shù)據(jù)損壞時(shí)的快速準(zhǔn)確恢復(fù)
  • 數(shù)據(jù)遷移工作

mysql常用備份工具

  • 邏輯備份方式
    • mysqldump(MDP)
      • 數(shù)據(jù)量較少泛源,使用它拔妥。100G以內(nèi)
      • 可讀性比較強(qiáng),壓縮比高达箍,節(jié)省空間没龙。不需要下載安裝
      • 備份時(shí)間相對較長《忻担恢復(fù)時(shí)間長
    • mydumper
    • load data in file
    • 主從方式(replication)
  • 物理備份方式
    • mysql enterprise backup(企業(yè)版)
    • percona Xtrabackup(PBK,XBK)

mysqldump(MDP)應(yīng)用

  • 介紹
    • 邏輯備份工具硬纤。備份的是sql語句
    • innodb可以采取快照備份的方式。開啟一個(gè)獨(dú)立的事務(wù)赃磨,獲取當(dāng)前最新的一致性快照筝家。將快照數(shù)據(jù),放在臨時(shí)表中邻辉,轉(zhuǎn)換成sql(create table溪王,create table ,insert)值骇,保存到sql文件中
    • 非innodb表莹菱,需要鎖表備份。觸發(fā)FTWRL雷客,全局鎖表芒珠。轉(zhuǎn)換成sql(create table,create table 搅裙,insert)皱卓,保存到sql文件中
  • ==核心參數(shù)==
    • 連接參數(shù)
      • -u
      • -p
      • -h
      • -P
      • -S
    • 備份參數(shù)
      • -A 全備
      • -B 備份1個(gè)或多個(gè)庫
    • 備份==高級參數(shù)==
      • ==--master-data=2==
        • 備份時(shí)自動(dòng)記錄binlog信息
        • 自動(dòng)鎖表和解鎖
        • 配合single transaction可以減少鎖表時(shí)間
      • ==--single-transaction==
        • 對于innodb引擎?zhèn)浞輹r(shí),開啟一個(gè)獨(dú)立事務(wù)部逮,獲取一致性快照進(jìn)行備份
      • -R -E --triggers
      • --max_allowed_packet=64M
        • 最大可以設(shè)置:128M
        • 這個(gè)是針對客戶端的娜汁,不是對server端的
          • ==select @@max_allowed_packet;==
          • 服務(wù)器端默認(rèn):4M
mkdir -p /data/backup
chown -R  mysql.mysql /data/*

mysqldump -uroot -pxxx -S /tmp/mysql.sock -A  >  /data/backup/full.sql
mysqldump -uroot -pxxx -B world test  >  /data/backup/db.sql

### 備份庫中單個(gè)表,多個(gè)表
mysqldump -uroot -pxxx  database_name table_name1  table_name2 >  /data/backup/table.sql

### 下面參數(shù)很重要,生產(chǎn)必備命令
mysqldump -uroot -pxxx -S /tmp/mysql.sock -A --master-data=2 --single-transaction -R -E --triggers --max_allowed_packet=64M >  /data/backup/full.sql


基于mysqldump+binlog故障恢復(fù)案列

案列場景:

基礎(chǔ)環(huán)境:centos7.6+mysql 5.7.28兄朋,lnmt網(wǎng)站業(yè)務(wù)掐禁,數(shù)據(jù)量100G(備份大概1個(gè)小時(shí)以內(nèi),不是固態(tài)盤)颅和,每天5-10M數(shù)據(jù)增長

備份策略:mysqldump每天全備傅事,binlog定時(shí)備份

故障模擬:周三上午10點(diǎn)數(shù)據(jù)故障,例如:核心業(yè)務(wù)庫被誤刪除

恢復(fù)思路:

  1. 掛維護(hù)頁
  2. 找測試庫
  3. 恢復(fù)周二全備
  4. 截取周二全備到周三上午10點(diǎn)誤刪除之前的binlog峡扩,并恢復(fù)
  5. 測試業(yè)務(wù)功能正常
  6. 恢復(fù)業(yè)務(wù)
    1. 故障庫導(dǎo)回原生產(chǎn)
    2. 直接用測試庫承擔(dān)生產(chǎn)蹭越,先跑著
### 故障模擬演練
#### 1.準(zhǔn)備數(shù)據(jù)
create database backup;
use backup;
create table t1 (id int);
insert into t1 values(1),(2),(3);
commit;
rm -rf /backup/*

#### 2.周二23:00全備
mysqldump -uroot -p123 -A  -R  -E --triggers --set-gtid-purged=OFF --master-data=2  --single-transaction --max_allowed_packet=64M|gzip > /backup/full_$(date +%F).sql.gz

#### 3.模擬周二 23:00到周三 10點(diǎn)之間數(shù)據(jù)變化
use backup;
insert into t1 values(11),(22),(33);
commit;
create table t2 (id int);
insert into t2 values(11),(22),(33);

#### 4.模擬故障,刪除表(只是模擬,不代表生產(chǎn)操作)
drop database backup;

### 恢復(fù)過程
#### 1.準(zhǔn)備臨時(shí)數(shù)據(jù)庫
systemctl start mysqld3307

#### 2.準(zhǔn)備備份
#####(1)準(zhǔn)備全備:
cd /backup
gunzip full_2018-10-17.sql.gz 

######(2)截取二進(jìn)制日志
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000036',MASTER_LOG_POS=793;
mysqlbinlog --skip-gtids --include-gtids='3ca79ab5-3e4d-11e9-a709-000c293b577e:6-7' /data/binlog/mysql-bin.000036 >/backup/bin.sql

#### 3.恢復(fù)備份到臨時(shí)庫
mysql -S /data/3307/mysql.sock
set sql_log_bin=0;
source /backup/full_2018-10-17.sql;
source /backup/bin.sql;

#### 4.將故障表導(dǎo)出并恢復(fù)到生產(chǎn)
mysqldump   -S /data/3307/mysql.sock backup t1  -R  -E --triggers --set-gtid-purged=OFF --master-data=2  --single-transaction --max_allowed_packet=64M >/backup/t1.sql
mysql -uroot -p123 
set sql_log_bin=0;
use backup; 
source /backup/t1.sql;
set sql_log_bin=1;

實(shí)現(xiàn)所有表的單獨(dú)備份

### 提示:
#### information_schema.tables
mysqldump -uroot -p123 world city -A  -R  -E --triggers --set-gtid-purged=OFF --master-data=2  --single-transaction --max_allowed_packet=64M >/backup/world_city.sql

select concat("mysqldump -uroot -p123 ",table_schema," ",table_name," --master-data=2 --single-transaction --set-gtid-purged=0  -R -E --triggers  --max_allowed_packet=64M>/backup/",table_schema,"_",table_name,".sql") from information_schema.tables where table_schema not in ('sys','information_schema','performance_schema');

壓縮備份并添加時(shí)間戳

mysqldump -uroot -p123 -A  -R -E --triggers --master-data=2  --single-transaction|gzip > /backup/full_$(date +%F).sql.gz
mysqldump -uroot -p123 -A  -R -E --triggers --master-data=2  --single-transaction|gzip > /backup/full_$(date +%F-%T).sql.gz

### mysqldump備份的恢復(fù)方式(在生產(chǎn)中恢復(fù)要謹(jǐn)慎教届,恢復(fù)會(huì)刪除重復(fù)的表)
set sql_log_bin=0;
source /backup/full_2018-06-28.sql

### 注意:
1响鹃、mysqldump在備份和恢復(fù)時(shí)都需要mysql實(shí)例啟動(dòng)為前提驾霜。
2、一般數(shù)據(jù)量級100G以內(nèi)买置,大約15-45分鐘可以恢復(fù)粪糙,數(shù)據(jù)量級很大很大的時(shí)候(PB、EB)
3忿项、mysqldump是覆蓋形式恢復(fù)的方法蓉冈。

### 一般我們認(rèn)為,在同數(shù)據(jù)量級倦卖,物理備份要比邏輯備份速度快.
邏輯備份的優(yōu)勢:
1洒擦、可讀性強(qiáng)
2、壓縮比很高

模擬故障案例并恢復(fù)

### 需求: 利用全備+binlog回復(fù)數(shù)據(jù)庫誤刪除之前怕膛。

#### 故障模擬及恢復(fù):

##### 1. 模擬周一23:00的全備
mysqldump -uroot -p -A -R -E --triggers --master-data=2  --single-transaction --set-gtid-purged=OFF --max_allowed_packet=64M>/data/backup/full.sql

##### 2. 模擬白天的數(shù)據(jù)變化
Master [(none)]>create database day1 charset utf8;
Master [(none)]>use day1
Master [day1]>create table t1(id int);
Master [day1]>insert into t1 values(1),(2),(3);
Master [day1]>commit;
Master [world]>update city set countrycode='CHN';
Master [world]>commit;

##### 模擬磁盤損壞:
[root@db01 data]# rm -rf /data/mysql/data/*

##### 3. 恢復(fù)故障
[root@db01 data]# pkill mysqld
[root@db01 data]# \rm -rf /data/mysql/data/*

##### 4. 恢復(fù)思路
######1.檢查備份可用性
######2.從備份中獲取二進(jìn)制日志位置
######3.根據(jù)日志位置截取需要的二進(jìn)制日志
######4.初始化數(shù)據(jù)庫,并啟動(dòng)
######5.恢復(fù)全備
######6.恢復(fù)二進(jìn)制日志

==從mysqldump 全備中獲取 庫和表的備份==

### 1熟嫩、獲得表結(jié)構(gòu)
sed -e'/./{H;$!d;}' -e 'x;/CREATE TABLE `city`/!d;q'  full.sql>createtable.sql

### 2、獲得INSERT INTO 語句褐捻,用于數(shù)據(jù)的恢復(fù)
grep -i 'INSERT INTO `city`'  full.sqll >data.sql &

### 3.獲取單庫的備份
sed -n '/^-- Current Database: `world`/,/^-- Current Database: `/p' all.sql >world.sql

percona xtrabackup(XBK掸茅、Xbackup)

安裝

### 安裝依賴包
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum -y install perl perl-devel libaio libaio-devel perl-Time-HiRes perl-DBD-MySQL libev

### 下載軟件并安裝
wget https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.12/binary/redhat/7/x86_64/percona-xtrabackup-24-2.4.12-1.el7.x86_64.rpm

#### https://www.percona.com/downloads/XtraBackup/Percona-XtraBackup-2.4.4/binary/redhat/6/x86_64/percona-xtrabackup-24-2.4.4-1.el6.x86_64.rpm

yum -y install percona-xtrabackup-24-2.4.4-1.el7.x86_64.rpm

介紹

  • 物理備份工具,拷貝數(shù)據(jù)文件柠逞。原生態(tài)支持全備和增量


  • 對于非Innodb表(比如 myisam)是昧狮,鎖表cp數(shù)據(jù)文件,屬于一種溫備份板壮。

    1. binlog只讀逗鸣,F(xiàn)TWRL,觸發(fā)全局鎖
    2. 拷貝非innodb表的數(shù)據(jù)
    3. 解鎖
  • 對于Innodb的表(支持事務(wù)的)绰精,不鎖表撒璧,拷貝數(shù)據(jù)頁,最終以數(shù)據(jù)文件的方式保存下來笨使,把一部分redo和undo一并備走卿樱,屬于熱備方式。
    1. checkpoint硫椰,將已提交的數(shù)據(jù)頁刷新到磁盤繁调。記錄一個(gè)LSN
    2. 拷貝innodb表相關(guān)的文件(ibdata1,frm,ibd......)
    3. 備份期間產(chǎn)生新的數(shù)據(jù)變化的redo也會(huì)備份走
 4.再次統(tǒng)計(jì)LSN,寫入到專用文件

 5.記錄二進(jìn)制日志位置記錄下來

  • 所有備份文件統(tǒng)一存放在一個(gè)目錄下

==xbk備份邏輯==

  1. checkpoint 靶草,記錄LSN號(hào)
  2. information_schema.xxx
  3. 拷貝innodb文件蹄胰,過程中發(fā)生的新變化redo也會(huì)被保存,保存至備份路徑
  4. binlog只讀奕翔,F(xiàn)TWRL(global read lock)
  5. 拷貝non_innodb烤送,拷貝完成后解鎖
  6. 生成備份相關(guān)的信息文件,binlog糠悯,LSN
  7. 刷新last LSN
  8. 完成備份

XBK應(yīng)用

  • 前提

    • 數(shù)據(jù)庫啟動(dòng)

    • 能連上數(shù)據(jù)庫

    • vi /etc/my.cnf
      [client]
      socket=/tmp/mysql.sock
      
      [mysqld]
      datadir=/xxx
      ### xtrabackup默認(rèn)會(huì)讀取這行參數(shù)
      
    • 服務(wù)器端的工具帮坚,這個(gè)工具只能放在服務(wù)器端上

  • 全備

    • ==innobackupex --user=root --password=123 /data/xbk==
    • ==innobackupex --user=root --password=123 --no-timestamp /data/xbk/full_`date +%F`==
  • 備份結(jié)果的部分文件

    • -rw-r----- 1 root root       24 Jun 29 09:59 xtrabackup_binlog_info
      -rw-r----- 1 root root      119 Jun 29 09:59 xtrabackup_checkpoints
      -rw-r----- 1 root root      489 Jun 29 09:59 xtrabackup_info
      -rw-r----- 1 root root     2560 Jun 29 09:59 xtrabackup_logfile
      
      ### xtrabackup_binlog_info :(備份時(shí)刻的binlog位置)
      [root@db01 full]# cat xtrabackup_binlog_info 
      mysql-bin.000003    536749
      79de40d3-5ff3-11e9-804a-000c2928f5dd:1-7
      記錄的是備份時(shí)刻,binlog的文件名字和當(dāng)時(shí)的結(jié)束的position互艾,可以用來作為截取binlog時(shí)的起點(diǎn)试和。
      
      ### xtrabackup_checkpoints :
      backup_type = full-backuped
      from_lsn = 0            上次所到達(dá)的LSN號(hào)(對于全備就是從0開始,對于增量有別的顯示方法)
      to_lsn = 160683027      備份開始時(shí)間(ckpt)點(diǎn)數(shù)據(jù)頁的LSN    
      last_lsn = 160683036    備份結(jié)束后,redo日志最終的LSN
      compact = 0
      recover_binlog_info = 0
      
      (1)備份時(shí)刻纫普,立即將已經(jīng)commit過的阅悍,內(nèi)存中的數(shù)據(jù)頁刷新到磁盤(CKPT).開始備份數(shù)據(jù),數(shù)據(jù)文件的LSN會(huì)停留在to_lsn位置昨稼。
      (2)備份時(shí)刻有可能會(huì)有其他的數(shù)據(jù)寫入,已備走的數(shù)據(jù)文件就不會(huì)再發(fā)生變化了。
      (3)在備份過程中氧秘,備份軟件會(huì)一直監(jiān)控著redo的undo点晴,如果一旦有變化會(huì)將日志也一并備走,并記錄LSN到last_lsn匾荆。
      從to_lsn  ----》last_lsn 就是拌蜘,備份過程中產(chǎn)生的數(shù)據(jù)變化.
      

==全備的恢復(fù)(XBK)==

破壞

pkill mysqld
rm  -rf /data/3306/*

==準(zhǔn)備備份(Prepared)==

### 將redo進(jìn)行重做,已提交的寫到數(shù)據(jù)文件牙丽,未提交的使用undo回滾掉简卧。模擬了CSR的過程
innobackupex --apply-log  /backup/xbk/full......

恢復(fù)備份

### 前提:
#### 1、被恢復(fù)的目錄是空
#### 2烤芦、被恢復(fù)的數(shù)據(jù)庫的實(shí)例是關(guān)閉
cp -a  /backup/xbk/full....../*    /data/3306/  
chown  -R   mysql.mysql  /data/*
/etc/init.d/mysqld  start

XBK的增量備份恢復(fù)

備份

  • 增量必須依賴于全備
  • 每次增量都是參照上次備份的LSN號(hào)碼(xtrabackup checkpoint)举娩,在此基礎(chǔ)上變化的數(shù)據(jù)頁,備份走构罗,
  • 并且會(huì)將備份過程中產(chǎn)生新的變化的redo一并備份走

恢復(fù)

  • 將所有需要inc備份铜涉,按順序合并到全備中
  • 并且需要將每個(gè)備份進(jìn)行prepare

==增量備份實(shí)戰(zhàn)==

### 1.刪掉原來備份
略.

### 2.全備(周日)
innobackupex --user=root --password --no-timestamp /backup/full >&/tmp/xbk_full.log

### 3.模擬周一數(shù)據(jù)變化
db01 [(none)]>create database cs charset utf8;
db01 [(none)]>use cs
db01 [cs]>create table t1 (id int);
db01 [cs]>insert into t1 values(1),(2),(3);
db01 [cs]>commit;

### 4.第一次增量備份(周一)
innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/full  /backup/inc1 &>/tmp/inc1.log

### 5.模擬周二數(shù)據(jù)
db01 [cs]>create table t2 (id int);
db01 [cs]>insert into t2 values(1),(2),(3);
db01 [cs]>commit;

### 6.周二增量
 innobackupex --user=root --password=123 --no-timestamp --incremental --incremental-basedir=/backup/inc1  /backup/inc2  &>/tmp/inc2.log
 
### 7.模擬周三數(shù)據(jù)變化
db01 [cs]>create table t3 (id int);
db01 [cs]>insert into t3 values(1),(2),(3);
db01 [cs]>commit;
db01 [cs]>drop database cs;

### 8.恢復(fù)到周三誤drop之前的數(shù)據(jù)狀態(tài)
####恢復(fù)思路:
####1. 掛出維護(hù)頁,停止當(dāng)天的自動(dòng)備份腳本
####2. 檢查備份:周日full+周一inc1+周二inc2绰播,周三的完整二進(jìn)制日志
####3. 進(jìn)行備份整理(細(xì)節(jié))骄噪,截取關(guān)鍵的二進(jìn)制日志(從備份---誤刪除之前)
####4. 測試庫進(jìn)行備份恢復(fù)及日志恢復(fù)
####5. 應(yīng)用進(jìn)行測試無誤,開啟業(yè)務(wù)
####6. 此次工作的總結(jié)

==恢復(fù)過程==

### 1. 檢查備份
1afe8136-601d-11e9-9022-000c2928f5dd:7-9

### 2. 備份整理(apply-log)+合并備份(full+inc1+inc2)
#### (1) 全備的整理
innobackupex --apply-log --redo-only /data/backup/full

#### (2) 合并inc1到full中
innobackupex --apply-log --redo-only --incremental-dir=/data/backup/inc1 /data/backup/full

#### (3) 合并inc2到full中
innobackupex --apply-log  --incremental-dir=/data/backup/inc2 /data/backup/full

#### 最后一次整理全備
innobackupex --apply-log  /data/backup/full

### 3. 截取周二 23:00 到drop 之前的 binlog 
 mysqlbinlog --skip-gtids --include-gtids='1afe8136-601d-11e9-9022-000c2928f5dd:7-9' /data/binlog/mysql-bin.000009 >/data/backup/binlog.sql
 
### 4.進(jìn)行恢復(fù)
mkdir /data/mysql/data2 -p
cp -a * /data/mysql/data2
chown -R mysql.  /data/*
systemctl stop mysqld

vim /etc/my.cnf
datadir=/data/mysql/data2
systemctl start mysqld

set sql_log_bin=0;
source /data/backup/binlog.sql

==小細(xì)節(jié)==

  1. 每次xbk恢復(fù)后蠢箩,可以reset master清除無用的gtid信息
  2. 每次故障恢復(fù)完后链蕊,立即做全備
  3. 如果出現(xiàn)增量合并不了怎么辦?
    • full+binlog方式恢復(fù)

第十二天


主從復(fù)制(replication)

介紹

  • 兩臺(tái)或以上數(shù)據(jù)庫實(shí)例谬泌,通過二進(jìn)制日志滔韵,實(shí)現(xiàn)數(shù)據(jù)的“同步”關(guān)系。(不是真的同步掌实,是異步的關(guān)系

前提

  1. 兩臺(tái)以上mysql實(shí)例 ,server_id,server_uuid不同
  2. 主庫開啟二進(jìn)制日志
  3. 專用的復(fù)制用戶
  4. 保證主從開啟之前的某個(gè)時(shí)間點(diǎn),從庫數(shù)據(jù)是和主庫一致(補(bǔ)課)
  5. 告知從庫,復(fù)制user,passwd,IP port,以及復(fù)制起點(diǎn)(change master to)
  6. 線程(三個(gè)):Dump thread 陪蜻, IO thread , SQL thread 開啟(start slave)

==搭建(單機(jī)多實(shí)例主從復(fù)制)==

### 1.清理主庫數(shù)據(jù)
rm -rf /data/3307/data/*

### 2.重新初始化3307
mysqld --initialize-insecure --user=mysql --basedir=/app/mysql --datadir=/data/3307/data

### 3.修改my.cnf ,開啟二進(jìn)制日志功能
vim /data/3307/my.cnf 
log_bin=/data/3307/data/mysql-bin

### 4.啟動(dòng)所有節(jié)點(diǎn)
systemctl start mysqld3307
systemctl start mysqld3308
systemctl start mysqld3309
ps -ef |grep mysqld
mysql      3684      1  4 09:59 ?        00:00:00 /app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
mysql      3719      1  7 09:59 ?        00:00:00 /app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
mysql      3754      1  8 09:59 ?        00:00:00 /app/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
mysql -S /data/3307/mysql.sock -e "select @@server_id"
mysql -S /data/3308/mysql.sock -e "select @@server_id"
mysql -S /data/3309/mysql.sock -e "select @@server_id"

### 5.主庫中創(chuàng)建復(fù)制用戶
mysql -S /data/3307/mysql.sock 
>grant replication slave on *.* to repl@'10.0.0.%' identified by '123';
>select user,host from mysql.user;

### 6.備份主庫并恢復(fù)到從庫
mysqldump -S /data/3307/mysql.sock -A --master-data=2 --single-transaction  -R -E --triggers >/backup/full.sql
#### -- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=653;
mysql -S /data/3308/mysql.sock
>source /backup/full.sql;

### 7.告知從庫關(guān)鍵復(fù)制信息(從庫)
#### ip port user  password  binlog position 
mysql -S /data/3308/mysql.sock
>help change master to;
>CHANGE MASTER TO
  MASTER_HOST='10.0.0.51',
  MASTER_USER='repl',
  MASTER_PASSWORD='123',
  MASTER_PORT=3307,
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=653,
  MASTER_CONNECT_RETRY=10;
  
### 8. 開啟主從專用線程(從庫)
>start slave ;

### 9.檢查復(fù)制狀態(tài)(從庫)
>show slave status \G;
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes  
#### 如果搭建不成功贱鼻,可以執(zhí)行以下命令(從庫)宴卖,從6-8步驟重新來過
>stop slave;
>reset slave all;

主從復(fù)制原理

主從中涉及的資源

  • 文件
    • 主庫:binlog文件
    • 從庫
      • relay-log文件(默認(rèn)文件名==`hostname`-relay-bin.000001==):存儲(chǔ)接受的binlog
        • ==手動(dòng)定義==
          • ==show variables like ''%relay%'';==
          • ==relay_log_basename=/data/3308/data/db01-relay-bin==
      • master.info:連接主庫的信息滋将,已經(jīng)接受binlog位置點(diǎn)信息
        • ==show variables like ''%master%'';==
        • ==master_info_repository=FILE/TABLE==
      • relay.info(relay-log.info):記錄從庫回放到的relay-log的位置點(diǎn)
        • ==relay_log_info_repository=FILE/TABLE==
  • 線程
    • 主庫:binlog_dump_Thread
      • 用來接受從庫請求,并且投遞binlog給從庫
      • ==show processlist;==
    • 從庫
      • io線程:請求binlog日志症昏,接受binlog日志
      • sql線程:回放relay日志

==原理==

img

文字說明:

 1. **S:**change master to 時(shí)随闽,ip, port, user, password ,binlog position寫入到**master.info**進(jìn)行記錄
  1. start slave 時(shí),從庫會(huì)啟動(dòng)IO線程和SQL線程
  2. IO_T肝谭,讀取master.info信息掘宪,獲取主庫信息連接主庫
  3. M:會(huì)生成一個(gè)準(zhǔn)備binlog DUMP線程,來響應(yīng)從庫
  4. IO_T根據(jù)master.info記錄的binlog文件名和position號(hào)攘烛,請求主庫DUMP最新日志
  5. M:DUMP線程檢查主庫的binlog日志魏滚,如果有新的,TP(傳送)給從從庫的IO_T
  6. IO_T將收到的日志存儲(chǔ)到了TCP/IP 緩存坟漱,立即返回ACK給主庫 鼠次,主庫工作完成
  7. IO_T將緩存中的數(shù)據(jù),存儲(chǔ)到relay-log日志文件,更新master.info文件里的binlog 文件名和postion靖秩,IO_T工作完成
  8. SQL_T讀取relay-log.info文件须眷,獲取到上次執(zhí)行到的relay-log的位置,作為起點(diǎn)沟突,回放relay-log
  9. SQL_T回放完成之后花颗,會(huì)更新relay-log.info文件。
  10. relay-log會(huì)有自動(dòng)清理的功能惠拭。
  • ==relay_log_purge=on==
  • 定期刪除應(yīng)用過的relay-log

細(xì)節(jié):主庫一旦有新的日志生成扩劝,會(huì)發(fā)送“信號(hào)”給binlog dump ,IO線程再請求

==上面圖片上的7和8的順序?qū)φ{(diào)==


主從復(fù)制監(jiān)控

主庫

  • show processlist;
  • show slave host;

從庫

  • ==show slave status\G==

主從復(fù)制故障分析

主從中的線程管理

  • start slave;
  • stop slave;
  • start slave io_thread;
  • start slave sql_thread;
  • stop slave io_thread;
  • stop slave sql_thread;

解除從庫身份

  • reset slave all;

  • show slave status \G

IO線程故障

故障原因

  • 連接主庫
    • 網(wǎng)絡(luò)职辅、端口棒呛、防火墻
    • 用戶、密碼域携、授權(quán)
    • 主庫連接數(shù)上限
    • 版本不統(tǒng)一
  • 請求日志簇秒,接受日志
    • 主庫二進(jìn)制日志不完整:損壞,不連續(xù)
    • 從庫請求的起點(diǎn)問題
    • 主從的server_id(server_uuid)相同
    • relaylog問題

sql線程故障

回放relay-log中的日志秀鞭∏鞴郏可以理解為執(zhí)行relay-log sql

原因整理

  • 創(chuàng)建的對象已經(jīng)存在
  • 需要操作的對象不存在
  • 約束沖突
  • 參數(shù),版本

主庫連接數(shù)上線,或者是主庫太繁忙

> show slave  staus \G 
Last_IO_Errno: 1040
Last_IO_Error: error reconnecting to master 'repl@10.0.0.51:3307' - retry-time: 10  retries: 7
### 處理思路:
#### 拿復(fù)制用戶,手工連接一下

mysql -urepl -p123 -h 10.0.0.51 -P 3307 
mysql: [Warning] Using a password on the command line interface can be insecure.
ERROR 1040 (HY000): Too many connections
### 處理方法:
set global max_connections=300;

==sql線程故障的處理方法==

### 方法一:
stop slave; 
set global sql_slave_skip_counter = 1;
#### 將同步指針向下移動(dòng)一個(gè)锋边,如果多次不同步皱坛,可以重復(fù)操作。
#### 使用這種方法豆巨,一定要保證此時(shí)故障數(shù)據(jù)是完全一致的剩辟,才能采用
#### 可以使用第三方工具,幫助我們檢查主從數(shù)據(jù)一致,并可惡意修復(fù)主從不一致情況
#### pt工具贩猎,主從相關(guān)的===
start slave;

### 方法二:暴力方法熊户,遇到自動(dòng)跳過
/etc/my.cnf
slave-skip-errors = 1032,1062,1007
#### 常見錯(cuò)誤代碼:
#### 1007:對象已存在
#### 1032:無法執(zhí)行DML
#### 1062:主鍵沖突,或約束沖突

### 但是,以上操作有時(shí)是有風(fēng)險(xiǎn)的融欧,

### 最安全的做法就是備份恢復(fù)+重新構(gòu)建主從---方法四(時(shí)間久)敏弃。把握一個(gè)原則,一切以主庫為主.===

### 方法三:好===
#### 將從庫進(jìn)行反操作一下。重啟線程
drop database xinzhan;
start slave sql_thread;

主從延時(shí)問題

  • ==seconds_behind_master=0==
    • 0秒噪馏,這個(gè)不能得出有或沒有延時(shí)的情況

原因

  • 外部
    • 網(wǎng)絡(luò)、主從硬件差異绿饵、版本差異欠肾、參數(shù)
  • 內(nèi)部
    • 主庫
      • 二進(jìn)制日志寫入不及時(shí)
      • 主庫并發(fā)事務(wù)量大,主庫可以并行,傳送時(shí)是串行
      • 主庫發(fā)生了大事務(wù),由于是串行傳送,會(huì)產(chǎn)生阻塞后續(xù)的事務(wù).
    • 從庫
      • 從庫默認(rèn)情況下只有一個(gè)SQL,只能串行回放事務(wù)SQL
      • 主庫如果并發(fā)事務(wù)量較大,從庫只能串行回放
      • 主庫發(fā)生了大事務(wù),會(huì)阻塞后續(xù)的所有的事務(wù)的運(yùn)行

主庫延時(shí)解決方案:

  1. 5.6 開始,開啟GTID,實(shí)現(xiàn)了GC(group commit)機(jī)制,可以并行傳輸日志給從庫IO
  2. 5.7 開始,不開啟GTID,會(huì)自動(dòng)維護(hù)匿名的GTID,也能實(shí)現(xiàn)GC,我們建議還是認(rèn)為開啟GTID
  3. 大事務(wù)拆成多個(gè)小事務(wù),可以有效的減少主從延時(shí).

從庫延時(shí)解決方案:

  1. 5.6 版本開啟GTID之后,加入了SQL多線程的特性,但是只能針對不同庫(database)下的事務(wù)進(jìn)行并發(fā)回放.
  2. 5.7 版本開始GTID之后,在SQL方面,提供了基于邏輯時(shí)鐘(logical_clock),binlog加入了seq_no機(jī)制,真正實(shí)現(xiàn)了基于事務(wù)級別的并發(fā)回放,這種技術(shù)我們把它稱之為MTS(enhanced multi-threaded slave).
  3. 大事務(wù)拆成多個(gè)小事務(wù),可以有效的減少主從延時(shí).

img

第十三天


延時(shí)從庫

介紹

  • 配置的一種特殊從庫,人為配置從庫和主庫延時(shí)
  • 一般企業(yè)建議3-6小時(shí)

數(shù)據(jù)庫故障?

  • 物理損壞:主從復(fù)制非常擅長解決物理損壞.
  • 邏輯損壞:普通主從復(fù)制沒辦法解決邏輯損壞

延時(shí)從庫:主庫做了某項(xiàng)操作之后拟赊,從庫延時(shí)多長時(shí)間回放(SQL)刺桃。可以處理邏輯損壞

配置延時(shí)從庫

### SQL線程延時(shí):數(shù)據(jù)已經(jīng)寫入relaylog中了,SQL線程"慢點(diǎn)"運(yùn)行
### 一般企業(yè)建議3-6小時(shí),具體看公司運(yùn)維人員對于故障的反應(yīng)時(shí)間

mysql>stop slave;
mysql>CHANGE MASTER TO MASTER_DELAY = 300;
mysql>start slave;
mysql> show slave status \G
SQL_Delay: 300
SQL_Remaining_Delay: NULL

==應(yīng)用==

### 故障模擬及恢復(fù)
#### 1.主庫數(shù)據(jù)操作
create database relay charset utf8;
use relay
create table t1 (id int);
insert into t1 values(1);
drop database relay;

#### 2. 停止從庫SQL線程
stop slave sql_thread;

#### 3. 找relaylog的截取起點(diǎn)和終點(diǎn)
##### 起點(diǎn):
Relay_Log_File: db01-relay-bin.000002
Relay_Log_Pos: 482
##### 終點(diǎn):
show relaylog events in 'db01-relay-bin.000002'
| db01-relay-bin.000002 | 1046 | Xid            |         7 |        2489 | COMMIT /* xid=144 */                  |
| db01-relay-bin.000002 | 1077 | Anonymous_Gtid |         7 |        2554 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'  |

mysqlbinlog --start-position=482 --stop-position=1077  /data/3308/data/db01-relay-bin.000002>/tmp/relay.sql

#### 4.從庫恢復(fù)relaylog
source /tmp/relay.sql

#### 5.從庫身份解除
stop slave;
reset slave all

過濾復(fù)制

主庫

  • show master status;
  • binlog_do_db
  • binlog_ignore_db

從庫

  • show slave status\G
  • replicate_do_db
  • replicate_ignore_db

實(shí)現(xiàn)過程

mysqldump -S /data/3307/mysql.sock -A --master-data=2 --single-transaction  -R --triggers >/backup/full.sql

vim  /backup/full.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=154;

[root@db01 ~]# mysql -S /data/3309/mysql.sock 
source /backup/full.sql

CHANGE MASTER TO
MASTER_HOST='10.0.0.51',
MASTER_USER='repl',
MASTER_PASSWORD='123',
MASTER_PORT=3307,
MASTER_LOG_FILE='mysql-bin.000002',
MASTER_LOG_POS=154,
MASTER_CONNECT_RETRY=10;
start  slave;

[root@db01 ~]# vim /data/3309/my.cnf 
replicate_do_db=ppt
replicate_do_db=word
[root@db01 ~]# systemctl restart mysqld3309

### 主庫:
Master [(none)]>create database word;
Query OK, 1 row affected (0.00 sec)
Master [(none)]>create database ppt;
Query OK, 1 row affected (0.00 sec)
Master [(none)]>create database excel;
Query OK, 1 row affected (0.01 sec)

半同步復(fù)制

  1. 主庫執(zhí)行新的事務(wù),commit時(shí),更新 show master status\G ,觸發(fā)一個(gè)信號(hào)給
  2. binlog dump 接收到主庫的 show master status\G信息,通知從庫日志更新了
  3. 從庫IO線程請求新的二進(jìn)制日志事件
  4. 主庫會(huì)通過dump線程傳送新的日志事件,給從庫IO線程
  5. 從庫IO線程接收到binlog日志,當(dāng)日志寫入到磁盤上的relaylog文件時(shí),給主庫ACK_receiver線程
  6. ACK_receiver線程觸發(fā)一個(gè)事件,告訴主庫commit可以成功了
  7. 如果ACK達(dá)到了我們預(yù)設(shè)值的超時(shí)時(shí)間,半同步復(fù)制會(huì)切換為原始的異步復(fù)制.

在classic replication:傳統(tǒng)異步非gtid復(fù)制工作模型下吸祟。會(huì)導(dǎo)致主從數(shù)據(jù)不一致情況瑟慈。

在5.5版本為了保證主從數(shù)據(jù)的一致性問題,加入了半同步復(fù)制的組件(插件)

在主從結(jié)構(gòu)中屋匕,都加入了半同步復(fù)制的插件

控制從庫io是否將relaylog落盤葛碧,一旦落盤通過插件返回ack給主庫ack_rec。接受到ack之后过吻,主庫的事務(wù)才能提交成功进泼。在默認(rèn)情況下,如果超過10秒沒有返回ack纤虽,此次復(fù)制行為會(huì)切換為異步復(fù)制乳绕。

在5.6、5.7當(dāng)中也加入了一些比較好的特性(after commit逼纸,after sync洋措,無損...),也不能完全保證5個(gè)9以上的數(shù)據(jù)一致

如果生產(chǎn)業(yè)務(wù)比較關(guān)注==主從最終一致==杰刽。我們推薦可以使用==mgr的架構(gòu)菠发,或者pxc等一致性結(jié)構(gòu)==

### 加載插件
#### 主:
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#### 從:
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

### 查看是否加載成功:
show plugins;

### 啟動(dòng):
#### 主:
SET GLOBAL rpl_semi_sync_master_enabled = 1;
#### 從:
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

### 重啟從庫上的IO線程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;

### 查看是否在運(yùn)行
#### 主:
show status like 'Rpl_semi_sync_master_status';
#### 從:
show status like 'Rpl_semi_sync_slave_status';

### 這個(gè)是過渡的,可以不用操作

==GTID復(fù)制==

作用

  • 主要保證主從復(fù)制中的高級的特性

GTID

  • 5.6版本出現(xiàn)专缠,沒有默認(rèn)開啟
  • 5.7中即使不開啟雷酪,也有匿名的GTID的記錄
  • dump傳輸可以并行,sql線程并發(fā)回放提供了保障涝婉。5.7.17+的版本以后幾乎都是GTID模式

配置過程

  • 第一次開啟的時(shí)候哥力,讀取relaylog的最后的gtid+讀取==gtid_purge參數(shù)==,確認(rèn)復(fù)制起點(diǎn)
### 清理環(huán)境
pkill mysqld
rm -rf /data/mysql/data/*
rm -rf /data/binlog/*3
### 準(zhǔn)備配置文件
#### 主庫db01:
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/data/mysql/
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=51
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db01 [\\d]>
EOF

#### slave1(db02):
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/data/mysql
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=52
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db02 [\\d]>
EOF

#### slave2(db03):
cat > /etc/my.cnf <<EOF
[mysqld]
basedir=/data/mysql
datadir=/data/mysql/data
socket=/tmp/mysql.sock
server_id=53
port=3306
secure-file-priv=/tmp
autocommit=0
log_bin=/data/binlog/mysql-bin
binlog_format=row
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
[mysql]
prompt=db03 [\\d]>
EOF

####
gtid-mode=on                --啟用gtid類型,否則就是普通的復(fù)制架構(gòu)
enforce-gtid-consistency=true     --強(qiáng)制GTID的一致性
log-slave-updates=1            --slave更新是否記入日志

### 初始化數(shù)據(jù)(三臺(tái))
mysqld --initialize-insecure --user=mysql --basedir=/data/mysql  --datadir=/data/mysql/data 

### 啟動(dòng)數(shù)據(jù)庫
/etc/init.d/mysqld start
### 構(gòu)建主從
### master:51
### slave:52,53

####  51:
grant replication slave  on *.* to repl@'10.0.0.%' identified by '123';

#### 52\53:
change master to 
master_host='10.0.0.51',
master_user='repl',
master_password='123' ,
MASTER_AUTO_POSITION=1;

start slave;

##### MASTER_AUTO_POSITION=1

GTID從庫誤寫入操作處理

### 查看監(jiān)控信息
Last_SQL_Error: Error 'Can't create database 'oldboy'; database exists' on query. Default database: 'oldboy'. Query: 'create database oldboy'

Retrieved_Gtid_Set: 71bfa52e-4aae-11e9-ab8c-000c293b577e:1-3
Executed_Gtid_Set:  71bfa52e-4aae-11e9-ab8c-000c293b577e:1-2,
7ca4a2b7-4aae-11e9-859d-000c298720f6:1

#### 注入空事物的方法:
stop slave;
set gtid_next='99279e1e-61b7-11e9-a9fc-000c2928f5dd:3';
begin;commit;
set gtid_next='AUTOMATIC';
    
### 這里的xxxxx:N 也就是你的slave sql thread報(bào)錯(cuò)的GTID吩跋,或者說是你想要跳過的GTID寞射。
### 最好的解決方案:重新構(gòu)建主從環(huán)境

GTID 復(fù)制和普通復(fù)制的區(qū)別

(0)在主從復(fù)制環(huán)境中,主庫發(fā)生過的事務(wù),在全局都是由唯一GTID記錄的,更方便Failover
(1)額外功能參數(shù)(3個(gè))
(2)change master to 的時(shí)候不再需要binlog 文件名和positio號(hào),MASTER_AUTO_POSITION=1;
(3)在復(fù)制過程中欣尼,從庫不再依賴master.info文件烦粒,而是直接讀取最后一個(gè)relaylog的 GTID號(hào)
(4) mysqldump備份時(shí),默認(rèn)會(huì)將備份中包含的事務(wù)操作戴卜,以以下方式
SET @@GLOBAL.GTID_PURGED='8c49d7ec-7e78-11e8-9638-000c29ca725d:1';
告訴從庫,我的備份中已經(jīng)有以上事務(wù),你就不用運(yùn)行了掏觉,直接從下一個(gè)GTID開始請求binlog就行。


第十四天


MHA

介紹

高可用架構(gòu)

(1)單活:MMM架構(gòu)——mysql-mmm(google)
(2)單活:MHA架構(gòu)——mysql-master-ha(日本DeNa),T-MHA
(3)多活:MGR ——5.7 新特性 MySQL Group replication(5.7.17) --->Innodb Cluster
(4)多活:MariaDB Galera Cluster架構(gòu),(PXC)Percona XtraDB Cluster值漫、MySQL Cluster(Oracle rac)架構(gòu)

xenon澳腹??杨何?

Orchestrator酱塔??危虱?

https://www.cnblogs.com/konggg/category/1493418.html

https://www.zhihu.com/column/c_1212787509211766784

http://wubx.net/

https://www.cnblogs.com/fengjian2016/category/1029383.html

https://www.cnblogs.com/geek-ace/

https://www.cnblogs.com/zhoujinyi/

https://github.com/openark

https://www.cnblogs.com/gomysql/

高性能架構(gòu)

讀寫分離架構(gòu)(讀性能較高)

  • 代碼級別
  • MySQL proxy (Atlas,mysql router,proxySQL(percona),maxscale)羊娃、amoeba(taobao)、xx-dbproxy等槽地。

分布式架構(gòu)(讀寫性能都提高):

  • 分庫分表——cobar--->TDDL(頭都大了),DRDS
  • Mycat--->DBLE自主研發(fā)等
  • NewSQL-->TiDB

==MHA架構(gòu)工作原理==

主庫宕機(jī)處理過程:

  1. 監(jiān)控節(jié)點(diǎn) (通過配置文件獲取所有節(jié)點(diǎn)信息)
    系統(tǒng),網(wǎng)絡(luò),SSH連接性
    主從狀態(tài),重點(diǎn)是主庫

  2. 選主
    (1) 如果判斷從庫(position或者GTID),數(shù)據(jù)有差異,最接近于Master的slave,成為備選主
    (2) 如果判斷從庫(position或者GTID),數(shù)據(jù)一致,按照配置文件順序,選主.
    (3) 如果設(shè)定有權(quán)重(candidate_master=1),按照權(quán)重強(qiáng)制指定備選主.

  3. 默認(rèn)情況下如果一個(gè)slave落后master 100M的relay logs的話迁沫,即使有權(quán)重,也會(huì)失效.

  4. 如果check_repl_delay=0的化,即使落后很多日志,也強(qiáng)制選擇其為備選主

  5. 數(shù)據(jù)補(bǔ)償
    (1) 當(dāng)SSH能連接,從庫對比主庫GTID 或者position號(hào),立即將二進(jìn)制日志保存至各個(gè)從節(jié)點(diǎn)并且應(yīng)用(save_binary_logs )
    (2) 當(dāng)SSH不能連接, 對比從庫之間的relaylog的差異(apply_diff_relay_logs)

  6. Failover
    將備選主進(jìn)行身份切換,對外提供服務(wù)
    其余從庫和新主庫確認(rèn)新的主從關(guān)系

  7. 應(yīng)用透明(VIP)

  8. 故障切換通知(send_reprt)

  9. 二次數(shù)據(jù)補(bǔ)償(binlog_server)

  10. 自愈自治(待開發(fā)...)

MHA高可用架構(gòu)介紹

1主2從,master:db01 slave:db02 db03 :
MHA 高可用方案軟件構(gòu)成

  • Manager軟件:選擇一個(gè)從節(jié)點(diǎn)安裝
  • Node軟件:所有節(jié)點(diǎn)都要安裝

MHA軟件構(gòu)成

Manager工具包主要包括以下幾個(gè)工具:

  • masterha_manger 啟動(dòng)MHA
  • masterha_check_ssh 檢查MHA的SSH配置狀況
  • masterha_check_repl 檢查MySQL復(fù)制狀況
  • masterha_master_monitor 檢測master是否宕機(jī)
  • masterha_check_status 檢測當(dāng)前MHA運(yùn)行狀態(tài)
  • masterha_master_switch 控制故障轉(zhuǎn)移(自動(dòng)或者手動(dòng))
  • masterha_conf_host 添加或刪除配置的server信息

Node工具包主要包括以下幾個(gè)工具:

  • save_binary_logs 保存和復(fù)制master的二進(jìn)制日志
  • apply_diff_relay_logs 識(shí)別差異的中繼日志事件并將其差異的事件應(yīng)用于其他的
  • purge_relay_logs 清除中繼日志(不會(huì)阻塞SQL線程)
  • 這些工具通常由MHA Manager的腳本觸發(fā)捌蚊,無需人為操作

==MHA環(huán)境搭建==

### 1.規(guī)劃
主庫: 51    node 
從庫: 
52      node
53      node    manager

### 2.配置關(guān)鍵程序軟連接
#### 2.之前集畅,需要準(zhǔn)備環(huán)境(略。1主2從GTID)
ln -s /data/mysql/bin/mysqlbinlog    /usr/bin/mysqlbinlog
ln -s /data/mysql/bin/mysql          /usr/bin/mysql

### 3.配置各節(jié)點(diǎn)互信
#### db01:
rm -rf /root/.ssh 
ssh-keygen
cd /root/.ssh 
mv id_rsa.pub authorized_keys
scp  -r  /root/.ssh  10.0.0.52:/root 
scp  -r  /root/.ssh  10.0.0.53:/root 
#### 各節(jié)點(diǎn)驗(yàn)證
#### db01:
ssh 10.0.0.51 date
ssh 10.0.0.52 date
ssh 10.0.0.53 date
#### db02:
ssh 10.0.0.51 date
ssh 10.0.0.52 date
ssh 10.0.0.53 date
#### db03:
ssh 10.0.0.51 date
ssh 10.0.0.52 date
ssh 10.0.0.53 date


### 4.安裝軟件
mha官網(wǎng):https://code.google.com/archive/p/mysql-master-ha/
github下載地址:https://github.com/yoshinorim/mha4mysql-manager/wiki/Downloads
#### 所有節(jié)點(diǎn)安裝node軟件依賴包
yum install perl-DBD-MySQL -y
rpm -ivh mha4mysql-node-0.56-0.el6.noarch.rpm
#### 所有節(jié)點(diǎn)創(chuàng)建mha需要的用戶
grant all privileges on *.* to mha@'10.0.0.%' identified by 'mha';
#### Manager軟件安裝(db03)
yum install -y perl-Config-Tiny epel-release perl-Log-Dispatch perl-Parallel-ForkManager perl-Time-HiRes
rpm -ivh mha4mysql-manager-0.56-0.el6.noarch.rpm

### 5.配置文件準(zhǔn)備(db03)
#### 創(chuàng)建配置文件目錄
 mkdir -p /etc/mha
#### 創(chuàng)建日志目錄
 mkdir -p /var/log/mha/app1
#### 編輯mha配置文件
#### app1.cnf表示是這個(gè)業(yè)務(wù)的名字
vim /etc/mha/app1.cnf
[server default]
master_ip_failover_script=/usr/local/bin/master_ip_failover
manager_log=/var/log/mha/app1/manager        
manager_workdir=/var/log/mha/app1            
master_binlog_dir=/data/binlog       
user=mha                                   
password=mha                               
ping_interval=2
repl_password=123
repl_user=repl
ssh_user=root                               
[server1]                                   
hostname=10.0.0.51
port=3306                                  
[server2]            
hostname=10.0.0.52
port=3306
[server3]
hostname=10.0.0.53
port=3306

### 6.狀態(tài)檢查
#### 互信檢查
masterha_check_ssh  --conf=/etc/mha/app1.cnf 
Fri Apr 19 16:39:34 2019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Apr 19 16:39:34 2019 - [info] Reading application default configuration from /etc/mha/app1.cnf..
Fri Apr 19 16:39:34 2019 - [info] Reading server configuration from /etc/mha/app1.cnf..
Fri Apr 19 16:39:34 2019 - [info] Starting SSH connection tests..
Fri Apr 19 16:39:35 2019 - [debug] 
Fri Apr 19 16:39:34 2019 - [debug]  Connecting via SSH from root@10.0.0.51(10.0.0.51:22) to root@10.0.0.52(10.0.0.52:22)..
Fri Apr 19 16:39:34 2019 - [debug]   ok.
Fri Apr 19 16:39:34 2019 - [debug]  Connecting via SSH from root@10.0.0.51(10.0.0.51:22) to root@10.0.0.53(10.0.0.53:22)..
Fri Apr 19 16:39:35 2019 - [debug]   ok.
Fri Apr 19 16:39:36 2019 - [debug] 
Fri Apr 19 16:39:35 2019 - [debug]  Connecting via SSH from root@10.0.0.52(10.0.0.52:22) to root@10.0.0.51(10.0.0.51:22)..
Fri Apr 19 16:39:35 2019 - [debug]   ok.
Fri Apr 19 16:39:35 2019 - [debug]  Connecting via SSH from root@10.0.0.52(10.0.0.52:22) to root@10.0.0.53(10.0.0.53:22)..
Fri Apr 19 16:39:35 2019 - [debug]   ok.
Fri Apr 19 16:39:37 2019 - [debug] 
Fri Apr 19 16:39:35 2019 - [debug]  Connecting via SSH from root@10.0.0.53(10.0.0.53:22) to root@10.0.0.51(10.0.0.51:22)..
Fri Apr 19 16:39:35 2019 - [debug]   ok.
Fri Apr 19 16:39:35 2019 - [debug]  Connecting via SSH from root@10.0.0.53(10.0.0.53:22) to root@10.0.0.52(10.0.0.52:22)..
Fri Apr 19 16:39:36 2019 - [debug]   ok.
Fri Apr 19 16:39:37 2019 - [info] All SSH connection tests passed successfully.

#### 主從狀態(tài)檢查
[root@db03 ~]# masterha_check_repl  --conf=/etc/mha/app1.cnf 
Fri Apr 19 16:40:50 2019 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Fri Apr 19 16:40:50 2019 - [info] Reading application default configuration from /etc/mha/app1.cnf..
Fri Apr 19 16:40:50 2019 - [info] Reading server configuration from /etc/mha/app1.cnf..
Fri Apr 19 16:40:50 2019 - [info] MHA::MasterMonitor version 0.56.
Fri Apr 19 16:40:51 2019 - [info] GTID failover mode = 1
Fri Apr 19 16:40:51 2019 - [info] Dead Servers:
Fri Apr 19 16:40:51 2019 - [info] Alive Servers:
Fri Apr 19 16:40:51 2019 - [info]   10.0.0.51(10.0.0.51:3306)
Fri Apr 19 16:40:51 2019 - [info]   10.0.0.52(10.0.0.52:3306)
Fri Apr 19 16:40:51 2019 - [info]   10.0.0.53(10.0.0.53:3306)
Fri Apr 19 16:40:51 2019 - [info] Alive Slaves:
Fri Apr 19 16:40:51 2019 - [info]   10.0.0.52(10.0.0.52:3306)  Version=5.7.20-log (oldest major version between slaves) log-bin:enabled
Fri Apr 19 16:40:51 2019 - [info]     GTID ON
Fri Apr 19 16:40:51 2019 - [info]     Replicating from 10.0.0.51(10.0.0.51:3306)
Fri Apr 19 16:40:51 2019 - [info]   10.0.0.53(10.0.0.53:3306)  Version=5.7.20-log (oldest major version between slaves) log-bin:enabled
Fri Apr 19 16:40:51 2019 - [info]     GTID ON
Fri Apr 19 16:40:51 2019 - [info]     Replicating from 10.0.0.51(10.0.0.51:3306)
Fri Apr 19 16:40:51 2019 - [info] Current Alive Master: 10.0.0.51(10.0.0.51:3306)
Fri Apr 19 16:40:51 2019 - [info] Checking slave configurations..
Fri Apr 19 16:40:51 2019 - [info]  read_only=1 is not set on slave 10.0.0.52(10.0.0.52:3306).
Fri Apr 19 16:40:51 2019 - [info]  read_only=1 is not set on slave 10.0.0.53(10.0.0.53:3306).
Fri Apr 19 16:40:51 2019 - [info] Checking replication filtering settings..
Fri Apr 19 16:40:51 2019 - [info]  binlog_do_db= , binlog_ignore_db= 
Fri Apr 19 16:40:51 2019 - [info]  Replication filtering check ok.
Fri Apr 19 16:40:51 2019 - [info] GTID (with auto-pos) is supported. Skipping all SSH and Node package checking.
Fri Apr 19 16:40:51 2019 - [info] Checking SSH publickey authentication settings on the current master..
Fri Apr 19 16:40:51 2019 - [info] HealthCheck: SSH to 10.0.0.51 is reachable.
Fri Apr 19 16:40:51 2019 - [info] 
10.0.0.51(10.0.0.51:3306) (current master)
 +--10.0.0.52(10.0.0.52:3306)
 +--10.0.0.53(10.0.0.53:3306)

Fri Apr 19 16:40:51 2019 - [info] Checking replication health on 10.0.0.52..
Fri Apr 19 16:40:51 2019 - [info]  ok.
Fri Apr 19 16:40:51 2019 - [info] Checking replication health on 10.0.0.53..
Fri Apr 19 16:40:51 2019 - [info]  ok.
Fri Apr 19 16:40:51 2019 - [warning] master_ip_failover_script is not defined.
Fri Apr 19 16:40:51 2019 - [warning] shutdown_script is not defined.
Fri Apr 19 16:40:51 2019 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.

### 7.開啟MHA(DB03)
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover  < /dev/null> /var/log/mha/app1/manager.log 2>&1 &

### 8.查看MHA狀態(tài)
[root@db03 ~]# masterha_check_status --conf=/etc/mha/app1.cnf
app1 (pid:4719) is running(0:PING_OK), master:10.0.0.51
[root@db03 ~]# mysql -umha -pmha -h 10.0.0.51 -e "show variables like 'server_id'"
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 51    |
+---------------+-------+
[root@db03 ~]# mysql -umha -pmha -h 10.0.0.52 -e "show variables like 'server_id'"
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 52    |
+---------------+-------+
[root@db03 ~]# mysql -umha -pmha -h 10.0.0.53 -e "show variables like 'server_id'"
mysql: [Warning] Using a password on the command line interface can be insecure.
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 53    |
+---------------+-------+

MHA Failover過程原理

高可用:最擅長的是為我們解決物理損壞

  1. 啟動(dòng)manager
    • 調(diào)用masterha_manager腳本啟動(dòng)manager程序
  2. 監(jiān)控
    • 通過masterha_master_monitor心跳檢測腳本缅糟,數(shù)據(jù)庫節(jié)點(diǎn)挺智,主要監(jiān)控主庫
    • 默認(rèn)探測4次,每隔(==ping_interval=2==)秒窗宦,如果主庫還沒有心跳赦颇,認(rèn)為主庫宕機(jī),進(jìn)入failover過程
  3. 選主
    1. 優(yōu)先級(主觀)赴涵,如果在節(jié)點(diǎn)配置時(shí)媒怯,加入==candidate_master=1==參數(shù)
      • 如果備選主,日志量落后master太多(后master 100M的relay logs的話)髓窜,也不會(huì)被選擇為新主
      • 可以通過==check_repl_delay=0==扇苞,不檢查日志落后的情況
    2. 日志量最接近主庫
    3. 日志量一樣欺殿,配置文件順序
  4. 日志補(bǔ)償
    • ssh能連上,通過==save_binary_logs==立即保存缺失部分的日志到從庫(/var/tmp目錄下)并恢復(fù)
    • ssh不能連鳖敷,兩個(gè)從庫進(jìn)行relay log日志diff(==apply_diff_relay_logs==)差異補(bǔ)償
  5. 主從身份切換脖苏,所有從庫取消和原有主庫的復(fù)制關(guān)系(stop slave ;reset slave all)。新主庫和剩余從庫重新構(gòu)建主從關(guān)系
  6. 故障庫自動(dòng)被剔除集群(==master_conf_host==配置信息去掉)
  7. MHA是一次性的高可用定踱,failover后棍潘,manger自動(dòng)退出

不足的地方:

  1. 數(shù)據(jù)補(bǔ)償
  2. 自動(dòng)提醒
  3. 自愈功能(待開發(fā))
  4. 應(yīng)用透明(vip)

==MHA+K8S+Operator官方==

==8.0 MGR+MYSQLSH==

應(yīng)用透明vip功能

### master_ip_failover_script=/usr/local/bin/master_ip_failover
### 注意:/usr/local/bin/master_ip_failover,必須事先準(zhǔn)備好

vi  /usr/local/bin/master_ip_failover
#### 修改一下幾行
my $vip = '10.0.0.55/24';
my $key = '1';
my $ssh_start_vip = "/sbin/ifconfig eth0:$key $vip";
my $ssh_stop_vip = "/sbin/ifconfig eth0:$key down";

vi /etc/mha/app1.cnf
#### 添加這一行
master_ip_failover_script=/usr/local/bin/master_ip_failover

dos2unix /usr/local/bin/master_ip_failover 
dos2unix: converting file /usr/local/bin/master_ip_failover to Unix format ...
chmod +x /usr/local/bin/master_ip_failover 

masterha_stop --conf=/etc/mha/app1.cnf
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

==binlog server==

### binlogserver配置:
#### 找一臺(tái)額外的機(jī)器崖媚,必須要有5.6以上的版本亦歉,支持gtid并開啟,我們直接用的第二個(gè)slave(db03)
vim /etc/mha/app1.cnf 
[binlog1]
no_master=1
hostname=10.0.0.53
master_binlog_dir=/data/mysql/binlog

mkdir -p /data/mysql/binlog
chown -R mysql.mysql /data/*
#### 修改完成后至扰,將主庫binlog拉過來(從000001開始拉鳍徽,之后的binlog會(huì)自動(dòng)按順序過來)

cd /data/mysql/binlog     -----》必須進(jìn)入到自己創(chuàng)建好的目錄
mysqlbinlog  -R --host=10.0.0.51 --user=mha --password=mha --raw  --stop-never mysql-bin.000001 &
#### ==拉取日志的起點(diǎn),需要按照目前從庫的已經(jīng)獲取到的二進(jìn)制日志點(diǎn)為起點(diǎn)==

masterha_stop --conf=/etc/mha/app1.cnf
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

郵件提箱

### 1. 準(zhǔn)備郵件腳本
####(1)準(zhǔn)備發(fā)郵件的腳本(上傳 email_2019-最新.zip中的腳本,到/usr/local/bin/中)
####(2)將準(zhǔn)備好的腳本添加到mha配置文件中,讓其調(diào)用
#### 可以自己用python發(fā)郵件寫的腳本

### 2. 修改manager配置文件敢课,調(diào)用郵件腳本
vi /etc/mha/app1.cnf
report_script=/usr/local/bin/send

### 3. 停止MHA
masterha_stop --conf=/etc/mha/app1.cnf
### 4. 開啟MHA    
nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &

測試mha failover功能

宕掉主庫

  • 查看vip
  • 主從狀態(tài)
  • 查看郵件
  • 切換日志
  • 故障庫是否剔除
  • masterha_manager+mysqlbinlog停掉

==故障修復(fù)思路==

  1. 排查進(jìn)程狀態(tài)
    • ps -ef|gerp manager
    • masterha_check_status --conf=/etc/mha/app1.cnf
  2. 檢查配置文件中的節(jié)點(diǎn)情況
    • cat /etc/mha/app1.cnf
    • 如果節(jié)點(diǎn)已經(jīng)被移除,說明切換過程已經(jīng)大部分成功
    • 如果節(jié)點(diǎn)還在绷杜,證明切換過程在中間卡住
  3. 看日志
    • ==cat /var/log/mha/app1/manager==
  4. 修復(fù)故障庫
    • /etc/init.d/mysqld start
    • .......
  5. 修復(fù)主從
    • 將故障庫修好后直秆,手動(dòng)加入已有的主從中,作為從庫
  6. 將配置文件修復(fù)(配置文件節(jié)點(diǎn)信息還在鞭盟,可忽略)
  7. 檢查ssh互信和repl的主從關(guān)系
    • masterha_check_ssh --conf=/etc/mha/app1.cnf
    • masterha_check_repl --conf=/etc/mha/app1.cnf
  8. 修復(fù)binlogserver
    • cd /data/mysql/binlog
    • rm -rf ./*
    • mysqlbinlog -R --host=10.0.0.52 --user=mha --password=mha --raw --stop-never mysql-bin.000001 &
      • 10.0.0.52為啥不是10.0.0.51
  9. 檢查主節(jié)點(diǎn)的vip的狀態(tài)
    • 如果不在圾结,再手工生成一下
  10. 啟動(dòng)mha
    • nohup masterha_manager --conf=/etc/mha/app1.cnf --remove_dead_master_conf --ignore_last_failover < /dev/null > /var/log/mha/app1/manager.log 2>&1 &
    • masterha_check_status --conf=/etc/mha/app1.cnf

atlas

Atlas是由 Qihoo 360, Web平臺(tái)部基礎(chǔ)架構(gòu)團(tuán)隊(duì)開發(fā)維護(hù)的一個(gè)基于MySQL協(xié)議的數(shù)據(jù)中間層項(xiàng)目。
它是在mysql-proxy 0.8.2版本的基礎(chǔ)上齿诉,對其進(jìn)行了優(yōu)化筝野,增加了一些新的功能特性。
360內(nèi)部使用Atlas運(yùn)行的mysql業(yè)務(wù)粤剧,每天承載的讀寫請求數(shù)達(dá)幾十億條歇竟。
下載地址https://github.com/Qihoo360/Atlas/releases
注意:
1、Atlas只能安裝運(yùn)行在64位的系統(tǒng)上
2抵恋、Centos 5.X安裝 Atlas-XX.el5.x86_64.rpm焕议,Centos 6.X安裝Atlas-XX.el6.x86_64.rpm。
3弧关、后端mysql版本應(yīng)大于5.1盅安,建議使用Mysql 5.6以上


自動(dòng)分表

使用Atlas的分表功能時(shí),首先需要在配置文件test.cnf設(shè)置tables參數(shù)世囊。
tables參數(shù)設(shè)置格式:數(shù)據(jù)庫名.表名.分表字段.子表數(shù)量别瞭,
比如:你的數(shù)據(jù)庫名叫school,表名叫stu株憾,分表字段叫id蝙寨,總共分為2張表,那么就寫為school.stu.id.2,如果還有其他的分表籽慢,以逗號(hào)分隔即可浸遗。

### 安裝配置(安裝在db03)
yum install -y Atlas*
cd /usr/local/mysql-proxy/conf
mv test.cnf test.cnf.bak
 vi test.cnf
[mysql-proxy]
admin-username = user
admin-password = pwd
proxy-backend-addresses = 10.0.0.55:3306
proxy-read-only-backend-addresses = 10.0.0.51:3306,10.0.0.53:3306
pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098=
daemon = true
keepalive = true
event-threads = 8
log-level = message
log-path = /usr/local/mysql-proxy/log
sql-log=ON
proxy-address = 0.0.0.0:33060
admin-address = 0.0.0.0:2345
charset=utf8

### 啟動(dòng)atlas
/usr/local/mysql-proxy/bin/mysql-proxyd test start
ps -ef |grep proxy

### 生產(chǎn)用戶要求
####開發(fā)人員申請一個(gè)應(yīng)用用戶 app(  select  update  insert)  密碼123456,要通過10網(wǎng)段登錄
#### 1. 在主庫中,創(chuàng)建用戶
grant select ,update,insert on *.* to app@'10.0.0.%' identified by '123456';
#### 2. 在atlas中添加生產(chǎn)用戶
/usr/local/mysql-proxy/bin/encrypt  123456      ---->制作加密密碼
vim test.cnf
pwds = repl:3yb5jEku5h4=,mha:O2jBXONX098=,app:/iZxz+0GRoA=

### 重啟atlas
/usr/local/mysql-proxy/bin/mysql-proxyd test restart
mysql -uapp -p123456  -h 10.0.0.53 -P 33060

功能測試

### 測試讀操作:
mysql -umha -pmha  -h 10.0.0.53 -P 33060 
db03 [(none)]>select @@server_id;
### 測試寫操作:
mysql> begin;select @@server_id;commit;

==atlas基本管理==

### 1.連接管理接口(db03)
mysql -uuser -ppwd -h127.0.0.1 -P2345

### 2.打印幫助
mysql> select * from help;

### 3.查詢后端所有節(jié)點(diǎn)信息
mysql>  SELECT * FROM backends    ;
+-------------+----------------+-------+------+
| backend_ndx | address        | state | type |
+-------------+----------------+-------+------+
|           1 | 10.0.0.55:3306 | up    | rw   |
|           2 | 10.0.0.51:3306 | up    | ro   |
|           3 | 10.0.0.53:3306 | up    | ro   |
+-------------+----------------+-------+------+
3 rows in set (0.00 sec)

### 4.動(dòng)態(tài)刪除節(jié)點(diǎn)
REMOVE BACKEND 3;

### 5.動(dòng)態(tài)添加節(jié)點(diǎn)
ADD SLAVE 10.0.0.53:3306;

### 6.保存配置到配置文件
save config;

### 7.上線或下線節(jié)點(diǎn)
set online $backend_id;
set offline $backend_id;

### 8.查看用戶
select * from  pwds;

### 9. 添加用戶
add pwd username:password;
#### username 必須在主從庫上都有,上面的password是明文箱亿,怎么變?yōu)槊芪?#### /usr/local/mysql-proxy/bin/encrypt  password

關(guān)于讀寫分離建議

  • mysql-router ---mysql官方
  • proxysql---percona
  • maxscale---mariadb

mycat

img
img

基礎(chǔ)環(huán)境準(zhǔn)備

  • 兩臺(tái)虛機(jī)db01跛锌,db02
  • 每臺(tái)創(chuàng)建四個(gè)mysql實(shí)例:3307、3308届惋、3309髓帽、3310
### 1.刪除歷史環(huán)境
pkill mysqld
rm -rf /data/330* 
mv /etc/my.cnf /etc/my.cnf.bak

### 2.創(chuàng)建相關(guān)目錄初始化數(shù)據(jù)
mkdir /data/33{07..10}/data -p
mysqld --initialize-insecure  --user=mysql --datadir=/data/3307/data --basedir=/app/mysql
mysqld --initialize-insecure  --user=mysql --datadir=/data/3308/data --basedir=/app/mysql
mysqld --initialize-insecure  --user=mysql --datadir=/data/3309/data --basedir=/app/mysql
mysqld --initialize-insecure  --user=mysql --datadir=/data/3310/data --basedir=/app/mysql

### 3.準(zhǔn)備配置文件和啟動(dòng)腳本
#### ========db01==============
cat >/data/3307/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
log-error=/data/3307/mysql.log
log_bin=/data/3307/mysql-bin
binlog_format=row
skip-name-resolve
server-id=7
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/data/3308/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3308/data
port=3308
socket=/data/3308/mysql.sock
log-error=/data/3308/mysql.log
log_bin=/data/3308/mysql-bin
binlog_format=row
skip-name-resolve
server-id=8
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/data/3309/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
port=3309
log-error=/data/3309/mysql.log
log_bin=/data/3309/mysql-bin
binlog_format=row
skip-name-resolve
server-id=9
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/data/3310/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3310/data
socket=/data/3310/mysql.sock
port=3310
log-error=/data/3310/mysql.log
log_bin=/data/3310/mysql-bin
binlog_format=row
skip-name-resolve
server-id=10
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/etc/systemd/system/mysqld3307.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3308.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3309.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3310.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target

[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
LimitNOFILE = 5000
EOF

#### ========db02===============
cat >/data/3307/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3307/data
socket=/data/3307/mysql.sock
port=3307
log-error=/data/3307/mysql.log
log_bin=/data/3307/mysql-bin
binlog_format=row
skip-name-resolve
server-id=17
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/data/3308/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3308/data
port=3308
socket=/data/3308/mysql.sock
log-error=/data/3308/mysql.log
log_bin=/data/3308/mysql-bin
binlog_format=row
skip-name-resolve
server-id=18
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/data/3309/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3309/data
socket=/data/3309/mysql.sock
port=3309
log-error=/data/3309/mysql.log
log_bin=/data/3309/mysql-bin
binlog_format=row
skip-name-resolve
server-id=19
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/data/3310/my.cnf<<EOF
[mysqld]
basedir=/app/mysql
datadir=/data/3310/data
socket=/data/3310/mysql.sock
port=3310
log-error=/data/3310/mysql.log
log_bin=/data/3310/mysql-bin
binlog_format=row
skip-name-resolve
server-id=20
gtid-mode=on
enforce-gtid-consistency=true
log-slave-updates=1
EOF

cat >/etc/systemd/system/mysqld3307.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3307/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3308.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3308/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3309.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3309/my.cnf
LimitNOFILE = 5000
EOF

cat >/etc/systemd/system/mysqld3310.service<<EOF
[Unit]
Description=MySQL Server
Documentation=man:mysqld(8)
Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
After=network.target
After=syslog.target
[Install]
WantedBy=multi-user.target
[Service]
User=mysql
Group=mysql
ExecStart=/app/mysql/bin/mysqld --defaults-file=/data/3310/my.cnf
LimitNOFILE = 5000
EOF

### 4.修改權(quán)限,啟動(dòng)多實(shí)例
chown -R mysql.mysql /data/*
systemctl start mysqld3307
systemctl start mysqld3308
systemctl start mysqld3309
systemctl start mysqld3310

mysql -S /data/3307/mysql.sock -e "show variables like 'server_id'"
mysql -S /data/3308/mysql.sock -e "show variables like 'server_id'"
mysql -S /data/3309/mysql.sock -e "show variables like 'server_id'"
mysql -S /data/3310/mysql.sock -e "show variables like 'server_id'"

### 5.節(jié)點(diǎn)主從規(guī)劃
#### 箭頭指向誰是主庫
    10.0.0.51:3307    <----->  10.0.0.52:3307
    10.0.0.51:3309    ------>  10.0.0.51:3307
    10.0.0.52:3309    ------>  10.0.0.52:3307

    10.0.0.52:3308  <----->    10.0.0.51:3308
    10.0.0.52:3310  ----->     10.0.0.52:3308
    10.0.0.51:3310  ----->     10.0.0.51:3308
    
### 6.分片規(guī)劃及配置
#### shard1:
    Master:10.0.0.51:3307
    slave1:10.0.0.51:3309
    Standby Master:10.0.0.52:3307
    slave2:10.0.0.52:3309   
##### db02
mysql  -S /data/3307/mysql.sock -e "grant replication slave on *.* to repl@'10.0.0.%' identified by '123';"
mysql  -S /data/3307/mysql.sock -e "grant all  on *.* to root@'10.0.0.%' identified by '123'  with grant option;"
##### db01
mysql  -S /data/3307/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3307/mysql.sock -e "start slave;"
mysql  -S /data/3307/mysql.sock -e "show slave status\G"

mysql  -S /data/3309/mysql.sock  -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3309/mysql.sock  -e "start slave;"
mysql  -S /data/3309/mysql.sock  -e "show slave status\G"
##### db02
mysql  -S /data/3307/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3307/mysql.sock -e "start slave;"
mysql  -S /data/3307/mysql.sock -e "show slave status\G"

mysql  -S /data/3309/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3309/mysql.sock -e "start slave;"
mysql  -S /data/3309/mysql.sock -e "show slave status\G"

#### shard2:
    Master:10.0.0.52:3308
    slave1:10.0.0.52:3310
    Standby Master:10.0.0.51:3308
    slave2:10.0.0.51:3310
##### db01
mysql  -S /data/3308/mysql.sock -e "grant replication slave on *.* to repl@'10.0.0.%' identified by '123';"
mysql  -S /data/3308/mysql.sock -e "grant all  on *.* to root@'10.0.0.%' identified by '123'  with grant option;"
##### db02
mysql  -S /data/3308/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3308/mysql.sock -e "start slave;"
mysql  -S /data/3308/mysql.sock -e "show slave status\G"

mysql  -S /data/3310/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3310/mysql.sock -e "start slave;"
mysql  -S /data/3310/mysql.sock -e "show slave status\G"
##### db01
mysql  -S /data/3308/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.52', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3308/mysql.sock -e "start slave;"
mysql  -S /data/3308/mysql.sock -e "show slave status\G"

mysql  -S /data/3310/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='10.0.0.51', MASTER_PORT=3308, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123';"
mysql  -S /data/3310/mysql.sock -e "start slave;"
mysql  -S /data/3310/mysql.sock -e "show slave status\G"

### 7.檢測主從狀態(tài)
mysql -S /data/3307/mysql.sock -e "show slave status\G"|grep "Running:"
mysql -S /data/3308/mysql.sock -e "show slave status\G"|grep "Running:"
mysql -S /data/3309/mysql.sock -e "show slave status\G"|grep "Running:"
mysql -S /data/3310/mysql.sock -e "show slave status\G"|grep "Running:"
#### 注:如果中間出現(xiàn)錯(cuò)誤脑豹,在每個(gè)節(jié)點(diǎn)進(jìn)行執(zhí)行以下命令郑藏,然后重復(fù)第6點(diǎn)
mysql -S /data/3307/mysql.sock -e "stop slave; reset slave all;"
mysql -S /data/3308/mysql.sock -e "stop slave; reset slave all;"
mysql -S /data/3309/mysql.sock -e "stop slave; reset slave all;"
mysql -S /data/3310/mysql.sock -e "stop slave; reset slave all;"
  1. schema拆分及業(yè)務(wù)分庫
  2. 垂直拆分-分庫分表
  3. 水平拆分-分片

企業(yè)代表產(chǎn)品(mysql分布式架構(gòu))

360 Atlas-Sharding
Alibaba cobar
Mycat---==DBLE==
Heisenberg
Oceanus
Vitess
OneProxy
DRDS

mycat安裝(db01)

### 1.安裝java運(yùn)行環(huán)境
yum install -y java

### 2.下載并安裝mycat
#### Mycat-server-xxxxx.linux.tar.gz
#### http://dl.mycat.org.cn/1.6.7.4/Mycat-server-1.6.7.4-release/
tar xf Mycat-server-1.6.5-release-20180122220033-linux.tar.gz

### 3.啟動(dòng)和連接
#### 配置環(huán)境變量
vim /etc/profile
export PATH=/application/mycat/bin:$PATH
source /etc/profile
#### 啟動(dòng)
mycat start
#### 連接mycat:
mysql -uroot -p123456 -h 127.0.0.1 -P8066

mycat軟件結(jié)構(gòu)

  • bin:程序目錄

    • mycat程序,啟動(dòng)和關(guān)閉mycat
    • 中間件
  • conf:配置相關(guān)目錄

    • ==schema.xml 主配置文件==

      • cd /application/mycat/conf
        mv schema.xml schema.xml.bak
        
        vim schema.xml 
        
        <?xml version="1.0"?>  
        <!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
        <mycat:schema xmlns:mycat="http://io.mycat/">
        
        ### 邏輯庫(testdb)
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> 
        </schema>  
        
        #### 數(shù)據(jù)節(jié)點(diǎn)DN(邏輯分片:dn1)瘩欺,實(shí)現(xiàn)分布式功能的垂直和水平拆分
            <dataNode name="dn1" dataHost="localhost1" database= "wordpress" />
            
        #### 數(shù)據(jù)主機(jī)DH必盖,讀寫分離和高可用
            <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1"> 
                <heartbeat>select user()</heartbeat>  
                
        ##### 主        
            <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> 
            
        ##### 從    
                    <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" /> 
            </writeHost> 
            
            </dataHost> 
            
        </mycat:schema>
        
    • rule.xml 分片配置

    • server.xml mycat服務(wù)相關(guān)配置(mysql -uroot -p123456 -h 127.0.0.1 -P8066)

  • logs:日志相關(guān)目錄

    • wrapper.log mycat啟動(dòng)日志
    • mycat.log mycat詳細(xì)工作日志

參數(shù)介紹

  • balance

    • balance="0", 不開啟讀寫分離機(jī)制,所有讀操作都發(fā)送到當(dāng)前可用的writeHost上俱饿。
    • balance="1"歌粥,全部的readHost與standby writeHost參與select語句的負(fù)載均衡,簡單的說拍埠,
      當(dāng)雙主雙從模式(M1->S1失驶,M2->S2,并且M1與 M2互為主備)枣购,正常情況下嬉探,M2,S1,S2都參與select語句的負(fù)載均衡。
    • balance="2"棉圈,所有讀操作都隨機(jī)的在writeHost涩堤、readhost上分發(fā)。
  • writeType

    • writeType="0", 所有寫操作發(fā)送到配置的第一個(gè)writeHost迄损,第一個(gè)掛了切到還生存的第二個(gè)writeHost定躏,重新啟動(dòng)后已切換后的為主,切換記錄在配置文件中:dnindex.properties .
    1. writeType=“1”芹敌,所有寫操作都隨機(jī)的發(fā)送到配置的writeHost痊远,但不推薦使用
  • switchType

    1. -1 表示不自動(dòng)切換
    • 1 默認(rèn)值,自動(dòng)切換
    • 2 基于MySQL主從同步的狀態(tài)決定是否切換 氏捞,心跳語句為 show slave status
  • datahost

  • maxCon="1000":最大的并發(fā)連接數(shù)

  • minCon="10" :mycat在啟動(dòng)之后碧聪,會(huì)在后端節(jié)點(diǎn)上自動(dòng)開啟的連接線程

  • tempReadHostAvailable="1"

    • 針對一主一從,如果雙主雙從就不需要了

應(yīng)用前環(huán)境準(zhǔn)備和配置(db01)

### 1.用戶創(chuàng)建及數(shù)據(jù)庫導(dǎo)入液茎,上面的操作后用戶已經(jīng)有了
#### db01:
mysql -S /data/3307/mysql.sock 
grant all on *.* to root@'10.0.0.%' identified by '123';
source /root/world.sql

mysql -S /data/3308/mysql.sock 
grant all on *.* to root@'10.0.0.%' identified by '123';
source /root/world.sql

### 2.配置文件處理(讀寫分離)
cd /application/mycat/conf
mv schema.xml schema.xml.bak
vim schema.xml 
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1"> 
</schema>  
        <dataNode name="sh1" dataHost="oldguo1" database= "world" />         
        <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">    
                <heartbeat>select user()</heartbeat>  
        <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> 
                        <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" /> 
        </writeHost> 
        </dataHost>  
</mycat:schema>

#### 重啟mycat
mycat restart

#### 讀寫分離測試
mysql -uroot -p -h 127.0.0.1 -P8066
show variables like 'server_id';
begin;
show variables like 'server_id';

### 3.配置讀寫分離及高可用
[root@db01 conf]# mv schema.xml schema.xml.rw
[root@db01 conf]# vim schema.xml

<?xml version="1.0"?>  
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">  
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1"> 
</schema>  
    <dataNode name="sh1" dataHost="oldguo1" database= "world" />  
    <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1"> 
        <heartbeat>select user()</heartbeat>  
    <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123"> 
            <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" /> 
    </writeHost> 
    <writeHost host="db3" url="10.0.0.52:3307" user="root" password="123"> 
            <readHost host="db4" url="10.0.0.52:3309" user="root" password="123" /> 
    </writeHost>        
    </dataHost>  
</mycat:schema>

#### 真正的 writehost:負(fù)責(zé)寫操作的writehost  
#### standby  writeHost  :和readhost一樣逞姿,只提供讀服務(wù)

####當(dāng)寫節(jié)點(diǎn)宕機(jī)后辞嗡,后面跟的readhost也不提供服務(wù),這時(shí)候standby的writehost就提供寫服務(wù)滞造,后面跟的readhost提供讀服務(wù)

#### 測試:
mysql -uroot -p123456 -h 127.0.0.1 -P 8066
show variables like 'server_id';
#### 讀寫分離測試
mysql -uroot -p -h 127.0.0.1 -P8066
show variables like 'server_id';
show variables like 'server_id';
show variables like 'server_id';
begin;
show variables like 'server_id';
#### 對db01 3307節(jié)點(diǎn)進(jìn)行關(guān)閉和啟動(dòng),測試讀寫操作

==垂直分表==

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">
        <table name="user" dataNode="sh1"/>
        <table name="order_t" dataNode="sh2"/>
</schema>
    <dataNode name="sh1" dataHost="oldguo1" database= "taobao" />
    <dataNode name="sh2" dataHost="oldguo2" database= "taobao" />
    <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
        <heartbeat>select user()</heartbeat>
    <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
            <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:3307" user="root" password="123">
            <readHost host="db4" url="10.0.0.52:3309" user="root" password="123" />
    </writeHost>
    </dataHost>
    <dataHost name="oldguo2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
        <heartbeat>select user()</heartbeat>
    <writeHost host="db1" url="10.0.0.51:3308" user="root" password="123">
            <readHost host="db2" url="10.0.0.51:3310" user="root" password="123" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:3308" user="root" password="123">
            <readHost host="db4" url="10.0.0.52:3310" user="root" password="123" />
    </writeHost>
    </dataHost>
</mycat:schema>
### 創(chuàng)建測試庫和表:
mysql -S /data/3307/mysql.sock -e "create database taobao charset utf8;"
mysql -S /data/3308/mysql.sock -e "create database taobao charset utf8;"
mysql -S /data/3307/mysql.sock -e "use taobao;create table user(id int,name varchar(20))";
mysql -S /data/3308/mysql.sock -e "use taobao;create table order_t(id int,name varchar(20))"

==水平拆分(表)==

概念

  • 分片策略
    • 范圍分片
    • 取模
    • 枚舉
    • 日期
    • hash
  • 分片鍵:作為分片條件的列

范圍分片==auto-sharding-long==

vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1"> 
        <table name="t3" dataNode="sh1,sh2" rule="auto-sharding-long" />
</schema>  
    <dataNode name="sh1" dataHost="oldguo1" database= "taobao" /> 
    <dataNode name="sh2" dataHost="oldguo2" database= "taobao" />  
    <dataHost name="oldguo1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
        <heartbeat>select user()</heartbeat>
    <writeHost host="db1" url="10.0.0.51:3307" user="root" password="123">
            <readHost host="db2" url="10.0.0.51:3309" user="root" password="123" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:3307" user="root" password="123">
            <readHost host="db4" url="10.0.0.52:3309" user="root" password="123" />
    </writeHost>
    </dataHost>
    <dataHost name="oldguo2" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
        <heartbeat>select user()</heartbeat>
    <writeHost host="db1" url="10.0.0.51:3308" user="root" password="123">
            <readHost host="db2" url="10.0.0.51:3310" user="root" password="123" />
    </writeHost>
    <writeHost host="db3" url="10.0.0.52:3308" user="root" password="123">
            <readHost host="db4" url="10.0.0.52:3310" user="root" password="123" />
    </writeHost>
    </dataHost>
</mycat:schema>


vim rule.xml
...
<tableRule name="auto-sharding-long">
                <rule>
                        <columns>id</columns>
                        <algorithm>rang-long</algorithm>
                </rule> 
    ...
<function name="rang-long"
    class="io.mycat.route.function.AutoPartitionByLong">
    <property name="mapFile">autopartition-long.txt</property>
</function>
vim autopartition-long.txt
# range start-end ,data node index
# K=1000,M=10000.
#0-500M=0
#500M-1000M=1
#1000M-1500M=2
# 或以下寫法
# 0-10000000=0
# 10000001-20000000=1
0-10=0
11-20=1

### 創(chuàng)建測試表:
mysql -S /data/3307/mysql.sock -e "use taobao;create table t3 (id int not null primary key auto_increment,name varchar(20) not null);"

mysql -S /data/3308/mysql.sock  -e "use taobao;create table t3 (id int not null primary key auto_increment,name varchar(20) not null);"

## 測試:
#### 重啟mycat
mycat restart
mysql -uroot -p123456 -h 127.0.0.1 -P 8066
insert into t3(id,name) values(1,'a');
insert into t3(id,name) values(2,'b');
insert into t3(id,name) values(3,'c');
insert into t3(id,name) values(4,'d');
insert into t3(id,name) values(11,'aa');
insert into t3(id,name) values(12,'bb');
insert into t3(id,name) values(13,'cc');
insert into t3(id,name) values(14,'dd');

取模分片==mod-long==

vim schema.xml
<table name="t4" dataNode="sh1,sh2" rule="mod-long" />

vim rule.xml
<property name="count">2</property>
### 準(zhǔn)備測試環(huán)境
#### 創(chuàng)建測試表:
mysql -S /data/3307/mysql.sock -e "use taobao;create table t4 (id int not null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t4 (id int not null primary key auto_increment,name varchar(20) not null);"

### 重啟mycat 
mycat restart 

### 測試: 
mysql -uroot -p123456 -h10.0.0.51 -P8066

use TESTDB
insert into t4(id,name) values(1,'a');
insert into t4(id,name) values(2,'b');
insert into t4(id,name) values(3,'c');
insert into t4(id,name) values(4,'d');

#### 分別登錄后端節(jié)點(diǎn)查詢數(shù)據(jù)
mysql -S /data/3307/mysql.sock -e "select * from taobao.t4;"
mysql -S /data/3308/mysql.sock -e "select * from taobao.t4;"

枚舉分片==sharding-by-intfile==

vim schema.xml
<table name="t5" dataNode="sh1,sh2" rule="sharding-by-intfile" />

vim rule.xml
<tableRule name="sharding-by-intfile"> 
<rule> <columns>name</columns> 
<algorithm>hash-int</algorithm> 
</rule> 
</tableRule> 

<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap"> 
<property name="mapFile">partition-hash-int.txt</property> 
  <property name="type">1</property>
                <!property name="defaultNode">0<!/property>
</function> 
vim partition-hash-int.txt 
bj=0 
sh=1
DEFAULT_NODE=1 

### columns 標(biāo)識(shí)將要分片的表字段续室,algorithm 分片函數(shù), 其中分片函數(shù)配置中谒养,mapFile標(biāo)識(shí)配置文件名稱

### 準(zhǔn)備測試環(huán)境
mysql -S /data/3307/mysql.sock -e "use taobao;create table t5 (id int not null primary key auto_increment,name varchar(20) not null);"
mysql -S /data/3308/mysql.sock -e "use taobao;create table t5 (id int not null primary key auto_increment,name varchar(20) not null);"

### 重啟mycat 
mycat restart 
mysql -uroot -p123456 -h10.0.0.51 -P8066
use TESTDB
insert into t5(id,name) values(1,'bj');
insert into t5(id,name) values(2,'sh');
insert into t5(id,name) values(3,'bj');
insert into t5(id,name) values(4,'sh');
insert into t5(id,name) values(5,'tj');

### 分別登錄后端節(jié)點(diǎn)查詢數(shù)據(jù)
mysql -S /data/3307/mysql.sock -e "select * from taobao.t5;"
mysql -S /data/3308/mysql.sock -e "select * from taobao.t5;"

<tableRule name="crc32slot">
<tableRule name="sharding-by-month">
==DBLE自己研究==


mycat+雙主雙從

==mycat+mha==

==mycat+pxc==


mycat全局表

a   b   c  d   
join 
t 

select  t1.name   ,t.x  from  t1 
join t 
select  t2.name   ,t.x  from  t2 
join t 
select  t3.name   ,t.x  from  t3 
join t 

使用場景:

如果你的業(yè)務(wù)中有些數(shù)據(jù)類似于數(shù)據(jù)字典挺狰,比如配置文件的配置,
常用業(yè)務(wù)的配置或者數(shù)據(jù)量不大很少變動(dòng)的表买窟,這些表往往不是特別大第股,而且大部分的業(yè)務(wù)場景都會(huì)用到嘉抓,那么這種表適合于Mycat全局表庞钢,無須對數(shù)據(jù)進(jìn)行切分垢揩,要在所有的分片上保存一份數(shù)據(jù)即可。

  • Mycat 在Join操作中亏推,業(yè)務(wù)表與全局表進(jìn)行Join聚合會(huì)優(yōu)先選擇相同分片內(nèi)的全局表join学赛,避免跨庫Join,
  • 在進(jìn)行數(shù)據(jù)插入操作時(shí)吞杭,mycat將把數(shù)據(jù)分發(fā)到全局表對應(yīng)的所有分片執(zhí)行罢屈,
  • 在進(jìn)行數(shù)據(jù)讀取時(shí)候?qū)?huì)隨機(jī)獲取一個(gè)節(jié)點(diǎn)讀取數(shù)據(jù)。
vim schema.xml 
<table name="t_area" primaryKey="id"  type="global" dataNode="sh1,sh2" /> 

### 后端數(shù)據(jù)準(zhǔn)備
mysql -S /data/3307/mysql.sock 
use taobao
create table t_area (id int not null primary key auto_increment,name varchar(20) not null);

mysql -S /data/3308/mysql.sock 
use taobao
create table t_area  (id int not null primary key auto_increment,name varchar(20) not null);

### 重啟mycat 
mycat restart 

### 測試: 
mysql -uroot -p123456 -h10.0.0.52 -P8066

use TESTDB
insert into t_area(id,name) values(1,'a');
insert into t_area(id,name) values(2,'b');
insert into t_area(id,name) values(3,'c');
insert into t_area(id,name) values(4,'d');

E-R分片

為了防止跨分片join篇亭,可以使用E-R模式

A join B
on a.xx=b.yy
join C
on A.id=C.id

1.png
vim schema.xml 
<table name="A" dataNode="sh1,sh2" rule="mod-long"> 
       <childTable name="B" joinKey="yy" parentKey="xx" /> 
</table> 

### rule的分片策略可以自己定義,如果rule有同名的锄贷,最好改名译蒂,然后添加rule.xml部分內(nèi)容

第十五天


nosql-redis

RDBMS :MySQL,Oracle 谊却,MSSQL柔昼,PG
NoSQL :not only sql---第二代數(shù)據(jù)庫架構(gòu)

  • 非關(guān)系型,非結(jié)構(gòu)化炎辨,半結(jié)構(gòu)化
  • 緩存數(shù)據(jù)庫
    • redis
    • memcached
    • tair
  • 文檔類
    • mongodb
    • es
  • 列存儲(chǔ)
    • hbase
  • 圖形存儲(chǔ)
    • neo4j

NewSQL:分布式數(shù)據(jù)庫架構(gòu)---第三代數(shù)據(jù)庫架構(gòu)轉(zhuǎn)型

數(shù)據(jù)類型豐富    (筆試捕透、面試)*****
支持持久化      (筆試、面試) *****
多種內(nèi)存分配及回收策略
支持事務(wù)            (面試)    ****
消息隊(duì)列碴萧、消息訂閱 
支持高可用                                 ****
支持分布式分片集群 (面試)   *****
緩存穿透\雪崩(筆試乙嘀、面試)   *****
Redis API                  **

redis功能介紹

  • 數(shù)據(jù)類型豐富 (筆試、面試)
  • 支持持久化 (筆試破喻、面試)
  • 多種內(nèi)存分配及回收策略
  • 支持事務(wù) (面試)
  • 消息隊(duì)列虎谢、消息訂閱
  • 支持高可用
  • 支持分布式分片集群 (面試)
  • 緩存穿透\雪崩(筆試、面試)
  • Redis API

企業(yè)緩存產(chǎn)品介紹

Memcached:

  • 優(yōu)點(diǎn):高性能讀寫曹质、單一數(shù)據(jù)類型婴噩、支持客戶端式分布式集群擎场、一致性hash、多核結(jié)構(gòu)几莽、多線程讀寫性能高迅办。
  • 缺點(diǎn):無持久化、節(jié)點(diǎn)故障可能出現(xiàn)緩存穿透章蚣、分布式需要客戶端實(shí)現(xiàn)站欺、跨機(jī)房數(shù)據(jù)同步困難、架構(gòu)擴(kuò)容復(fù)雜度高

Redis:

  • 優(yōu)點(diǎn):高性能讀寫究驴、多數(shù)據(jù)類型支持镊绪、數(shù)據(jù)持久化、高可用架構(gòu)洒忧、支持自定義虛擬內(nèi)存蝴韭、支持分布式分片集群、單線程讀寫性能極高

  • 缺點(diǎn):多線程讀寫較Memcached慢熙侍,所以更適合單機(jī)多實(shí)例的環(huán)境

新浪榄鉴、京東、直播類平臺(tái)蛉抓、網(wǎng)頁游戲

結(jié)論:memcache與redis在讀寫性能的對比

  • memcached 適合,多用戶訪問,每個(gè)用戶少量的rw
  • redis 適合,少用戶訪問,每個(gè)用戶大量rw

Tair:

  • 優(yōu)點(diǎn):高性能讀寫庆尘、支持三種存儲(chǔ)引擎(ddb、rdb巷送、ldb)驶忌、支持高可用、支持分布式分片集群笑跛、支撐了幾乎所有淘寶業(yè)務(wù)的緩存付魔。
  • 缺點(diǎn):單機(jī)情況下,讀寫性能較其他兩種產(chǎn)品較慢

redis使用場景

Memcached:多核的緩存服務(wù)飞蹂,更加適合于多用戶并發(fā)訪問次數(shù)較少的應(yīng)用場景
Redis:單核的緩存服務(wù)几苍,單節(jié)點(diǎn)情況下,更加適合于少量用戶陈哑,多次訪問的應(yīng)用場景妻坝。
Redis一般是==單機(jī)多實(shí)例架構(gòu),配合redis集群==出現(xiàn)惊窖。

redis安裝部署

### 下載:
wget http://download.redis.io/releases/redis-3.2.12.tar.gz
### 解壓:上傳至 /data
tar xzf redis-3.2.12.tar.gz
mv redis-3.2.12 redis

### 安裝:
yum -y install gcc automake autoconf libtool make
cd redis
make

### 環(huán)境變量:
vim /etc/profile 
export PATH=/data/redis/src:$PATH
source /etc/profile 

### 啟動(dòng):
redis-server & 

### 連接測試:
redis-cli 
127.0.0.1:6379> set num 10
OK
127.0.0.1:6379> get num
10

redis基本管理操作

### 1.基礎(chǔ)配置文件介紹
mkdir /data/6379
cat > /data/6379/redis.conf<<EOF
daemonize yes
port 6379
logfile /data/6379/redis.log
dir /data/6379
dbfilename dump.rdb
EOF

redis-cli shutdown 
redis-server /data/6379/redis.conf 
netstat -lnp|grep 63

### 2.配置文件說明
#### redis.conf
#### 是否后臺(tái)運(yùn)行:
daemonize yes
#### 默認(rèn)端口:
port 6379
#### 日志文件位置
logfile /var/log/redis.log
#### 持久化文件存儲(chǔ)位置
dir /data/6379
#### RDB持久化數(shù)據(jù)文件:
dbfilename dump.rdb

redis安全配置

### redis默認(rèn)開啟了保護(hù)模式刽宪,只允許本地回環(huán)地址登錄并訪問數(shù)據(jù)庫。
#### 禁止protected-mode
#### protected-mode yes/no (保護(hù)模式爬坑,是否只允許本地訪問)

###(1)Bind :指定IP進(jìn)行監(jiān)聽
vim /data/6379/redis.conf
bind 10.0.0.51  127.0.0.1

###(2)增加requirepass  {password}
vim /data/6379/redis.conf
requirepass 123456

redis-cli shutdown 
redis-server /data/6379/redis.conf 
netstat -lnp|grep 63

### ---------驗(yàn)證-----
#### 方法一:
redis-cli -a 123456
127.0.0.1:6379> set name zhangsan 
OK
127.0.0.1:6379> exit
#### 方法二:
redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> set a b

redis-cli -a 123 -h 10.0.0.51 -p 6379
10.0.0.51:6379> set b 2
OK

在線查看和修改配置

CONFIG GET *
CONFIG GET requirepass
CONFIG GET r*
CONFIG SET requirepass 123

config set maxmemory 128M
config rewrite
### 上面是這個(gè)寫入配置文件

redis持久化

  • rdb
    • 可以在指定的時(shí)間間隔內(nèi)生成數(shù)據(jù)集的 時(shí)間點(diǎn)快照(point-in-time snapshot)纠屋。新快照會(huì)覆蓋舊快照
    • 優(yōu)點(diǎn):速度快,適合于用做備份盾计,主從復(fù)制也是基于RDB持久化功能實(shí)現(xiàn)的售担。
    • 缺點(diǎn):會(huì)有數(shù)據(jù)丟失
  • aof(append-only log file)
    • 記錄服務(wù)器執(zhí)行的所有寫操作命令赁遗,并在服務(wù)器啟動(dòng)時(shí),通過重新執(zhí)行這些命令來還原數(shù)據(jù)集族铆。
    • AOF 文件中的命令全部以 Redis 協(xié)議的格式來保存岩四,新命令會(huì)被追加到文件的末尾。
    • 優(yōu)點(diǎn):可以最大程度保證數(shù)據(jù)不丟
    • 缺點(diǎn):日志記錄量級比較大哥攘,持久化時(shí)間較長
### rdb持久化核心配置參數(shù):
vim /data/6379/redis.conf
dir /data/6379
dbfilename dump.rdb
save 900 1
save 300 10
save 60 10000

配置分別表示:
900秒(15分鐘)內(nèi)有1個(gè)更改
300秒(5分鐘)內(nèi)有10個(gè)更改
60秒內(nèi)有10000個(gè)更改



### AOF持久化配置
appendonly yes
appendfsync always
appendfsync everysec
appendfsync no
是否打開aof日志功能
每1個(gè)命令,都立即同步到aof 
每秒寫1次
寫入工作交給操作系統(tǒng),由操作系統(tǒng)判斷緩沖區(qū)大小,統(tǒng)一寫入到aof.

vim /data/6379/redis.conf
appendonly yes
appendfsync everysec 



面試: redis 持久化方式有哪些剖煌?有什么區(qū)別?

  • rdb:基于快照的持久化逝淹,速度更快耕姊,一般用作備份,主從復(fù)制也是依賴于rdb持久化功能
  • aof:以追加的方式記錄redis操作日志的文件栅葡≤岳迹可以最大程度的保證redis數(shù)據(jù)安全,類似于mysql的binlog

redis數(shù)據(jù)類型

  • string

    • 應(yīng)用場景:會(huì)話緩存欣簇、計(jì)數(shù)器(微博數(shù)规脸,粉絲數(shù),訂閱熊咽、禮物)

    • #### 增
      set mykey "test"                為鍵設(shè)置新值莫鸭,并覆蓋原有值
      getset mycounter 0              設(shè)置值,取值同時(shí)進(jìn)行
      setex mykey 10 "hello"          設(shè)置指定 Key 的過期時(shí)間為10秒,在存活時(shí)間可以獲取value
      setnx mykey "hello"             若該鍵不存在,則為鍵設(shè)置新值
      mset key3  "zyx"  key4 "xyz"    批量設(shè)置鍵
      
      #### 刪
      del mykey                        刪除已有鍵
      
      #### 改
      append mykey "hello"            若該鍵并不存在,返回當(dāng)前 Value 的長度横殴;該鍵已經(jīng)存在被因,返回追加后 Value的長度
      incr mykey                      值增加1,若該key不存在,創(chuàng)建key,初始值設(shè)為0,增加后結(jié)果為1
      decrby  mykey  5                值減少5
      setrange mykey 20 dd            把第21和22個(gè)字節(jié),替換為dd, 超過value長度,自動(dòng)補(bǔ)0
      
      #### 查  
      exists mykey                    判斷該鍵是否存在,存在返回 1衫仑,否則返回0
      get mykey                       獲取Key對應(yīng)的value
      strlen mykey                    獲取指定 Key 的字符長度
      ttl mykey                       查看一下指定 Key 的剩余存活時(shí)間(秒數(shù))
      getrange mykey 1 20             獲取第2到第20個(gè)字節(jié),若20超過value長度,則截取第2個(gè)和后面所有的
      mget key3 key4                  批量獲取鍵
      
  • hash

    • ==應(yīng)用場景:數(shù)據(jù)庫緩存==

      • mysql的熱點(diǎn)表數(shù)據(jù)氏身,灌入到redis hash類型
    • ### 存數(shù)據(jù):
      hmset stu  id 101 name zhangsan age 20 gender m
      hmset stu1 id 102 name zhangsan1 age 21 gender f
      
      ### 取數(shù)據(jù):
      HMGET stu id name age gender
      HMGET stu1 id name age gender
      
      select concat("hmset city_",id," id ",id," name ",name," countrycode ",countrycode," district ",district," population ",population) from city limit 10 into outfile '/tmp/hmset.txt'
      
      
      ### 增
      hset myhash field1 "s"    
      若字段field1不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的Hashes, Hashes中,key為field1 ,并設(shè)value為s ,若存在會(huì)覆蓋原value
      hsetnx myhash field1 s    
      若字段field1不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的Hashes, Hashes中,key為field1 ,并設(shè)value為s惑畴, 若字段field1存在,則無效
      hmset myhash field1 "hello" field2 "world       一次性設(shè)置多個(gè)字段
      
      ### 刪
      hdel myhash field1                      刪除 myhash 鍵中字段名為 field1 的字段
      del myhash                              刪除鍵
      
      ### 改  
      hincrby myhash field 1                  給field的值加1
      
      ### 查
      hget myhash field1                      獲取鍵值為 myhash,字段為 field1 的值
      hlen myhash                             獲取myhash鍵的字段數(shù)量
      hexists myhash field1                   判斷 myhash 鍵中是否存在字段名為 field1 的字段
      hmget myhash field1 field2 field3       一次性獲取多個(gè)字段
      hgetall myhash                          返回 myhash 鍵的所有字段及其值
      hkeys myhash                            獲取myhash 鍵中所有字段的名字
      hvals myhash                            獲取 myhash 鍵中所有字段的值
      
  • list

    • 應(yīng)用場景:微信朋友圈,即時(shí)消息展示航徙;

    • ### 增 
      lpush mykey a b             若key不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的List,依次插入a ,b如贷, 若List類型的key存在,則插入value中
      lpushx mykey2 e             若key不存在,此命令無效, 若key存在,則插入value中
      linsert mykey before a a1   在 a 的前面插入新元素 a1
      linsert mykey after e e2    在e 的后面插入新元素 e2
      rpush mykey a b             在鏈表尾部先插入b,在插入a
      rpushx mykey e              若key存在,在尾部插入e, 若key不存在,則無效
      rpoplpush mykey mykey2      將mykey的尾部元素彈出,再插入到mykey2 的頭部(原子性的操作)
      
      ### 刪
      del mykey                   刪除已有鍵 
      lrem mykey 2 a              從頭部開始找,按先后順序,值為a的元素,刪除數(shù)量為2個(gè),若存在第3個(gè),則不刪除
      ltrim mykey 0 2             從頭開始,索引為0,1,2的3個(gè)元素,其余全部刪除
      
      ### 改
      lset mykey 1 e              從頭開始, 將索引為1的元素值,設(shè)置為新值 e,若索引越界,則返回錯(cuò)誤信息
      rpoplpush mykey mykey       將 mykey 中的尾部元素移到其頭部
      
      ### 查
      lrange mykey 0 -1           取鏈表中的全部元素到踏,其中0表示第一個(gè)元素,-1表示最后一個(gè)元素杠袱。
      lrange mykey 0 2            從頭開始,取索引為0,1,2的元素
      lrange mykey 0 0            從頭開始,取第一個(gè)元素,從第0個(gè)開始,到第0個(gè)結(jié)束
      lpop mykey                  獲取頭部元素,并且彈出頭部元素,出棧
      lindex mykey 6              從頭開始,獲取索引為6的元素 若下標(biāo)越界,則返回nil 
      
  • set

    • 社交類的平臺(tái),好友系統(tǒng)窝稿。共同好友楣富,二度好友

    • ### 增
      sadd myset a b c  
      若key不存在,創(chuàng)建該鍵及與其關(guān)聯(lián)的set,依次插入a ,b,若key存在,則插入value中,若a 在myset中已經(jīng)存在,則插入了 d 和 e 兩個(gè)新成員。
      
      ### 刪
      spop myset              尾部的b被移出,事實(shí)上b并不是之前插入的第一個(gè)或最后一個(gè)成員
      srem myset a d f        若f不存在, 移出 a伴榔、d ,并返回2
      
      ### 改
      smove myset myset2 a        將a從 myset 移到 myset2纹蝴,
      
      ### 查
      sismember myset a           判斷 a 是否已經(jīng)存在庄萎,返回值為 1 表示存在。
      smembers myset          查看set中的內(nèi)容
      scard myset             獲取Set 集合中元素的數(shù)量
      srandmember myset       隨機(jī)的返回某一成員
      sdiff myset1 myset2 myset3      1和2得到一個(gè)結(jié)果,拿這個(gè)集合和3比較,獲得每個(gè)獨(dú)有的值
      sdiffstore diffkey myset myset2 myset3      3個(gè)集和比較,獲取獨(dú)有的元素,并存入diffkey 關(guān)聯(lián)的Set中
      sinter myset myset2 myset3              獲得3個(gè)集合中都有的元素
      sinterstore interkey myset myset2 myset3  把交集存入interkey 關(guān)聯(lián)的Set中
      sunion myset myset2 myset3              獲取3個(gè)集合中的成員的并集
      sunionstore unionkey myset myset2 myset3  把并集存入unionkey 關(guān)聯(lián)的Set中
      
  • sorted-set

    • 排行榜

    • ### 增
      zadd myzset 2 "two" 3 "three"       添加兩個(gè)分?jǐn)?shù)分別是 2 和 3 的兩個(gè)成員
      
      ### 刪
      zrem myzset one two                 刪除多個(gè)成員變量,返回刪除的數(shù)量
      
      ### 改
      zincrby myzset 2 one                將成員 one 的分?jǐn)?shù)增加 2塘安,并返回該成員更新后的分?jǐn)?shù)
      
      ### 查 
      zrange myzset 0 -1 WITHSCORES       返回所有成員和分?jǐn)?shù),不加WITHSCORES,只返回成員
      zrank myzset one                    獲取成員one在Sorted-Set中的位置索引值糠涛。0表示第一個(gè)位置
      zcard myzset                        獲取 myzset 鍵中成員的數(shù)量
      zcount myzset 1 2                   獲取分?jǐn)?shù)滿足表達(dá)式 1 <= score <= 2 的成員的數(shù)量
      zscore myzset three                 獲取成員 three 的分?jǐn)?shù)
      zrangebyscore myzset  1 2               獲取分?jǐn)?shù)滿足表達(dá)式 1 < score <= 2 的成員
      #-inf 表示第一個(gè)成員,+inf最后一個(gè)成員
      #limit限制關(guān)鍵字
      #2  3  是索引號(hào)
      zrangebyscore myzset -inf +inf limit 2 3  返回索引是2和3的成員
      zremrangebyscore myzset 1 2         刪除分?jǐn)?shù) 1<= score <= 2 的成員兼犯,并返回實(shí)際刪除的數(shù)量
      zremrangebyrank myzset 0 1              刪除位置索引滿足表達(dá)式 0 <= rank <= 1 的成員
      zrevrange myzset 0 -1 WITHSCORES        按位置索引從高到低,獲取所有成員和分?jǐn)?shù)
      #原始成員:位置索引從小到大
            one  0  
            two  1
      #執(zhí)行順序:把索引反轉(zhuǎn)
            位置索引:從大到小
            one 1
            two 0
      #輸出結(jié)果: two  
             one
      zrevrange myzset 1 3                獲取位置索引,為1,2,3的成員
      #相反的順序:從高到低的順序
      zrevrangebyscore myzset 3 0             獲取分?jǐn)?shù) 3>=score>=0的成員并以相反的順序輸出
      zrevrangebyscore myzset 4 0 limit 1 2    獲取索引是1和2的成員,并反轉(zhuǎn)位置索引
      
img

mysql--->canal--->redis

(1)
 set name zhangsan  
(2)
 MSET id 101 name zhangsan age 20 gender m
 等價(jià)于以下操作:
 SET id 101 
 set name zhangsan 
 set age 20 
 set gender m
(3)計(jì)數(shù)器
每點(diǎn)一次關(guān)注忍捡,都執(zhí)行以下命令一次
127.0.0.1:6379> incr num
顯示粉絲數(shù)量:
127.0.0.1:6379> get num

暗箱操作:
127.0.0.1:6379> INCRBY num 10000
(integer) 10006
127.0.0.1:6379> get num
"10006"
127.0.0.1:6379> DECRBY num 10000
(integer) 6
127.0.0.1:6379> get num
"6"


存數(shù)據(jù):
hmset stu  id 101 name zhangsan age 20 gender m
hmset stu1 id 102 name zhangsan1 age 21 gender f

取數(shù)據(jù):
HMGET stu id name age gender
HMGET stu1 id name age gender

select concat("hmset city_",id," id ",id," name ",name," countrycode ",countrycode," district ",district," population ",population) from city limit 10 into outfile '/tmp/hmset.txt'


微信朋友圈:
127.0.0.1:6379> LPUSH wechat "today is nice day !"
127.0.0.1:6379> LPUSH wechat "today is bad day !"
127.0.0.1:6379> LPUSH wechat "today is good  day !"
127.0.0.1:6379> LPUSH wechat "today is rainy  day !"
127.0.0.1:6379> LPUSH wechat "today is friday !"

[5,4,3,2,1]
 0 1 2 3 4 

[e,d,c,b,a]
0 1 2 3  4

127.0.0.1:6379> lrange wechat  0 0
1) "today is friday !"
127.0.0.1:6379> lrange wechat  0 1
1) "today is friday !"
2) "today is rainy  day !"
127.0.0.1:6379> lrange wechat  0 2
1) "today is friday !"
2) "today is rainy  day !"
3) "today is good  day !"
127.0.0.1:6379> lrange wechat  0 3
127.0.0.1:6379> lrange wechat  -2 -1
1) "today is bad day !"
2) "today is nice day !"


127.0.0.1:6379> sadd lxl pg1 jnl baoqiang gsy alexsb
(integer) 5
127.0.0.1:6379> sadd jnl baoqiang ms bbh yf wxg
(integer) 5
127.0.0.1:6379> SUNION lx jnl
1) "baoqiang"
2) "yf"
3) "bbh"
4) "ms"
5) "wxg"
127.0.0.1:6379> SUNION lxl  jnl
1) "gsy"
2) "yf"
3) "alexsb"
4) "bbh"
5) "jnl"
6) "pg1"
7) "baoqiang"
8) "ms"
9) "wxg"
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> SINTER lxl jnl
1) "baoqiang"
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> SDIFF jnl lxl
1) "wxg"
2) "yf"
3) "bbh"
4) "ms"
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> 
127.0.0.1:6379> SDIFF lxl jnl
1) "jnl"
2) "pg1"
3) "gsy"
4) "alexsb"


127.0.0.1:6379> zadd topN 0 smlt 0 fskl 0 fshkl 0 lzlsfs 0 wdhbx 0 wxg 
(integer) 6
127.0.0.1:6379> ZINCRBY topN 100000 smlt
"100000"
127.0.0.1:6379> ZINCRBY topN 10000 fskl
"10000"
127.0.0.1:6379> ZINCRBY topN 1000000 fshkl
"1000000"
127.0.0.1:6379> ZINCRBY topN 100 lzlsfs
"100"
127.0.0.1:6379> ZINCRBY topN 10 wdhbx
"10"
127.0.0.1:6379> ZINCRBY topN 100000000 wxg
"100000000"

127.0.0.1:6379> ZREVRANGE topN 0 2 
1) "wxg"
2) "fshkl"
3) "smlt"
127.0.0.1:6379> ZREVRANGE topN 0 2 withscores
1) "wxg"
2) "100000000"
3) "fshkl"
4) "1000000"
5) "smlt"
6) "100000"
127.0.0.1:6379> 


redis消息模式

消息模式是為了幫助解決在架構(gòu)中,資源有效利用方面提供有效的協(xié)調(diào)

redis的消息模式有兩種形式:消息隊(duì)列切黔、發(fā)布訂閱

img

發(fā)布訂閱

  • SUBSCRIBE channel [channel ...]
    • 訂閱頻道砸脊,可以同時(shí)訂閱多個(gè)頻道
  • PUBLISH channel msg
    • 將信息 message 發(fā)送到指定的頻道 channel
  • UNSUBSCRIBE [channel ...]
    • 取消訂閱指定的頻道, 如果不指定頻道,則會(huì)取消訂閱所有頻道
  • PSUBSCRIBE pattern [pattern ...]
    • 訂閱一個(gè)或多個(gè)符合給定模式的頻道纬霞,每個(gè)模式以 * 作為匹配符凌埂,比如 it* 匹配所 有以 it 開頭的頻道( it.news 、 it.blog 险领、 it.tweets 等等)侨舆, news.* 匹配所有 以 news. 開頭的頻道( news.it 、 news.global.today 等等)绢陌,諸如此類
  • PUNSUBSCRIBE [pattern [pattern ...]]
    • 退訂指定的規(guī)則, 如果沒有參數(shù)則會(huì)退訂所有規(guī)則
  • PUBSUB subcommand [argument [argument ...]]
    • 查看訂閱與發(fā)布系統(tǒng)狀態(tài)
### 注意:使用發(fā)布訂閱模式實(shí)現(xiàn)的消息隊(duì)列挨下,當(dāng)有客戶端訂閱channel后只能收到后續(xù)發(fā)布到該頻道的消息,之前發(fā)送的不會(huì)緩存脐湾,必須Provider和Consumer同時(shí)在線臭笆。

### 發(fā)布訂閱例子:
窗口1:
127.0.0.1:6379> SUBSCRIBE baodi 
窗口2:
127.0.0.1:6379> PUBLISH baodi "jin tian zhen kaixin!"

### 訂閱多頻道:
窗口1:
127.0.0.1:6379> PSUBSCRIBE wang*
窗口2:
127.0.0.1:6379> PUBLISH wangbaoqiang "jintian zhennanshou "

redis事務(wù)

redis的事務(wù)是基于隊(duì)列實(shí)現(xiàn)的。redis是樂觀鎖機(jī)制秤掌,僅實(shí)現(xiàn)原子性的保證愁铺,屬于弱事務(wù)支持
mysql的事務(wù)是基于事務(wù)日志和悲觀鎖機(jī)制、mvcc闻鉴、isolation等機(jī)制一起保證實(shí)現(xiàn)的茵乱,強(qiáng)事務(wù)支持。

### 開啟事務(wù)功能時(shí)(multi)
multi 
command1      
command2
command3
command4
exec 
discard

#### 4條語句作為一個(gè)組孟岛,并沒有真正執(zhí)行瓶竭,而是被放入同一隊(duì)列中。
#### 如果渠羞,這時(shí)執(zhí)行discard斤贰,會(huì)直接丟棄隊(duì)列中所有的命令,而不是做回滾次询。
#### 當(dāng)執(zhí)行exec時(shí)荧恍,對列中所有操作,要么全成功要么全失敗

127.0.0.1:6379> set a b
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a b
QUEUED
127.0.0.1:6379> set c d
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK

redis樂觀鎖實(shí)現(xiàn)(模擬買票)

### 發(fā)布一張票
set ticket 1
#### 窗口1:
watch ticket
multi
set ticket 0       1---->0
#### 窗口2:
multi 
set ticket 0 
exec 
窗口1:
exec

redis的key的通過操作和服務(wù)器管理命令

KEYS *   keys a  keys a*    查看已存在所有鍵的名字   ****
TYPE                        返回鍵所存儲(chǔ)值的類型     ****
EXPIRE\ PEXPIRE             以秒\毫秒設(shè)定生存時(shí)間       ***
TTL\ PTTL                   以秒\毫秒為單位返回生存時(shí)間 ***
PERSIST                     取消生存時(shí)間設(shè)置            ***
DEL                         刪除一個(gè)key
EXISTS                      檢查是否存在
RENAME                      變更KEY名

### 例子:
127.0.0.1:6379> set name zhangsan 
127.0.0.1:6379> EXPIRE name 60
(integer) 1
127.0.0.1:6379> ttl name
(integer) 57
127.0.0.1:6379> set a b ex 60
OK
127.0.0.1:6379> ttl a
127.0.0.1:6379> PERSIST a
(integer) 1
127.0.0.1:6379> ttl a
(integer) -1

==服務(wù)器管理命令==

  • info
    • info memory
    • info cpu
    • info replication
  • 剩下看下面的shell
  • config
  • nohup redis-cli -a 1 -h ip -p 6379 monitor>> /tmp/redis-mon.log &
Info

Client list
Client kill ip:port

config get *
CONFIG RESETSTAT 重置統(tǒng)計(jì)
CONFIG GET/SET/rewrite 動(dòng)態(tài)修改

Dbsize

FLUSHALL 清空所有數(shù)據(jù) 

select 1
FLUSHDB 清空當(dāng)前庫

MONITOR 監(jiān)控實(shí)時(shí)指令

SHUTDOWN 關(guān)閉服務(wù)器

min-slaves-to-write 1
min-slaves-max-lag  3


redis主從復(fù)制

redis master/slave replication(master-replica)

原理

  1. 副本庫通過slaveof 10.0.0.51 6379命令,連接主庫,并發(fā)送``SYNC`給主庫
  2. 主庫收到SYNC,會(huì)立即觸發(fā)BGSAVE,后臺(tái)保存RDB,發(fā)送給副本庫
  3. 副本庫接收后會(huì)應(yīng)用RDB快照
  4. 主庫會(huì)陸續(xù)將中間產(chǎn)生的新的操作,保存并發(fā)送給副本庫
  5. 到此,我們主復(fù)制集就正常工作了
  6. 再此以后,主庫只要發(fā)生新的操作,都會(huì)以命令傳播的形式自動(dòng)發(fā)送給副本庫.
  7. 所有復(fù)制相關(guān)信息,從info信息中都可以查到.即使重啟任何節(jié)點(diǎn),他的主從關(guān)系依然都在.
  8. 如果發(fā)生主從關(guān)系斷開時(shí),從庫數(shù)據(jù)沒有任何損壞,在下次重連之后,從庫發(fā)送PSYNC給主庫
  9. 主庫只會(huì)將從庫缺失部分的數(shù)據(jù)同步給從庫應(yīng)用,達(dá)到快速恢復(fù)主從的目的

主從數(shù)據(jù)一致性保證

  • min-slaves-to-write 1
  • min-slaves-max-lag 3

主庫是否要開啟持久化

如果不開有可能舒岸,主庫重啟操作凳寺,造成所有主從數(shù)據(jù)丟失!

主從復(fù)制操作

### 1猜谚、環(huán)境:
#### 準(zhǔn)備兩個(gè)或兩個(gè)以上redis實(shí)例
mkdir /data/638{0..2}

### 2.配置文件示例:
cat >> /data/6380/redis.conf <<EOF
port 6380
daemonize yes
pidfile /data/6380/redis.pid
loglevel notice
logfile "/data/6380/redis.log"
dbfilename dump.rdb
dir /data/6380
requirepass 123
masterauth 123
EOF

cat >>   /data/6381/redis.conf <<EOF
port 6381
daemonize yes
pidfile /data/6381/redis.pid
loglevel notice
logfile "/data/6381/redis.log"
dbfilename dump.rdb
dir /data/6381
requirepass 123
masterauth 123
EOF

cat >>   /data/6382/redis.conf <<EOF
port 6382
daemonize yes
pidfile /data/6382/redis.pid
loglevel notice
logfile "/data/6382/redis.log"
dbfilename dump.rdb
dir /data/6382
requirepass 123
masterauth 123
EOF

### 3.啟動(dòng):
redis-server /data/6380/redis.conf
redis-server /data/6381/redis.conf
redis-server /data/6382/redis.conf

####主節(jié)點(diǎn):6380
#### 從節(jié)點(diǎn):6381授艰、6382

### 4辨嗽、開啟主從:
####6381/6382命令行:
redis-cli -p 6381 -a 123 SLAVEOF 127.0.0.1 6380
redis-cli -p 6382 -a 123 SLAVEOF 127.0.0.1 6380

### 5、查詢主從狀態(tài)
 redis-cli -p 6380 -a 123 info replication
 redis-cli -p 6381 -a 123 info replication
 redis-cli -p 6382 -a 123 info replication

### 6.解除主從
redis-cli -p 6381 -a 123 SLAVEOF no one

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淮腾,一起剝皮案震驚了整個(gè)濱河市糟需,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌谷朝,老刑警劉巖洲押,帶你破解...
    沈念sama閱讀 212,542評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異圆凰,居然都是意外死亡杈帐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,596評論 3 385
  • 文/潘曉璐 我一進(jìn)店門专钉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挑童,“玉大人,你說我怎么就攤上這事跃须≌镜穑” “怎么了?”我有些...
    開封第一講書人閱讀 158,021評論 0 348
  • 文/不壞的土叔 我叫張陵菇民,是天一觀的道長尽楔。 經(jīng)常有香客問我,道長第练,這世上最難降的妖魔是什么阔馋? 我笑而不...
    開封第一講書人閱讀 56,682評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮娇掏,結(jié)果婚禮上呕寝,老公的妹妹穿的比我還像新娘。我一直安慰自己婴梧,他們只是感情好壁涎,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,792評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著志秃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪嚼酝。 梳的紋絲不亂的頭發(fā)上浮还,一...
    開封第一講書人閱讀 49,985評論 1 291
  • 那天,我揣著相機(jī)與錄音闽巩,去河邊找鬼钧舌。 笑死担汤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洼冻。 我是一名探鬼主播崭歧,決...
    沈念sama閱讀 39,107評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼撞牢!你這毒婦竟也來了率碾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,845評論 0 268
  • 序言:老撾萬榮一對情侶失蹤屋彪,失蹤者是張志新(化名)和其女友劉穎所宰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畜挥,經(jīng)...
    沈念sama閱讀 44,299評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡仔粥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,612評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蟹但。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片躯泰。...
    茶點(diǎn)故事閱讀 38,747評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖华糖,靈堂內(nèi)的尸體忽然破棺而出麦向,到底是詐尸還是另有隱情,我是刑警寧澤缅阳,帶...
    沈念sama閱讀 34,441評論 4 333
  • 正文 年R本政府宣布磕蛇,位于F島的核電站,受9級特大地震影響十办,放射性物質(zhì)發(fā)生泄漏秀撇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,072評論 3 317
  • 文/蒙蒙 一向族、第九天 我趴在偏房一處隱蔽的房頂上張望呵燕。 院中可真熱鬧,春花似錦件相、人聲如沸再扭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,828評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽泛范。三九已至,卻和暖如春紊撕,著一層夾襖步出監(jiān)牢的瞬間罢荡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,069評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留区赵,地道東北人惭缰。 一個(gè)月前我還...
    沈念sama閱讀 46,545評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像笼才,于是被迫代替她去往敵國和親漱受。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,658評論 2 350

推薦閱讀更多精彩內(nèi)容