1. 程式人生 > >分布式系列十四: 分庫分表

分布式系列十四: 分庫分表

state rep 設置 過多 記錄 切分 uuid 調用 nag

分庫分表是為了應對業務系統在高並發,大數據量背景下而對數據存儲進行的優化.

關於分表, 本人使用過SQLSERVER數據庫有分區表, 表分區比起人為按一定策略分表有一定優勢, 而且生產環境中表分區也一直運行良好. sqlserver2000有分區視圖的概念, 而分區視圖實際就是建立在分表基礎上的, 為遵循分表策略的一系列表提供了一個統一的入口.

使用表分區或分表方案各有利弊, 具體還需視情況做權衡.

為什麽要分庫分表

  • 提高查詢性能
  • 容量提升

分庫分表的方法

  • 垂直切分

    1. 垂直分庫: 按照業務領域拆分, 每個庫都存儲了該業務領域內的數據. 這解決了表過多的問題
    2. 垂直分表: 解決了表中列過多的問題. 避免表過寬導致的查詢性能問題.
  • 水平切分

    防止表的數據量過大, 拆分的表結構完全相同, 也就是將數據分布到不同的表中, 可以是同一個庫, 也可以是不同庫.

拆分策略

  • 垂直拆分: ER(Entity Relationship)分片, 需要註意相關的表拆分到同一個庫, 防止join問題.

  • 水平拆分

    1. 一致性hash(註意節點變化導致的問題)
    2. 範圍 一般按自增id
    3. 日期

拆分帶來的問題

  1. 跨庫join;

    解決方案: 設計前盡量考慮; 服務層調用; 使用全局表; 字段冗余;

  2. 跨表排序

  3. 唯一主鍵

    自增id導致的重復.
    UUID: 性能較低
    snowflake: 雪花算法
    zookeeper,redis,mongoDB
    數據庫表

  4. 分布式事務

    互聯網很少使用強一致性分布式事務, 但使用時就必須考慮.

分庫分表的難度在於業務

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

  • 提前規劃 (主鍵, join問題提前解決)
  • 單表數據超過1000w, 且還在增長

表分區的缺點

  • 分區字段不靈活, 可能導致表鎖
  • 關聯查詢的性能可能不高
  • 自己分庫分表有更大靈活性, 表分區將查詢執行計劃交給mysql, 對開發人員透明, 可能不好優化.

MySql 主從

可參看這篇文章

針對寫少讀多的情況. 可以配置多個只讀從庫, 使用HaProxy做負載均衡.

安裝MySql

apt-get install mysql-server 安裝最新版本的mysql
service mysql start

服務方式啟動 或者轉到目錄/usr/bin使用 ./mysqld_safe &啟動
service mysql stop 關閉, 或者使用mysqladmin -u root shutdown

GRANT ALL PRIVILEAGES ON *.* TO ‘root‘@‘%‘ INDENTIFIED BY ‘root‘ WITH GRANT OPTION 授權外網訪問

主從配置

從節點創建用戶 create user repl identified by ‘repl‘
從節點授權 grant replication slave on *.* to ‘repl‘@‘%‘ identified by ‘repl‘

mysql的數據文件和二進制文件: /var/lib/mysql/
mysql配置文件: /etc/mysql/my.cnf
mysql的日誌文件: /var/log/mysql/mysql.log

配置文件中my.cnf中:

主配置:

log-bin=mysql-bin  //開啟日誌文件
server.id=123  //唯一id

show master status; 可以查看文件名稱

從配置:

server.id=124
relay-log=slave-relay-bin  //打開中繼日誌
relay-log-index=slave-relay-bin.index
read-only=1 //只讀

從節點指定主服務器節點:

change master to master_host=‘192.168.11.123‘,master_port=3306,master_user=‘repl‘,master_password=‘repl‘,master_log_file=‘mysql.bin.000001‘,master_log_pos=154;

master_log_file=‘mysql.bin.000001‘,master_log_pos=154;就是使用show master status;查詢到的信息.

從節點啟動slave: start slave;
從節點查看狀態: show slave status;

主從同步原理

Slave 中有兩個線程, IO和SQL, 分別用來同步日誌文件和執行sql.

master -> 寫binlog -> slave IO/Thread -> replylog -> SQL/Thread -> slave DB

mysqlbinlog --base64-output=decode-rows -v mysql-bin.00001 用來查看binlog日誌文件內容

日誌文件的存儲與kafka的日誌優點類似, 順序存儲, 分文件存儲.

binlog文件的格式:

  • statement 基於sql語句, 如update A set name=name+‘-‘; effect row 1000
  • row 基於行模式, 存在1000條數據變更, 記錄變化的值 默認為row
  • mixed 混合模式, mysql自行處理.

show binlog events in ‘mysql-bin.00001‘ 查看日誌文件的事件
show variablees like ‘%log%‘ //查看日誌模式 statement row mixed
set global binlog_format=‘minxed‘ //設置模式 或者在配置文件中指定binlog_format=minxed

雙主

都可以寫數據, 可能存在數據不一致.

主從同步的問題

  • 數據同步延時, 大量數據同步, 網絡問題, IO阻塞
  • 延時監控: Nagios, mk-heartbeat
    redis可以提供應用層解決方案

分布式系列十四: 分庫分表