W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
先在這里感謝phalapi框架創(chuàng)始人@dogstar,為我們提供了這樣一個(gè)優(yōu)秀的開(kāi)源框架.
編寫(xiě)本次拓展出于的目的是解決大量數(shù)據(jù)寫(xiě)入分析的問(wèn)題,也希望本拓展能對(duì)大家有些幫助,能夠解決大家遇到的同樣的問(wèn)題.
注:V0.1bate版本,很多功能尚不完善,只提供技術(shù)交流使用,請(qǐng)不要用戶生產(chǎn)環(huán)境
附上:
官網(wǎng)地址:http://www.phalapi.net/
開(kāi)源中國(guó)Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release
說(shuō)到為什么寫(xiě)這個(gè)拓展,起因是這樣的,在和產(chǎn)品交流的時(shí)候他們希望可以存一些東西作為數(shù)據(jù)分析用,我考慮過(guò)hadoop但是如果說(shuō)使用hadoop需要投入的成本太高了,在想有沒(méi)有什么好辦法的時(shí)候,想到了分表分庫(kù)解決數(shù)據(jù)量大的問(wèn)題,那么可以有一個(gè)封裝好的服務(wù)就和操作數(shù)據(jù)庫(kù)一樣操作可以達(dá)到良好的分表分庫(kù)的效果嗎,出于這個(gè)考慮就開(kāi)始這個(gè)拓展的編寫(xiě).
大量select
當(dāng)一個(gè)數(shù)據(jù)庫(kù)需要對(duì)付大量的select請(qǐng)求的時(shí)候,我們往往會(huì)想到使用讀寫(xiě)分離來(lái)解決此類問(wèn)題,一個(gè)寫(xiě)庫(kù)多個(gè)讀庫(kù),一臺(tái)或多臺(tái)服務(wù)器用一個(gè)讀庫(kù),所有的寫(xiě)入操作使用主庫(kù)操作,應(yīng)為是大量的select操作,讀的壓力被分配到了很多個(gè)讀庫(kù)實(shí)例,可以很好的解決問(wèn)題大量select的問(wèn)題,再者就是進(jìn)行添加緩存機(jī)制的優(yōu)化,這樣也是能很好的解決問(wèn)題
大量的insert
對(duì)于大量insert上面所謂的讀寫(xiě)分離完全不夠看了,所有的壓力全部會(huì)集中在負(fù)責(zé)寫(xiě)入的主庫(kù),但并不是應(yīng)為并發(fā)請(qǐng)求的問(wèn)題,問(wèn)題是在于數(shù)據(jù)量大導(dǎo)致不管是干嘛都會(huì)慢,當(dāng)數(shù)據(jù)量到了上億的級(jí)別簡(jiǎn)直不敢想像,如果是通過(guò)分表分庫(kù)(如果是4庫(kù)4表也就是16張表),數(shù)據(jù)分均衡的分配到(庫(kù)數(shù)量-乘-表數(shù)量)這么多張表里面從而達(dá)到解決大量數(shù)據(jù)的問(wèn)題(在分表分庫(kù)前面有一個(gè)主表),當(dāng)然他也有缺陷就是當(dāng)進(jìn)行條件查詢的時(shí)候最壞的條件會(huì)遍歷(庫(kù)數(shù)量-乘-表數(shù)量)這么多張表才能獲得想要的結(jié)果,所以不是很建議用到查詢列表比較平凡的應(yīng)用中,當(dāng)然結(jié)合緩存和讀寫(xiě)分離可以緩解壓力
大家可以到Git項(xiàng)目PhalApi Library下載拓展文件,把其中的DB_Cluster文件夾復(fù)制到/PhalApi/Library目錄下,如下圖:
把其中的Config中的cluster.php文件放到默認(rèn)的Config配置文件中
然后在init.php中注冊(cè)以下兩句話
//初始化配置文件 DI()->Cluster_DB = new Cluster_Lite(DI()->config->get('cluster'));
然后把框架自帶的Demo文件替換成拓展自帶的Demo文件如下就完成了第一步
這里使用Mysql作為集群的數(shù)據(jù)庫(kù)
大家可以看到拓展文件里面有一個(gè)Data/user_cluster.sql 文件,里面有一個(gè) user_base的建表語(yǔ)句和另外user0,user1,user2,user3這四個(gè)表的建表語(yǔ)句
在文件里面有一些注意事項(xiàng)這里這里再次強(qiáng)調(diào)一下
--本次集群采取4庫(kù)每一庫(kù)4表 4*4共16表的mysql集群(基礎(chǔ)庫(kù)不算在里面) --基礎(chǔ)庫(kù)(id自增長(zhǎng),用表索引進(jìn)行列表查詢條件) --庫(kù)名project --當(dāng)自己建立集群mysql的時(shí)候要注意以下幾點(diǎn) --1.一定要注意ID要加上自動(dòng)增長(zhǎng),這里進(jìn)行的分表分庫(kù)都是基于自增ID進(jìn)行的,如果是自定義字符串ID需要進(jìn)行算法修改,也可以使用其他緩存生成自增ID --2.除了ID之外的字段(用于按條件查詢列表ID)一定要加上索引或者是主鍵,不然數(shù)據(jù)量大的時(shí)候獲取列表ID會(huì)很慢 --3.除了ID之外的字段一定要是更具業(yè)務(wù)需求進(jìn)行查詢比較頻繁的,而且要保持盡量的少1-2個(gè),大于2個(gè)建議在分出一張表做對(duì)應(yīng) --庫(kù)名分表為user_cluster0,user_cluster1,user_cluster2,user_cluster3(可自定) --下面四張表為每一個(gè)庫(kù)中都擁有的4張表(注意ID不能使用自動(dòng)增長(zhǎng)) --表名可以自定但是每個(gè)庫(kù)中的表名一定要統(tǒng)一 --user0,user1,user2,user3
我這里使用結(jié)構(gòu)如下(大家可以自由的配置可以2庫(kù)+2表,2庫(kù)+4表等都行,只需在配置文件中配置就可)
數(shù)據(jù)庫(kù)project -user_base表 數(shù)據(jù)庫(kù)user_cluster0,user_cluster1,user_cluster2,user_cluster3 都有以下表 -user0,user1,user2,user3
我們需在在默認(rèn)dbs.php 數(shù)據(jù)庫(kù)配置中配置鏈接好project庫(kù)
然后大家看向cluster.php集群配置文件按照注釋配置好自己的數(shù)據(jù)庫(kù),如果沒(méi)有多個(gè)mysql實(shí)例,可以一個(gè)實(shí)例建立4個(gè)庫(kù)模擬4個(gè)mysql分布式集群.
這里指的著重講一下的是以下配置問(wèn)題
/** * 配置表 */ 'cluster' => array( //集群分布配置 'list' => array( 'demo' => array( //使用demo集群配置最大ID和最小ID,最大ID為0等于不上限 'id_min' => 0, 'id_max' => 0, ), ), //where查詢條件放到衍生表中的字段 'where' => array( 'city' ), //ID名稱 'id_name' => 'uId', ),
在list中可以配置多個(gè)集群數(shù)組KEY的名稱對(duì)應(yīng)配置文件上面demo集群并且可以設(shè)定ID范圍,做這個(gè)設(shè)計(jì)主要是為了當(dāng)我有一個(gè)2庫(kù)*2表的集群,已經(jīng)承載了1個(gè)億的數(shù)據(jù)了,已經(jīng)無(wú)法承擔(dān)數(shù)據(jù)量了這個(gè)時(shí)候就要更換集群,在這里只需要吧demo的id_max配置成1億,在配置一個(gè)demo1然后把id_min設(shè)定到1億,當(dāng)ID大于1億了之后就會(huì)自己找到第二集群插入數(shù)據(jù)了(不用擔(dān)心多集群了之后查詢以及其他操作這里已經(jīng)做好了兼容)
還有where屬性,這里的where用于配置在user_base表中除了ID之外的索引字段能夠增加查詢的性能,但是盡量少應(yīng)為這個(gè)會(huì)減少base表的性能,可以適當(dāng)?shù)娜∩?/p>
大家看向Demo的API文件中有四個(gè)接口select,delete,update,insert里面的參數(shù)都是隨機(jī)生成的
在看向Cluster/User.php里面繼承了Cluster_DB需要使用數(shù)據(jù)庫(kù)集群就需要集成這個(gè)類并且實(shí)現(xiàn)以下兩個(gè)方法
/** * 獲取集群實(shí)例類 */ public function getCluster(){ return DI()->Cluster_DB; } /** * 獲取主數(shù)據(jù)庫(kù)表實(shí)例 */ public function getMainDB(){ return DI()->notorm->user_base; }
getCluster方法返回在init.php中注冊(cè)DI()->Cluster_DB即可,因?yàn)橐粋€(gè)集群對(duì)應(yīng)一張表可以根據(jù)需求使用不通的集群實(shí)例
getMainDB方法是為了獲取base表的實(shí)例只需要把表實(shí)例返回即可
當(dāng)做好這幾件事情大家就可以嘗試請(qǐng)求接口看看結(jié)果了
實(shí)現(xiàn)架構(gòu)思維
我在開(kāi)始寫(xiě)這個(gè)拓展之前在想要讓使用者如何去使用這個(gè)框架,怎么讓使用者最方便,最后的到的答案是如果可以和正常使用Model層一樣去使用的話是最好的,所以大家可以看到在Demo/Cluster/User.php中增刪改查和正常使用基本沒(méi)有區(qū)別.
分表分庫(kù)算法
當(dāng)我們是2庫(kù)2表的情況下,我們用2*2=4然后用我們獲取的ID比如55,用55%2*2 就會(huì)得到一個(gè)小于4的數(shù)字,55得到的是3,用3/表數(shù)2=1.5取整是1表,然后用3%表數(shù)2=1,也就是存入1庫(kù)1表(注意是從0開(kāi)始算的)
因?yàn)槲覀兊耐卣故切枰谝粋€(gè)base表實(shí)現(xiàn)ID增長(zhǎng)和where語(yǔ)句查詢?cè)诜值郊簬?kù),所以base庫(kù)需要應(yīng)付的量比較大所以這里對(duì)base表進(jìn)行了一次針對(duì)于不同數(shù)據(jù)量進(jìn)行的單ID查詢和where查詢基準(zhǔn)測(cè)試
300w數(shù)據(jù):
5700w數(shù)據(jù):
1.3億數(shù)據(jù):
明顯可以看出來(lái)隨著數(shù)據(jù)量的增加查詢速度有明顯的降低,但是到了億級(jí)的時(shí)候還能維持到where條件查詢不上0.1秒的情況還是比較理想的,最關(guān)鍵的是在億級(jí)的時(shí)候插入還是相當(dāng)快的所以非常適合,大量數(shù)據(jù)的寫(xiě)入,如果是對(duì)查詢有比較大的要求的童鞋可以考慮吧5000W作為一個(gè)分界點(diǎn)對(duì)基礎(chǔ)base進(jìn)行劃分(后期將會(huì)把此功能集成到拓展內(nèi)部)
應(yīng)為工作量比較大還在進(jìn)行測(cè)試中!
在此希望本擴(kuò)展能給大家?guī)?lái)解決實(shí)際問(wèn)題的思路,第一版是bate版本請(qǐng)不要使用在生產(chǎn)環(huán)境中,如果出現(xiàn)問(wèn)題或者是有BUG可以直接聯(lián)系我QQ591235675也可加入PhalApi交流群一同交流探討
注:筆者能力有限有說(shuō)的不對(duì)的地方希望大家能夠指出,也希望多多交流!
官網(wǎng)QQ交流群:421032344 歡迎大家的加入!
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: