分庫分表
-
關系型資料庫和NoSQL
非關系型資料庫: key-value: redis 、memcache ;
面向文檔: mongoDB
面向列: HBase
資料切分
mycat
TDDL
Sharding-JDBC
cobar
- 對于存儲層的壓力知道如何去提供解決方案和思路
- 對分庫分表的常用手段有全面了解
- 了解Mysql的主從及binlog
- 知道Mycat及其他相似的中間件
為什麼要分庫分表
超大容量問題
- 訂單表資料量過大
- 單表處理能力有瓶頸
性能問題
- 單一資料庫解決所有應用節點
- 單一資料庫有性能極限
如何去做到
垂直切分、 水準切分
- 垂直分庫
- 解決的是表過多的問題
- 不同的表放在不同的庫中
- 比如說訂單相關的放在訂單庫中
- 垂直分表
- 解決單表列過多的問題
- 列多的表拆分成多個列少的表
- 比如說商 品表拆分
- 通過關聯關系維持資料
- 比如說商 品表拆分
水準切分
- 大資料表拆成小表
常見的拆分政策
拆分如果全部放在一個庫中,可能會有性能問題。
可能把部分表放在不同的資料庫中
拆分次元選擇的資料非常重要
垂直拆分
er分片
水準拆分
- 一緻性hash
- 範圍切分
- 可以按照ID
- 日期拆分
拆分以後帶來的問題
跨庫join的問題
select a.x ,b.y from a,b on a.id=b.id
- 設計的時候考慮到應用層的join問題。
- 拆分的時候考慮好
-
在服務層去做調用
A服務裡查詢到一個list
直接通過接口查詢
/**
*批量查詢不要這樣使用
**/
for(list){
bservice.select(list);
}
- 全局表
- 資料變更比較少的基于全局應用的表
- 或者抽離公共服務
-
做字段備援(空間換時間的做法)
訂單表需要展示,商家id 商家名稱(因為訂單表和商家表是一對一的關系),那麼查詢的時候可能每一次都需要為了查詢商家名稱,可以做商家名稱字段備援
商家名稱變更解決辦法
- 定時任務
- 任務通知
跨分片資料排序分頁
在應用層做拼接
唯一主鍵問題
用自增id做主鍵,多表情況下自增id會重複
解決方案
- UUID 性能比較低
- 值比較長
- 導緻索引比較大
- 性能比較低
- snowflake (雪花算法)
- 時間序列
- 機器标志
- 技術順序号
- 一起組成的完成id
- mongoDB
- ObjectId
- zookeeper
- 有序節點,從1開始遞增
- redis自增
- incr
- 資料庫表
- 專門一張表來擷取id
分布式事務問題
多個資料庫表之間保證原子性
性能問題; 網際網路公司用強一緻性分布式事務比較少,一般使用最終一緻性,或者軟事物來解決
分庫分表最難的在于業務的複雜度;
前提: 水準分表的前提是已經存在大量的業務資料。而這個業務資料已經滲透到了各個應用節點
如何權衡目前公司的存儲需要優化
1. 提前規劃(主鍵問題解決、 join問題)
2. 目前資料單表超過1000W、每天的增長量持續上升
Mysql的主從
絕大部分都是寫少讀多的操作,可以做讀寫分離,多個讀庫做壓力釋放
讀庫可以實作負載均衡

資料庫的版本5.7版本
安裝以後檔案對應的目錄
mysql的資料檔案和二進制檔案:
/var/lib/mysql/
mysql的配置檔案:
/etc/my.cnf
mysql的日志檔案:
/var/log/mysql.log
6 為master
- 建立一個使用者
,并且允許其他伺服器可以通過該使用者遠端通路master,通過該使用者去讀取二進制資料,實作資料同步repl
Create user repl identified by 'repl';
repl使用者必須具有REPLICATION SLAVE權限,除此之外其他權限都不需要
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY 'repl' ;
2.修改6
etc/my.cnf
配置檔案,在[mysqld] 下添加如下配置
log-bin=mysql-bin #啟用二進制日志檔案
server-id=6 #伺服器唯一ID
3.重新開機資料庫
systemctl restart mysqld
4.登入到資料庫,通過
show master status
檢視master的狀态資訊
118 為slave
- 修改118 my.cnf配置檔案, 在[mysqld]下增加如下配置
server-id=118 #伺服器id,唯一
relay-log=slave-relay-bin #中繼日志,儲存master同步過來的資訊
relay-log-index=slave-relay-bin.index
read_only=1
- 重新開機資料庫:
systemctl restart mysqld
- 連接配接到資料庫用戶端,通過如下指令建立同步連接配接
master_log_pos
表示從主節點哪個位置開始讀,
master_log_file
這兩個部分從master的
show master status
可以找到對應的值,不能随便寫。
- 執行
start slave
-
show slave status\G;
- 檢視slave伺服器狀态,當如下兩個線程狀态為yes,表示主從複制配置成功
Slave_IO_Running=Yes Slave_SQL_Running=Yes
- 檢視slave伺服器狀态,當如下兩個線程狀态為yes,表示主從複制配置成功
主從同步的原理
- master記錄二進制日志。在每個事務更新資料完成之前,master在二日志記錄這些改變。MySQL将事務串行的寫入二進制日志,即使事務中的語句都是交叉執行的。在事件寫入二進制日志完成後,master通知存儲引擎送出事務
- slave将master的binary log拷貝到它自己的中繼日志。首先,slave開始一個工作線程——I/O線程。I/O線程在master上打開一個普通的連接配接,然後開始binlog dump process。Binlog dump process從master的二進制日志中讀取事件,如果已經跟上master,它會睡眠并等待master産生新的事件。I/O線程将這些事件寫入中繼日志
- SQL線程從中繼日志讀取事件,并重放其中的事件而更新slave的資料,使其與master中的資料一緻
binlog: 用來記錄mysql的資料更新或者潛在更新(update xxx where id=x effect row 0);
檔案内容存儲:
/var/lib/mysql
mysqlbinlog --base64-output=decode-rows -v mysql-bin.000001
檢視binlog的内容
show binlog events in 'mysql-bin.000001'
檢視binlog的日志,不需要看内容
binlog的格式
檢視目前日志模式
show variables like '%log%'
-> binlog_format
statement :
基于sql語句的模式。update table set name =””; effect row 1000; uuid、now() other function
row: (預設)
基于行模式; 存在1000條資料變更; 記錄修改以後每一條記錄變化的值
mixed:
混合模式,由mysql自動判斷處理
修改
binlog_formater
,通過在mysql用戶端輸入如下指令可以修改
set global binlog_format='row/mixed/statement';
或者在
vim /etc/my.cnf
的[mysqld]下增加
binlog_format='mixed'
主從同步的延時問題
一主多從或者雙主
網絡延遲比較大
磁盤的讀寫
主從同步延遲是怎麼産生的
- 當master庫tps比較高的時候,産生的DDL數量超過slave一個sql線程所能承受的範圍,或者slave的大型query語句産生鎖等待
- 網絡傳輸: bin檔案的傳輸延遲
- 磁盤的讀寫耗時:檔案通知更新、磁盤讀取延遲、磁盤寫入延遲
解決方案
- 在資料庫和應用層增加緩存處理,優先從緩存中讀取資料
- 從緩存中取,同步後然後再從slave中取
- 減少slave同步延遲,可以修改slave庫
屬性;sync_binlog
設定為0執行ddlsync_binlog=0
binlog
不會立馬重新整理到檔案中,而是通過檔案系統排程重新整理
檔案系統來排程把
重新整理到磁盤binlog_cache
sync_binlog=n
等于n表示執行n個事物重新整理
- 增加延時監控
做網絡監控Nagios
mk-heartbeat
心跳監控
通過監控做報警
- Mysql的主從配置
- 了解binlog及主從複制原理
MyCat
簡介
位址:http://www.mycat.io/
https://github.com/MyCATApache/Mycat-Server
相當于代理
作用
- 攔截sql
- 分片
- 路由
- 緩存
- 讀寫分離
查詢如果是分片鍵那麼直接落到對應資料庫,如果不是分片鍵,那麼會路由到所有資料庫
haproxy負載均衡
keepalive 高可用
配置檔案
rlue.xml
分片資料庫
對應的rule分片政策
範圍分片
這是範圍分片,0-200M表示到分片5
schema.xml
邏輯資料庫邏輯表
server.xml
配置目前服務
使用
單庫大表拆分
跨庫分表
讀寫分離
高可用
分庫分表雙主(資料雙向同步)政策
- 需要通過haProxy做一個叢集
- 再對haproxy做一個高可用
資料庫分庫分表
在網際網路行業中,最大的特點是并發量高、資料量大;為了應對這兩個特點,後端的技術架構需要使用各種技術來支撐;而這個專題所講的是關于資料庫層面的優化
當資料庫的通路量到達一定的瓶頸的時候,當資料庫單表資料比較大嚴重影響ddl性能的時候。我們應該根據什麼思路去做優化和調整
- 持久化存儲在大型分布式架構下部分需要應對的問題
- 如何去做分庫分表
- 拆分政策
- 分庫分表帶來的問題及解決方案
- 如何知道目前的系統需要做分庫分表
- Mysql的讀寫分離實戰
- Mysql主主複制以及基于keepalived實作雙主高可用
- 基于HAProxy實作
- 主從同步延遲問題及解決方案
- 認識Mycat及Mycat安裝
- Mycat資料切分實戰
- Mycat讀寫分離實戰
- Mycat分片政策
- Mycat全局表配置
centos7安裝mysql5.7操作步驟
下載下傳mysql的repo源
wget http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm
安裝源
rpm -ivh mysql57-community-release-el7-8.noarch.rpm
安裝資料庫
yum install mysql-server
啟動資料庫
systemctl start mysqld
登入到mysql
- 5.7版本預設對于root帳号有一個随機密碼,可以通過
獲得,[email protected]: 此處為随機密碼grep "password" /var/log/mysqld.log
- 運作mysql -uroot -p 回車
- 粘貼随機密碼
- 修改密碼
- 重新開機
Open & Edit
/etc/my.cnf
or
/etc/mysql/my.cnf
, depending on your distro.
Add
skip-grant-tables
under [mysqld]
Restart Mysql
service mysqld restart
You should be able to login to mysql now using the below command
mysql -u root -p
Run mysql>
flush privileges;
Set new password by ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';
Go back to
/etc/my.cnf
and remove/comment
skip-grant-tables
Restart Mysql
service mysqld restart
Now you will be able to login with the new password
mysql -u root -p
操作
- 預設的随機密碼是沒辦法直接對資料庫做操作的,需要修改密碼,然後,5.7版本用了validate_password密碼加強插件,是以在修改密碼的時候絕對不是 123456 能糊弄過去的。需要嚴格按照規範去設定密碼
- 但是,如果想讓密碼簡單點也可以,降低安全政策, 登入到mysql用戶端執行如下兩條指令
set global validate_password_length=1;
set global validate_password_policy=0;
- 這樣就能設定簡單的密碼了,但是密碼長度必須是大于等于4位
賦權操作
預設情況下其他伺服器的用戶端不能直接通路mysql服務端,需要對ip授權
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;