天天看點

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

分庫分表

  • 關系型資料庫和NoSQL

    非關系型資料庫: key-value: redis 、memcache ;

    面向文檔: mongoDB

    面向列: HBase

    資料切分

    mycat

    TDDL

    Sharding-JDBC

    cobar

  1. 對于存儲層的壓力知道如何去提供解決方案和思路
  2. 對分庫分表的常用手段有全面了解
  3. 了解Mysql的主從及binlog
  4. 知道Mycat及其他相似的中間件

為什麼要分庫分表

超大容量問題

  • 訂單表資料量過大
    • 單表處理能力有瓶頸

性能問題

  • 單一資料庫解決所有應用節點
    • 單一資料庫有性能極限

如何去做到

垂直切分、 水準切分

  1. 垂直分庫
    1. 解決的是表過多的問題
    2. 不同的表放在不同的庫中
      1. 比如說訂單相關的放在訂單庫中
  2. 垂直分表
    1. 解決單表列過多的問題
    2. 列多的表拆分成多個列少的表
      1. 比如說商 品表拆分
        1. 通過關聯關系維持資料

水準切分

  • 大資料表拆成小表

常見的拆分政策

拆分如果全部放在一個庫中,可能會有性能問題。

​ 可能把部分表放在不同的資料庫中

拆分次元選擇的資料非常重要

垂直拆分

​ er分片

水準拆分

  • 一緻性hash
  • 範圍切分
    • 可以按照ID
  • 日期拆分

拆分以後帶來的問題

跨庫join的問題

select a.x ,b.y from a,b on a.id=b.id

  1. 設計的時候考慮到應用層的join問題。
    1. 拆分的時候考慮好
  2. 在服務層去做調用

    A服務裡查詢到一個list

    直接通過接口查詢

/**
	*批量查詢不要這樣使用
**/
for(list){
  bservice.select(list);
}
           
  1. 全局表
    1. 資料變更比較少的基于全局應用的表
    2. 或者抽離公共服務
  2. 做字段備援(空間換時間的做法)

    ​ 訂單表需要展示,商家id 商家名稱(因為訂單表和商家表是一對一的關系),那麼查詢的時候可能每一次都需要為了查詢商家名稱,可以做商家名稱字段備援

    ​ 商家名稱變更解決辦法

    1. 定時任務
    2. 任務通知

跨分片資料排序分頁

​ 在應用層做拼接

唯一主鍵問題

​ 用自增id做主鍵,多表情況下自增id會重複

解決方案

  • UUID 性能比較低
    • 值比較長
    • 導緻索引比較大
    • 性能比較低
  • snowflake (雪花算法)
    • 時間序列
    • 機器标志
    • 技術順序号
    • 一起組成的完成id
  • mongoDB
    • ObjectId
  • zookeeper
    • 有序節點,從1開始遞增
  • redis自增
    • incr
  • 資料庫表
    • 專門一張表來擷取id

分布式事務問題

​ 多個資料庫表之間保證原子性

​ 性能問題; 網際網路公司用強一緻性分布式事務比較少,一般使用最終一緻性,或者軟事物來解決

​ 分庫分表最難的在于業務的複雜度;

​ 前提: 水準分表的前提是已經存在大量的業務資料。而這個業務資料已經滲透到了各個應用節點

如何權衡目前公司的存儲需要優化

1. 提前規劃(主鍵問題解決、 join問題)

2. 目前資料單表超過1000W、每天的增長量持續上升

Mysql的主從

絕大部分都是寫少讀多的操作,可以做讀寫分離,多個讀庫做壓力釋放

讀庫可以實作負載均衡

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

資料庫的版本5.7版本

安裝以後檔案對應的目錄

mysql的資料檔案和二進制檔案:

/var/lib/mysql/

mysql的配置檔案:

/etc/my.cnf

mysql的日志檔案:

/var/log/mysql.log

6 為master

  1. 建立一個使用者

    repl

    ,并且允許其他伺服器可以通過該使用者遠端通路master,通過該使用者去讀取二進制資料,實作資料同步
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

  1. 修改118 my.cnf配置檔案, 在[mysqld]下增加如下配置
server-id=118  #伺服器id,唯一

relay-log=slave-relay-bin #中繼日志,儲存master同步過來的資訊

relay-log-index=slave-relay-bin.index

read_only=1
           
  1. 重新開機資料庫:

    systemctl restart mysqld

  2. 連接配接到資料庫用戶端,通過如下指令建立同步連接配接

master_log_pos

表示從主節點哪個位置開始讀,

master_log_file

這兩個部分從master的

show master status

可以找到對應的值,不能随便寫。

  1. 執行

    start slave

  2. show slave status\G;

    1. 檢視slave伺服器狀态,當如下兩個線程狀态為yes,表示主從複制配置成功
      Slave_IO_Running=Yes
      Slave_SQL_Running=Yes
                 

主從同步的原理

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟
  1. master記錄二進制日志。在每個事務更新資料完成之前,master在二日志記錄這些改變。MySQL将事務串行的寫入二進制日志,即使事務中的語句都是交叉執行的。在事件寫入二進制日志完成後,master通知存儲引擎送出事務
    1. slave将master的binary log拷貝到它自己的中繼日志。首先,slave開始一個工作線程——I/O線程。I/O線程在master上打開一個普通的連接配接,然後開始binlog dump process。Binlog dump process從master的二進制日志中讀取事件,如果已經跟上master,它會睡眠并等待master産生新的事件。I/O線程将這些事件寫入中繼日志
    2. 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'

主從同步的延時問題

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

一主多從或者雙主

網絡延遲比較大

磁盤的讀寫

主從同步延遲是怎麼産生的

  1. 當master庫tps比較高的時候,産生的DDL數量超過slave一個sql線程所能承受的範圍,或者slave的大型query語句産生鎖等待
  2. 網絡傳輸: bin檔案的傳輸延遲
  3. 磁盤的讀寫耗時:檔案通知更新、磁盤讀取延遲、磁盤寫入延遲

解決方案

  1. 在資料庫和應用層增加緩存處理,優先從緩存中讀取資料
    1. 從緩存中取,同步後然後再從slave中取
  2. 減少slave同步延遲,可以修改slave庫

    sync_binlog

    屬性;

    sync_binlog=0

    設定為0執行ddl

    binlog

    不會立馬重新整理到檔案中,而是通過檔案系統排程重新整理

    ​ 檔案系統來排程把

    binlog_cache

    重新整理到磁盤

sync_binlog=n

等于n表示執行n個事物重新整理

  1. 增加延時監控

    Nagios

    做網絡監控

    mk-heartbeat

    心跳監控

    通過監控做報警

  2. Mysql的主從配置
  3. 了解binlog及主從複制原理

MyCat

簡介

位址:http://www.mycat.io/

​ https://github.com/MyCATApache/Mycat-Server

​ 相當于代理

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

作用

  • 攔截sql
  • 分片
  • 路由
  • 緩存
  • 讀寫分離

查詢如果是分片鍵那麼直接落到對應資料庫,如果不是分片鍵,那麼會路由到所有資料庫

haproxy負載均衡

keepalive 高可用

配置檔案

rlue.xml

​ 分片資料庫

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟
分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

對應的rule分片政策

範圍分片

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

這是範圍分片,0-200M表示到分片5

schema.xml

​ 邏輯資料庫邏輯表

server.xml

​ 配置目前服務

使用

單庫大表拆分

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

跨庫分表

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

讀寫分離

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

高可用

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟

分庫分表雙主(資料雙向同步)政策

分庫分表分庫分表如何權衡目前公司的存儲需要優化Mysql的主從MyCat資料庫分庫分表centos7安裝mysql5.7操作步驟
  • 需要通過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

  1. 5.7版本預設對于root帳号有一個随機密碼,可以通過

    grep "password" /var/log/mysqld.log

    獲得,[email protected]: 此處為随機密碼
  2. 運作mysql -uroot -p 回車
  3. 粘貼随機密碼
  4. 修改密碼
  5. 重新開機

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

操作

  1. 預設的随機密碼是沒辦法直接對資料庫做操作的,需要修改密碼,然後,5.7版本用了validate_password密碼加強插件,是以在修改密碼的時候絕對不是 123456 能糊弄過去的。需要嚴格按照規範去設定密碼
  2. 但是,如果想讓密碼簡單點也可以,降低安全政策, 登入到mysql用戶端執行如下兩條指令
set global validate_password_length=1;

set global validate_password_policy=0; 
           
  1. 這樣就能設定簡單的密碼了,但是密碼長度必須是大于等于4位

賦權操作

預設情況下其他伺服器的用戶端不能直接通路mysql服務端,需要對ip授權
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;
FLUSH PRIVILEGES;