學習總結(jié)
寫這篇文章主要想解一下自己在大數(shù)據(jù)量下寫數(shù)據(jù)或者頻繁寫數(shù)據(jù)的疑問,工作或者和他人閑聊中一般遇到的大數(shù)據(jù)量寫的場景其實不多歹河,多是密集讀的場景,或者大部分情況下的解決方案都比較不徹底,或者比較“臟”妒穴,維護起來比較煩心搪哪,于是不如就花時間把這個問題想一想蛙卤。
分庫分表的原因
分庫分表是一個實施的方案,我們要做分庫分表要解決的問題具體來說是:
要解決數(shù)據(jù)庫寫壓力大的問題噩死;
或者數(shù)據(jù)量大導致讀寫慢的問題颤难;
或者是MySQL集群水平擴展問題;
解決這些問題的辦法并不只有分庫或者分表已维,數(shù)據(jù)量大的問題通過做冷熱數(shù)據(jù)分離也是可以解決的行嗤;業(yè)務密集寫導致機器負載高的問題也是可以通過產(chǎn)品同學和開發(fā)同學一起商量去解決的;數(shù)據(jù)量如果不是很大的情況下垛耳,通過垂直分表也是一個解決問題的辦法栅屏,例如在業(yè)務或架構(gòu)上解耦,不同服務讀取該服務單獨的庫堂鲜,或者單個服務內(nèi)將大表分離為多個表栈雳,業(yè)務端分散寫壓力,自然也都是可以解決問題的缔莲。
這里我們只是來研究討論一下水平擴展下的分庫分表方案和設計哥纫。
分布算法設計/數(shù)據(jù)分布設計
我們接下來遇到的問題是我們要怎么設計我們的數(shù)據(jù)分布,分庫痴奏、分表蛀骇、分區(qū)都是分散數(shù)據(jù)分布的方式,由于單純分區(qū)還是在單臺機器上的配置读拆,所以主要討論的是架構(gòu)上分庫(或是分庫+分表)的實現(xiàn)和方案擅憔。
數(shù)據(jù)的分布一般最常見的有按范圍分和按哈希分,當然能用的不止這兩種檐晕,詳細可以參考MyCat支持的分庫分表方式暑诸。
自定義分布
存一個將ID和庫的Mapping關(guān)系的單獨的記錄庫,分布算法用另外的服務實現(xiàn),分布算法服務可能會迭代个榕,所以這種方式可能適合經(jīng)常變動的業(yè)務啦逆,數(shù)據(jù)分布的關(guān)系自然就被記錄在該mapping表里,實際中可能不太常見笛洛。
缺點是會引入新的單點夏志,也就是引入了該mapping服務的高可用問題。
按范圍分區(qū)間
按范圍區(qū)分在實際應用中很常見苛让,這個范圍字段通常是某唯一 id 或時間字段沟蔑,優(yōu)點是自然增長,不需要考慮以后數(shù)據(jù)規(guī)模再次變大數(shù)據(jù)要重分布的問題狱杰;
缺點也是明顯的瘦材,一般情況下密集訪問的都是最近時間內(nèi)的數(shù)據(jù),密集訪問其實還是集中在最近時間內(nèi)產(chǎn)生的數(shù)據(jù)上仿畸,并發(fā)規(guī)模若再變高依舊存在密集訪問的問題食棕。
按某業(yè)務字段 Hash
通過業(yè)務字段值 Hash 處理后的值分布數(shù)據(jù),這個數(shù)據(jù)分布方式也是很常見的實現(xiàn)方式错沽,比如希望分 N 個庫簿晓,可以按用戶 ID 取模 N ,可以均勻地將用戶相關(guān)的數(shù)據(jù)分布到不同的庫上千埃,若希望在數(shù)據(jù)庫內(nèi)再對表進行劃分憔儿,可以再對該 ID 作 Hash 處理。Hash 算法的設計可能會業(yè)務不同而異因放可,我們可以學習一下美團技術(shù)團隊分庫分表方案上 Hash 算法的設計谒臼。
分庫方案討論
確定我們的業(yè)務的數(shù)據(jù)分布,技術(shù)選型就是接下來很重要的事情耀里,我們了解發(fā)現(xiàn)現(xiàn)在業(yè)界現(xiàn)在分庫分表的實現(xiàn)基本有在業(yè)務側(cè)實現(xiàn)和通過中間件實現(xiàn)的方式蜈缤。我可能還是偏向于用中間件的方式將分庫分表的處理邏輯與業(yè)務剝離開,由運維或者 devops 去單獨維護冯挎,好處是對開發(fā)完全透明底哥,不使得已經(jīng)比較復雜的業(yè)務代碼變得更復雜。
分庫中間件或開源庫調(diào)研
現(xiàn)在業(yè)內(nèi)使用的開源庫或者中間件有多種织堂,包括:Cobar叠艳、TDDL奶陈、Atlas易阳、Sharding-jdbc、MyCat吃粒、kingshard潦俺。
業(yè)務端分庫分表開源庫
Sharding-jdbc:Sharding-jdbc 可能是 Java 系同學的福音,也是經(jīng)常會看到的,已經(jīng)發(fā)展到 ShardingSphere 了事示,有興趣的同學自己去了解吧早像,我們這里不作研究了。
中間件
我們接下來對業(yè)界比較常見的肖爵,或者是我比較感興趣的分庫分表中間件作一下對比或者深入了解卢鹦。
MyCat
mycat 的安裝和啟動方式我們這里就不做討論了,mycat 官方文檔都有描述劝堪。mycat 是用 Java 寫的中間件冀自,前身是或者參考了阿里的內(nèi)部分布式中間件,在官網(wǎng)也能看到其功能介紹秒啦,使用于生產(chǎn)環(huán)境的公司等等熬粗,能看出來技術(shù)功底還是相當靠譜的,說是最常見最靠譜的中間件也不為過余境。與其它中間件一樣驻呐,前面做一層負載均衡,比如用HAProxy等芳来,也能作為一個常見的高可用方案含末。
另外社區(qū)還是相當活躍的,有大神在維護即舌,用于生產(chǎn)環(huán)境比較讓人安心的答渔。具體介紹和操作都可以翻閱官方的文檔,都解釋得非常詳細侥涵。
配置我們可以詳細討論一下沼撕,在結(jié)構(gòu)上有這么幾個概念:
- Schema:邏輯庫,也就是邏輯意義上的數(shù)據(jù)庫芜飘,像是司機信息庫等务豺。
- Table:邏輯表,表會綁定對應的一個或多個 DataNode (邏輯數(shù)據(jù)節(jié)點)嗦明×ぃ可以指定表的分片規(guī)則,不指定會使用默認規(guī)則娶牌。
- DataNode:邏輯數(shù)據(jù)節(jié)點奔浅,該邏輯數(shù)據(jù)節(jié)點還會綁定 DataHost (物理物理數(shù)據(jù)節(jié)點)。
- DataSource或DataHost:定義物理節(jié)點诗良,同時保存物理節(jié)點信息諸如IP汹桦、最大連接數(shù)、heartbeat等鉴裹。
- 分片規(guī)則(rule):也就是我們設計的數(shù)據(jù)分布方式舞骆,數(shù)據(jù)會按該分片規(guī)則分布到對應的節(jié)點上钥弯。有多種默認的分片規(guī)則如哈希、范圍督禽,也可以根據(jù)業(yè)務情況自定義脆霎。
配置文件主要有:
- schema.xml 配置邏輯表及數(shù)據(jù)節(jié)點
- rule.xml 配置分片規(guī)則
- server.xml 配置服務器權(quán)限
可以參考這個實例的 schema.xml 配置,rule.xml 和 server.xml 暫不作展示了:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 數(shù)據(jù)庫配置狈惫,與server.xml中的數(shù)據(jù)庫對應 -->
<schema name="db_person" checkSQLschema="false" sqlMaxLimit="100">
<table name="person" dataNode="dn1" />
<table name="vehicle" dataNode="dn1" />
<table name="images" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2" rule="mod-long" />
</schema>
<!-- 分片配置 -->
<dataNode name="dn1" dataHost="internal-01" database="db_person" />
<dataNode name="dn2" dataHost="internal-02" database="db_person" />
<!-- 物理數(shù)據(jù)庫配置 -->
<dataHost name="internal-01" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="172.190.0.2" url="172.190.0.2:3306" user="root" password="123456">
</writeHost>
</dataHost>
<dataHost name="internal-02" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="172.190.0.3" url="172.190.0.3:3306" user="root" password="123456">
</writeHost>
</dataHost>
</mycat:schema>
MyCat 的官方文檔描述得非常詳細睛蛛,包括 MyCat 使用的網(wǎng)絡 IO 并發(fā)模型都有闡述,如果對 MyCat 有興趣胧谈,閱讀一遍官方文檔是非常有益于理解 MyCat 的玖院。
kingshard
了解 kingshard 是因為 kingshard 是用 go 寫的,在學習上成本會低很多第岖,kingshard 是一位 go 大神維護的难菌,聽說將其使用在生產(chǎn)環(huán)境的公司也有不少,應該也是比較好的一款分庫分表中間件蔑滓,后面有時間我們可以來分析學習一下 kingshard 的具體實現(xiàn)郊酒。
kingshard 的結(jié)構(gòu)或概念相對比較簡單,支持多個表放在單個庫上键袱,后面再擴容在配置上也非常友好燎窘。
配置實例(/etc/ks.yaml):
user_list:
-
user : kingshard
password : kingshard
# the web api server
web_addr: 0.0.0.0:9797
#HTTP Basic Auth
web_user: admin
web_password: admin
log_path: /Users/jerry/log
log_level: debug
log_sql: on
nodes :
-
name : node1
user : root
password : 123456
max_conns_limit : 32
master : 127.0.0.1:3307
# slave represents a real mysql salve server,and the number after '@' is-
# read load weight of this slave.
#slave : 192.168.59.101:3307@2,192.168.59.101:3307@3
down_after_noalive : 32
-
name : node2
user : root
password : 123456
max_conns_limit : 32
master : 127.0.0.1:3308
down_after_noalive: 32
-
name: node3
user: root
password: 123456
master: 127.0.0.1:3309
down_after_noalive: 32
-
name: node4
user: root
password: 123456
master: 127.0.0.1:3310
down_after_noalive: 32
# schema defines sharding rules, the db is the sharding table database.
schema_list :
-
user: kingshard
nodes: [node1,node2,node3,node4]
default: node1
shard:
-
db : db_driver
table: t_join_driver
key: driver_join_id
type: hash
nodes: [node1, node2, node3, node4]
locations: [4,4,4,4]
可以看到配置還是很簡單的,定義節(jié)點( Node )信息蹄咖,以及分庫分表的 schema 信息褐健,如表名、使用哪些節(jié)點澜汤、分庫分表方式(如 hash )蚜迅、數(shù)據(jù)分布等。接下來就是分別搭建每個數(shù)據(jù)庫節(jié)點俊抵,即可啟動谁不。
不過我的客戶端連接 kingshard 上一直連接不上,一直沒找到問題所在徽诲,后面有時間我們可以來學習一下 MySQL 協(xié)議以及 kingshard 的實現(xiàn)刹帕。
Postgres-XL(pgsql)
以上都是使用 MySQL 作為后端數(shù)據(jù)庫服務器的,但是數(shù)據(jù)庫服務器界還有 pgsql 這么個泰斗級的存在谎替,pgsql 功能強大偷溺,如果使用 pgsql 存儲,那么也有已經(jīng)使用于生產(chǎn)的分庫分表方案钱贯,其中一個便是 Postgres-XL挫掏。
Postgres-XL是一個可橫向擴展的開源數(shù)據(jù)庫集群,基于Postgres-XC喷舀,而Postgres-XC又是基于PostgreSql砍濒。PostgreSQL許可證是一種自由開源許可證淋肾,類似于BSD或MIT許可證硫麻。
這里我們只展示一下 Postgres-XL 的架構(gòu)爸邢,權(quán)作記錄。
后結(jié)
我們這里對于分庫分表的學習和討論還是偏于表層的拿愧,對于分庫分表其實一直沒有非掣芎樱“干凈”、從容又高效的解決方案浇辜,具體對每個不同中間件的使用還是要實際中磨合才能真正合適不同的業(yè)務券敌。事實上現(xiàn)在不少大型互聯(lián)網(wǎng)公司的存儲引擎或者方案都是自研的,所以我們在使用開源中間件滿足業(yè)務的同時柳洋,其實更有必要的是研究底層實現(xiàn)待诅,比如什么樣的網(wǎng)絡IO并發(fā)模型是最合適本業(yè)務的、底層存儲引擎是否真的是我們最想要的等等熊镣,因為很有可能分布式數(shù)據(jù)水平擴展問題并沒有簡單粗暴的“銀彈”卑雁。