久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

詳解MySQL大表優(yōu)化方案

 WindySky 2017-03-10

當(dāng)MySQL單表記錄數(shù)過大時(shí),增刪改查性能都會急劇下降,,可以參考以下步驟來優(yōu)化:

單表優(yōu)化

除非單表數(shù)據(jù)未來會一直不斷上漲,,否則不要一開始就考慮拆分,拆分會帶來邏輯,、部署,、運(yùn)維的各種復(fù)雜度,,一般以整型值為主的表在千萬級以下,字符串為主的表在五百萬以下是沒有太大問題的,。而事實(shí)上很多時(shí)候MySQL單表的性能依然有不少優(yōu)化空間,,甚至能正常支撐千萬級以上的數(shù)據(jù)量:

字段

  • 盡量使用TINYINT、SMALLINT,、MEDIUM_INT作為整數(shù)類型而非INT,,如果非負(fù)則加上UNSIGNED
  • VARCHAR的長度只分配真正需要的空間
  • 使用枚舉或整數(shù)代替字符串類型
  • 盡量使用TIMESTAMP而非DATETIME,
  • 單表不要有太多字段,,建議在20以內(nèi)
  • 避免使用NULL字段,,很難查詢優(yōu)化且占用額外索引空間
  • 用整型來存IP

索引

  • 索引并不是越多越好,要根據(jù)查詢有針對性的創(chuàng)建,,考慮在WHERE和ORDER BY命令上涉及的列建立索引,,可根據(jù)EXPLAIN來查看是否用了索引還是全表掃描
  • 應(yīng)盡量避免在WHERE子句中對字段進(jìn)行NULL值判斷,否則將導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描
  • 值分布很稀少的字段不適合建索引,,例如"性別"這種只有兩三個(gè)值的字段
  • 字符字段只建前綴索引
  • 字符字段最好不要做主鍵
  • 不用外鍵,,由程序保證約束
  • 盡量不用UNIQUE,由程序保證約束
  • 使用多列索引時(shí)主意順序和查詢條件保持一致,,同時(shí)刪除不必要的單列索引

查詢SQL

  • 可通過開啟慢查詢?nèi)罩緛碚页鲚^慢的SQL
  • 不做列運(yùn)算:SELECT id WHERE age + 1 = 10,,任何對列的操作都將導(dǎo)致表掃描,它包括數(shù)據(jù)庫教程函數(shù),、計(jì)算表達(dá)式等等,,查詢時(shí)要盡可能將操作移至等號右邊
  • sql語句盡可能簡單:一條sql只能在一個(gè)cpu運(yùn)算;大語句拆小語句,減少鎖時(shí)間;一條大sql可以堵死整個(gè)庫
  • 不用SELECT *
  • OR改寫成IN:OR的效率是n級別,,IN的效率是log(n)級別,,in的個(gè)數(shù)建議控制在200以內(nèi)
  • 不用函數(shù)和觸發(fā)器,在應(yīng)用程序?qū)崿F(xiàn)
  • 避免%xxx式查詢
  • 少用JOIN
  • 使用同類型進(jìn)行比較,,比如用'123'和'123'比,,123和123比
  • 盡量避免在WHERE子句中使用!=或<>操作符,否則將引擎放棄使用索引而進(jìn)行全表掃描
  • 對于連續(xù)數(shù)值,,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5
  • 列表數(shù)據(jù)不要拿全表,,要使用LIMIT來分頁,每頁數(shù)量也不要太大

引擎

目前廣泛使用的是MyISAM和InnoDB兩種引擎:

MyISAM

MyISAM引擎是MySQL 5.1及之前版本的默認(rèn)引擎,,它的特點(diǎn)是:

  • 不支持行鎖,,讀取時(shí)對需要讀到的所有表加鎖,寫入時(shí)則對表加排它鎖
  • 不支持事務(wù)
  • 不支持外鍵
  • 不支持崩潰后的安全恢復(fù)
  • 在表有讀取查詢的同時(shí),,支持往表中插入新紀(jì)錄
  • 支持BLOB和TEXT的前500個(gè)字符索引,支持全文索引
  • 支持延遲更新索引,,極大提升寫入性能
  • 對于不會進(jìn)行修改的表,,支持壓縮表,極大減少磁盤空間占用

InnoDB

InnoDB在MySQL 5.5后成為默認(rèn)索引,它的特點(diǎn)是:

  • 支持行鎖,,采用MVCC來支持高并發(fā)
  • 支持事務(wù)
  • 支持外鍵
  • 支持崩潰后的安全恢復(fù)
  • 不支持全文索引

總體來講,,MyISAM適合SELECT密集型的表,而InnoDB適合INSERT和UPDATE密集型的表

系統(tǒng)調(diào)優(yōu)參數(shù)

可以使用下面幾個(gè)工具來做基準(zhǔn)測試:

  • sysbench:一個(gè)模塊化,,跨平臺以及多線程的性能測試工具
  • iibench-mysql:基于 Java 的 MySQL/Percona/MariaDB 索引進(jìn)行插入性能測試工具
  • tpcc-mysql:Percona開發(fā)的TPC-C測試工具

具體的調(diào)優(yōu)參數(shù)內(nèi)容較多,,具體可參考官方文檔,這里介紹一些比較重要的參數(shù):

  • back_log:back_log值指出在MySQL暫時(shí)停止回答新請求之前的短時(shí)間內(nèi)多少個(gè)請求可以被存在堆棧中,。也就是說,,如果MySql的連接數(shù)據(jù)達(dá)到max_connections時(shí),新來的請求將會被存在堆棧中,,以等待某一連接釋放資源,,該堆棧的數(shù)量即back_log,如果等待連接的數(shù)量超過back_log,,將不被授予連接資源,。可以從默認(rèn)的50升至500
  • wait_timeout:數(shù)據(jù)庫連接閑置時(shí)間,,閑置連接會占用內(nèi)存資源,。可以從默認(rèn)的8小時(shí)減到半小時(shí)
  • max_user_connection: 最大連接數(shù),,默認(rèn)為0無上限,,最好設(shè)一個(gè)合理上限
  • thread_concurrency:并發(fā)線程數(shù),設(shè)為CPU核數(shù)的兩倍
  • skip_name_resolve:禁止對外部連接進(jìn)行DNS解析,,消除DNS解析時(shí)間,,但需要所有遠(yuǎn)程主機(jī)用IP訪問
  • key_buffer_size:索引塊的緩存大小,增加會提升索引處理速度,,對MyISAM表性能影響最大,。對于內(nèi)存4G左右,可設(shè)為256M或384M,,通過查詢show status like 'key_read%',,保證key_reads / key_read_requests在0.1%以下最好
  • innodb_buffer_pool_size:緩存數(shù)據(jù)塊和索引塊,對InnoDB表性能影響最大,。通過查詢show status like 'Innodb_buffer_pool_read%',,保證 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests越高越好
  • innodb_additional_mem_pool_size:InnoDB存儲引擎用來存放數(shù)據(jù)字典信息以及一些內(nèi)部數(shù)據(jù)結(jié)構(gòu)的內(nèi)存空間大小,當(dāng)數(shù)據(jù)庫對象非常多的時(shí)候,,適當(dāng)調(diào)整該參數(shù)的大小以確保所有數(shù)據(jù)都能存放在內(nèi)存中提高訪問效率,,當(dāng)過小的時(shí)候,MySQL會記錄Warning信息到數(shù)據(jù)庫的錯(cuò)誤日志中,,這時(shí)就需要該調(diào)整這個(gè)參數(shù)大小
  • innodb_log_buffer_size:InnoDB存儲引擎的事務(wù)日志所使用的緩沖區(qū),,一般來說不建議超過32MB
  • query_cache_size:緩存MySQL中的ResultSet,,也就是一條SQL語句執(zhí)行的結(jié)果集,所以僅僅只能針對select語句,。當(dāng)某個(gè)表的數(shù)據(jù)有任何任何變化,,都會導(dǎo)致所有引用了該表的select語句在Query Cache中的緩存數(shù)據(jù)失效。所以,,當(dāng)我們的數(shù)據(jù)變化非常頻繁的情況下,,使用Query Cache可能會得不償失。根據(jù)命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))進(jìn)行調(diào)整,,一般不建議太大,,256MB可能已經(jīng)差不多了,大型的配置型靜態(tài)數(shù)據(jù)可適當(dāng)調(diào)大.
  • 可以通過命令show status like 'Qcache_%'查看目前系統(tǒng)Query catch使用大小
  • read_buffer_size:MySql讀入緩沖區(qū)大小,。對表進(jìn)行順序掃描的請求將分配一個(gè)讀入緩沖區(qū),,MySql會為它分配一段內(nèi)存緩沖區(qū)。如果對表的順序掃描請求非常頻繁,,可以通過增加該變量值以及內(nèi)存緩沖區(qū)大小提高其性能
  • sort_buffer_size:MySql執(zhí)行排序使用的緩沖大小,。如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段,。如果不能,可以嘗試增加sort_buffer_size變量的大小
  • read_rnd_buffer_size:MySql的隨機(jī)讀緩沖區(qū)大小,。當(dāng)按任意順序讀取行時(shí)(例如,按照排序順序),,將分配一個(gè)隨機(jī)讀緩存區(qū),。進(jìn)行排序查詢時(shí),MySql會首先掃描一遍該緩沖,,以避免磁盤搜索,,提高查詢速度,如果需要排序大量數(shù)據(jù),,可適當(dāng)調(diào)高該值,。但MySql會為每個(gè)客戶連接發(fā)放該緩沖空間,所以應(yīng)盡量適當(dāng)設(shè)置該值,,以避免內(nèi)存開銷過大,。
  • record_buffer:每個(gè)進(jìn)行一個(gè)順序掃描的線程為其掃描的每張表分配這個(gè)大小的一個(gè)緩沖區(qū)。如果你做很多順序掃描,,可能想要增加該值
  • thread_cache_size:保存當(dāng)前沒有與連接關(guān)聯(lián)但是準(zhǔn)備為后面新的連接服務(wù)的線程,,可以快速響應(yīng)連接的線程請求而無需創(chuàng)建新的
  • table_cache:類似于thread_cache_size,但用來緩存表文件,,對InnoDB效果不大,,主要用于MyISAM

升級硬件

Scale up,,這個(gè)不多說了,,根據(jù)MySQL是CPU密集型還是I/O密集型,,通過提升CPU和內(nèi)存、使用SSD,,都能顯著提升MySQL性能

讀寫分離

也是目前常用的優(yōu)化,,從庫讀主庫寫,一般不要采用雙主或多主引入很多復(fù)雜性,,盡量采用文中的其他方案來提高性能,。同時(shí)目前很多拆分的解決方案同時(shí)也兼顧考慮了讀寫分離

緩存

緩存可以發(fā)生在這些層次:

  • MySQL內(nèi)部:在系統(tǒng)調(diào)優(yōu)參數(shù)介紹了相關(guān)設(shè)置
  • 數(shù)據(jù)訪問層:比如MyBatis針對SQL語句做緩存,而Hibernate可以精確到單個(gè)記錄,,這里緩存的對象主要是持久化對象Persistence Object
  • 應(yīng)用服務(wù)層:這里可以通過編程手段對緩存做到更精準(zhǔn)的控制和更多的實(shí)現(xiàn)策略,,這里緩存的對象是數(shù)據(jù)傳輸對象Data Transfer Object
  • Web層:針對web頁面做緩存
  • 瀏覽器客戶端:用戶端的緩存

可以根據(jù)實(shí)際情況在一個(gè)層次或多個(gè)層次結(jié)合加入緩存。這里重點(diǎn)介紹下服務(wù)層的緩存實(shí)現(xiàn),,目前主要有兩種方式:

  • 直寫式(Write Through):在數(shù)據(jù)寫入數(shù)據(jù)庫后,,同時(shí)更新緩存,,維持?jǐn)?shù)據(jù)庫與緩存的一致性。這也是當(dāng)前大多數(shù)應(yīng)用緩存框架如Spring Cache的工作方式,。這種實(shí)現(xiàn)非常簡單,,同步好,,但效率一般。
  • 回寫式(Write Back):當(dāng)有數(shù)據(jù)要寫入數(shù)據(jù)庫時(shí),,只會更新緩存,,然后異步批量的將緩存數(shù)據(jù)同步到數(shù)據(jù)庫上。這種實(shí)現(xiàn)比較復(fù)雜,,需要較多的應(yīng)用邏輯,,同時(shí)可能會產(chǎn)生數(shù)據(jù)庫與緩存的不同步,但效率非常高,。

表分區(qū)

MySQL在5.1版引入的分區(qū)是一種簡單的水平拆分,,用戶需要在建表的時(shí)候加上分區(qū)參數(shù),對應(yīng)用是透明的無需修改代碼

對用戶來說,,分區(qū)表是一個(gè)獨(dú)立的邏輯表,,但是底層由多個(gè)物理子表組成,,實(shí)現(xiàn)分區(qū)的代碼實(shí)際上是通過對一組底層表的對象封裝,但對SQL層來說是一個(gè)完全封裝底層的黑盒子,。MySQL實(shí)現(xiàn)分區(qū)的方式也意味著索引也是按照分區(qū)的子表定義,,沒有全局索引

用戶的SQL語句是需要針對分區(qū)表做優(yōu)化,SQL條件中要帶上分區(qū)條件的列,,從而使查詢定位到少量的分區(qū)上,,否則就會掃描全部分區(qū),可以通過EXPLAIN PARTITIONS來查看某條SQL語句會落在那些分區(qū)上,,從而進(jìn)行SQL優(yōu)化,,如下圖5條記錄落在兩個(gè)分區(qū)上:

mysql> explain partitions select count(1) from user_partition where id in (1,2,3,4,5);

+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |

+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

| 1 | SIMPLE | user_partition | p1,p4 | range | PRIMARY | PRIMARY | 8 | NULL | 5 | Using where; Using index |

+----+-------------+----------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

1 row in set (0.00 sec)

分區(qū)的好處是:

  • 可以讓單表存儲更多的數(shù)據(jù)
  • 分區(qū)表的數(shù)據(jù)更容易維護(hù),可以通過清楚整個(gè)分區(qū)批量刪除大量數(shù)據(jù),,也可以增加新的分區(qū)來支持新插入的數(shù)據(jù),。另外,還可以對一個(gè)獨(dú)立分區(qū)進(jìn)行優(yōu)化,、檢查,、修復(fù)等操作
  • 部分查詢能夠從查詢條件確定只落在少數(shù)分區(qū)上,速度會很快
  • 分區(qū)表的數(shù)據(jù)還可以分布在不同的物理設(shè)備上,,從而搞笑利用多個(gè)硬件設(shè)備
  • 可以使用分區(qū)表賴避免某些特殊瓶頸,,例如InnoDB單個(gè)索引的互斥訪問、ext3文件系統(tǒng)的inode鎖競爭
  • 可以備份和恢復(fù)單個(gè)分區(qū)

分區(qū)的限制和缺點(diǎn):

  • 一個(gè)表最多只能有1024個(gè)分區(qū)
  • 如果分區(qū)字段中有主鍵或者唯一索引的列,,那么所有主鍵列和唯一索引列都必須包含進(jìn)來
  • 分區(qū)表無法使用外鍵約束
  • NULL值會使分區(qū)過濾無效
  • 所有分區(qū)必須使用相同的存儲引擎

分區(qū)的類型:

  • RANGE分區(qū):基于屬于一個(gè)給定連續(xù)區(qū)間的列值,,把多行分配給分區(qū)
  • LIST分區(qū):類似于按RANGE分區(qū),區(qū)別在于LIST分區(qū)是基于列值匹配一個(gè)離散值集合中的某個(gè)值來進(jìn)行選擇
  • HASH分區(qū):基于用戶定義的表達(dá)式的返回值來進(jìn)行選擇的分區(qū),,該表達(dá)式使用將要插入到表中的這些行的列值進(jìn)行計(jì)算,。這個(gè)函數(shù)可以包含MySQL中有效的、產(chǎn)生非負(fù)整數(shù)值的任何表達(dá)式
  • KEY分區(qū):類似于按HASH分區(qū),,區(qū)別在于KEY分區(qū)只支持計(jì)算一列或多列,,且MySQL服務(wù)器提供其自身的哈希函數(shù)。必須有一列或多列包含整數(shù)值

分區(qū)適合的場景有:

  • 最適合的場景數(shù)據(jù)的時(shí)間序列性比較強(qiáng),,則可以按時(shí)間來分區(qū),,如下所示: 
  1. CREATE TABLE members ( 
  2.     firstname VARCHAR(25) NOT NULL, 
  3.     lastname VARCHAR(25) NOT NULL, 
  4.     username VARCHAR(16) NOT NULL, 
  5.     email VARCHAR(35), 
  6.     joined DATE NOT NULL 
  7. PARTITION BY RANGE( YEAR(joined) ) ( 
  8.     PARTITION p0 VALUES LESS THAN (1960), 
  9.     PARTITION p1 VALUES LESS THAN (1970), 
  10.     PARTITION p2 VALUES LESS THAN (1980), 
  11.     PARTITION p3 VALUES LESS THAN (1990), 
  12.     PARTITION p4 VALUES LESS THAN MAXVALUE 
  13. ); 

查詢時(shí)加上時(shí)間范圍條件效率會非常高,同時(shí)對于不需要的歷史數(shù)據(jù)能很容的批量刪除,。

  • 如果數(shù)據(jù)有明顯的熱點(diǎn),,而且除了這部分?jǐn)?shù)據(jù),其他數(shù)據(jù)很少被訪問到,,那么可以將熱點(diǎn)數(shù)據(jù)單獨(dú)放在一個(gè)分區(qū),,讓這個(gè)分區(qū)的數(shù)據(jù)能夠有機(jī)會都緩存在內(nèi)存中,查詢時(shí)只訪問一個(gè)很小的分區(qū)表,能夠有效使用索引和緩存

另外MySQL有一種早期的簡單的分區(qū)實(shí)現(xiàn) - 合并表(merge table),,限制較多且缺乏優(yōu)化,,不建議使用,應(yīng)該用新的分區(qū)機(jī)制來替代

垂直拆分

垂直分庫是根據(jù)數(shù)據(jù)庫里面的數(shù)據(jù)表的相關(guān)性進(jìn)行拆分,,比如:一個(gè)數(shù)據(jù)庫里面既存在用戶數(shù)據(jù),,又存在訂單數(shù)據(jù),那么垂直拆分可以把用戶數(shù)據(jù)放到用戶庫,、把訂單數(shù)據(jù)放到訂單庫,。垂直分表是對數(shù)據(jù)表進(jìn)行垂直拆分的一種方式,常見的是把一個(gè)多字段的大表按常用字段和非常用字段進(jìn)行拆分,,每個(gè)表里面的數(shù)據(jù)記錄數(shù)一般情況下是相同的,只是字段不一樣,,使用主鍵關(guān)聯(lián)

比如原始的用戶表是:

垂直拆分后是:

垂直拆分的優(yōu)點(diǎn)是:

  • 可以使得行數(shù)據(jù)變小,,一個(gè)數(shù)據(jù)塊(Block)就能存放更多的數(shù)據(jù),在查詢時(shí)就會減少I/O次數(shù)(每次查詢時(shí)讀取的Block 就少)
  • 可以達(dá)到最大化利用Cache的目的,,具體在垂直拆分的時(shí)候可以將不常變的字段放一起,,將經(jīng)常改變的放一起
  • 數(shù)據(jù)維護(hù)簡單

缺點(diǎn)是:

  • 主鍵出現(xiàn)冗余,需要管理冗余列
  • 會引起表連接JOIN操作(增加CPU開銷)可以通過在業(yè)務(wù)服務(wù)器上進(jìn)行join來減少數(shù)據(jù)庫壓力
  • 依然存在單表數(shù)據(jù)量過大的問題(需要水平拆分)
  • 事務(wù)處理復(fù)雜

水平拆分

概述

水平拆分是通過某種策略將數(shù)據(jù)分片來存儲,,分庫內(nèi)分表和分庫兩部分,,每片數(shù)據(jù)會分散到不同的MySQL表或庫,達(dá)到分布式的效果,,能夠支持非常大的數(shù)據(jù)量,。前面的表分區(qū)本質(zhì)上也是一種特殊的庫內(nèi)分表

庫內(nèi)分表,僅僅是單純的解決了單一表數(shù)據(jù)過大的問題,,由于沒有把表的數(shù)據(jù)分布到不同的機(jī)器上,,因此對于減輕MySQL服務(wù)器的壓力來說,并沒有太大的作用,,大家還是競爭同一個(gè)物理機(jī)上的IO,、CPU、網(wǎng)絡(luò),,這個(gè)就要通過分庫來解決

前面垂直拆分的用戶表如果進(jìn)行水平拆分,,結(jié)果是:

實(shí)際情況中往往會是垂直拆分和水平拆分的結(jié)合,即將Users_A_M和Users_N_Z再拆成Users和UserExtras,,這樣一共四張表

水平拆分的優(yōu)點(diǎn)是:

  • 不存在單庫大數(shù)據(jù)和高并發(fā)的性能瓶頸
  • 應(yīng)用端改造較少
  • 提高了系統(tǒng)的穩(wěn)定性和負(fù)載能力

缺點(diǎn)是:

  • 分片事務(wù)一致性難以解決
  • 跨節(jié)點(diǎn)Join性能差,,邏輯復(fù)雜
  • 數(shù)據(jù)多次擴(kuò)展難度跟維護(hù)量極大

分片原則

  • 能不分就不分,參考單表優(yōu)化
  • 分片數(shù)量盡量少,,分片盡量均勻分布在多個(gè)數(shù)據(jù)結(jié)點(diǎn)上,,因?yàn)橐粋€(gè)查詢SQL跨分片越多,則總體性能越差,,雖然要好于所有數(shù)據(jù)在一個(gè)分片的結(jié)果,,只在必要的時(shí)候進(jìn)行擴(kuò)容,,增加分片數(shù)量
  • 分片規(guī)則需要慎重選擇做好提前規(guī)劃,分片規(guī)則的選擇,,需要考慮數(shù)據(jù)的增長模式,,數(shù)據(jù)的訪問模式,分片關(guān)聯(lián)性問題,,以及分片擴(kuò)容問題,,最近的分片策略為范圍分片,枚舉分片,,一致性Hash分片,,這幾種分片都有利于擴(kuò)容
  • 盡量不要在一個(gè)事務(wù)中的SQL跨越多個(gè)分片,分布式事務(wù)一直是個(gè)不好處理的問題
  • 查詢條件盡量優(yōu)化,,盡量避免Select * 的方式,,大量數(shù)據(jù)結(jié)果集下,會消耗大量帶寬和CPU資源,,查詢盡量避免返回大量結(jié)果集,,并且盡量為頻繁使用的查詢語句建立索引。
  • 通過數(shù)據(jù)冗余和表分區(qū)賴降低跨庫Join的可能

這里特別強(qiáng)調(diào)一下分片規(guī)則的選擇問題,,如果某個(gè)表的數(shù)據(jù)有明顯的時(shí)間特征,,比如訂單、交易記錄等,,則他們通常比較合適用時(shí)間范圍分片,,因?yàn)榫哂袝r(shí)效性的數(shù)據(jù),我們往往關(guān)注其近期的數(shù)據(jù),,查詢條件中往往帶有時(shí)間字段進(jìn)行過濾,,比較好的方案是,當(dāng)前活躍的數(shù)據(jù),,采用跨度比較短的時(shí)間段進(jìn)行分片,,而歷史性的數(shù)據(jù),則采用比較長的跨度存儲,。

總體上來說,,分片的選擇是取決于最頻繁的查詢SQL的條件,因?yàn)椴粠魏蜽here語句的查詢SQL,,會遍歷所有的分片,,性能相對最差,因此這種SQL越多,,對系統(tǒng)的影響越大,,所以我們要盡量避免這種SQL的產(chǎn)生。

解決方案

由于水平拆分牽涉的邏輯比較復(fù)雜,當(dāng)前也有了不少比較成熟的解決方案,。這些方案分為兩大類:客戶端架構(gòu)和代理架構(gòu),。

客戶端架構(gòu)

通過修改數(shù)據(jù)訪問層,如JDBC,、Data Source,、MyBatis,通過配置來管理多個(gè)數(shù)據(jù)源,,直連數(shù)據(jù)庫,,并在模塊內(nèi)完成數(shù)據(jù)的分片整合,一般以Jar包的方式呈現(xiàn)

這是一個(gè)客戶端架構(gòu)的例子:

可以看到分片的實(shí)現(xiàn)是和應(yīng)用服務(wù)器在一起的,,通過修改Spring JDBC層來實(shí)現(xiàn)

客戶端架構(gòu)的優(yōu)點(diǎn)是:

  • 應(yīng)用直連數(shù)據(jù)庫,,降低外圍系統(tǒng)依賴所帶來的宕機(jī)風(fēng)險(xiǎn)
  • 集成成本低,無需額外運(yùn)維的組件

缺點(diǎn)是:

  • 限于只能在數(shù)據(jù)庫訪問層上做文章,,擴(kuò)展性一般,,對于比較復(fù)雜的系統(tǒng)可能會力不從心
  • 將分片邏輯的壓力放在應(yīng)用服務(wù)器上,造成額外風(fēng)險(xiǎn)

代理架構(gòu)

通過獨(dú)立的中間件來統(tǒng)一管理所有數(shù)據(jù)源和數(shù)據(jù)分片整合,,后端數(shù)據(jù)庫集群對前端應(yīng)用程序透明,需要獨(dú)立部署和運(yùn)維代理組件

這是一個(gè)代理架構(gòu)的例子:

代理組件為了分流和防止單點(diǎn),,一般以集群形式存在,,同時(shí)可能需要Zookeeper之類的服務(wù)組件來管理

代理架構(gòu)的優(yōu)點(diǎn)是:

  • 能夠處理非常復(fù)雜的需求,不受數(shù)據(jù)庫訪問層原來實(shí)現(xiàn)的限制,,擴(kuò)展性強(qiáng)
  • 對于應(yīng)用服務(wù)器透明且沒有增加任何額外負(fù)載

缺點(diǎn)是:

  • 需部署和運(yùn)維獨(dú)立的代理中間件,,成本高
  • 應(yīng)用需經(jīng)過代理來連接數(shù)據(jù)庫,網(wǎng)絡(luò)上多了一跳,,性能有損失且有額外風(fēng)險(xiǎn)

各方案比較

  出品方 架構(gòu)模型 支持?jǐn)?shù)據(jù)庫 分庫 分表 讀寫分離 外部依賴 是否開源 實(shí)現(xiàn)語言 支持語言 最后更新 Github星數(shù)
MySQL Fabric MySQL官方 代理架構(gòu) MySQL python 無限制 4個(gè)月前 35
Cobar 阿里巴巴 代理架構(gòu) MySQL Java 無限制 兩年前 1287
Cobar Client 阿里巴巴 客戶端架構(gòu) MySQL Java Java 三年前 344
TDDL 淘寶 客戶端架構(gòu) 無限制 Diamond 只開源部分 Java Java 未知 519
Atlas 奇虎360 代理架構(gòu) MySQL C 無限制 10個(gè)月前 1941
Heisenberg 百度熊照 代理架構(gòu) MySQL Java 無限制 2個(gè)月前 197
TribeDB 個(gè)人 代理架構(gòu) MySQL NodeJS 無限制 3個(gè)月前 126
ShardingJDBC 當(dāng)當(dāng) 客戶端架構(gòu) MySQL Java Java 當(dāng)天 1144
Shark 個(gè)人 客戶端架構(gòu) MySQL Java Java 兩天前 84
KingShard 個(gè)人 代理架構(gòu) MySQL Golang 無限制 兩天前 1836
OneProxy 平民軟件 代理架構(gòu) MySQL 未知 無限制 未知 未知
MyCat 社區(qū) 代理架構(gòu) MySQL Java 無限制 兩天前 1270
Vitess Youtube 代理架構(gòu) MySQL Golang 無限制 當(dāng)天 3636
Mixer 個(gè)人 代理架構(gòu) MySQL Golang 無限制 9個(gè)月前 472
JetPants Tumblr 客戶端架構(gòu) MySQL Ruby Ruby 10個(gè)月前 957
HibernateShard Hibernate 客戶端架構(gòu) 無限制 Java Java 4年前 57
MybatisShard MakerSoft 客戶端架構(gòu) 無限制 Java Java 11個(gè)月前 119
Gizzard Twitter 代理架構(gòu) 無限制 Java 無限制 3年前 2087
 

如此多的方案,如何進(jìn)行選擇?可以按以下思路來考慮:

  1. 確定是使用代理架構(gòu)還是客戶端架構(gòu)。中小型規(guī)?;蚴潜容^簡單的場景傾向于選擇客戶端架構(gòu),,復(fù)雜場景或大規(guī)模系統(tǒng)傾向選擇代理架構(gòu)
  2. 具體功能是否滿足,比如需要跨節(jié)點(diǎn)ORDER BY,,那么支持該功能的優(yōu)先考慮
  3. 不考慮一年內(nèi)沒有更新的產(chǎn)品,,說明開發(fā)停滯,甚至無人維護(hù)和技術(shù)支持
  4. 最好按大公司->社區(qū)->小公司->個(gè)人這樣的出品方順序來選擇
  5. 選擇口碑較好的,,比如github星數(shù),、使用者數(shù)量質(zhì)量和使用者反饋
  6. 開源的優(yōu)先,往往項(xiàng)目有特殊需求可能需要改動源代碼

按照上述思路,,推薦以下選擇:

  • 客戶端架構(gòu)
  • 代理架構(gòu)

兼容MySQL且可水平擴(kuò)展的數(shù)據(jù)庫

目前也有一些開源數(shù)據(jù)庫兼容MySQL協(xié)議,,如:

  • TiDB
  • Cubrid

但其工業(yè)品質(zhì)和MySQL尚有差距,且需要較大的運(yùn)維投入,如果想將原始的MySQL遷移到可水平擴(kuò)展的新數(shù)據(jù)庫中,,可以考慮一些云數(shù)據(jù)庫:

  • 阿里云PetaData
  • 阿里云OceanBase
  • 騰訊云DCDB

NoSQL

在MySQL上做Sharding是一種戴著鐐銬的跳舞,,事實(shí)上很多大表本身對MySQL這種RDBMS的需求并不大,并不要求ACID,,可以考慮將這些表遷移到NoSQL,,徹底解決水平擴(kuò)展問題,例如:

  • 日志類,、監(jiān)控類,、統(tǒng)計(jì)類數(shù)據(jù)
  • 非結(jié)構(gòu)化或弱結(jié)構(gòu)化數(shù)據(jù)
  • 對事務(wù)要求不強(qiáng),且無太多關(guān)聯(lián)操作的數(shù)據(jù)

【編輯推薦】

【責(zé)任編輯:枯木 TEL:(010)68476606】

點(diǎn)贊 6

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多