分庫分表是為了應對業務系統在高並發,大數據量背景下而對數據存儲進行的優化.
關於分表, 本人使用過SQLSERVER數據庫有分區表, 表分區比起人為按一定策略分表有一定優勢, 而且生產環境中表分區也一直運行良好. sqlserver2000有分區視圖的概念, 而分區視圖實際就是建立在分表基礎上的, 為遵循分表策略的一系列表提供了一個統一的入口.
使用表分區或分表方案各有利弊, 具體還需視情況做權衡.
為什么要分庫分表
- 提高查詢性能
- 容量提升
分庫分表的方法
-
垂直切分
- 垂直分庫: 按照業務領域拆分, 每個庫都存儲了該業務領域內的數據. 這解決了表過多的問題
- 垂直分表: 解決了表中列過多的問題. 避免表過寬導致的查詢性能問題.
-
水平切分
防止表的數據量過大, 拆分的表結構完全相同, 也就是將數據分布到不同的表中, 可以是同一個庫, 也可以是不同庫.
拆分策略
-
垂直拆分: ER(Entity Relationship)分片, 需要注意相關的表拆分到同一個庫, 防止join問題.
-
水平拆分
- 一致性hash(注意節點變化導致的問題)
- 范圍 一般按自增id
- 日期
拆分帶來的問題
-
跨庫join;
解決方案: 設計前盡量考慮; 服務層調用; 使用全局表; 字段冗余;
-
跨表排序
-
唯一主鍵
自增id導致的重復.
UUID: 性能較低
snowflake: 雪花算法
zookeeper,redis,mongoDB
數據庫表 -
分布式事務
互聯網很少使用強一致性分布式事務, 但使用時就必須考慮.
分庫分表的難度在於業務
如何權衡當前公司存儲需要優化
- 提前規划 (主鍵, 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可以提供應用層解決方案