//寫入數(shù)據(jù)的示例偽代碼 //data為我們要存儲的數(shù)據(jù)對象 data.title=”title”;
data.name=”name”;
data.time=”2009-12-01 10:10:01”;
data.from=”1”;
id=DB.Insert(data);//寫入MySQL數(shù)據(jù)庫
NoSQL.Add(id,data);//以寫入MySQL產(chǎn)生的自增id為主鍵寫入NoSQL數(shù)據(jù)庫
復(fù)制代碼
如果有數(shù)據(jù)一致性要求,可以像如下的方式使用
//寫入數(shù)據(jù)的示例偽代碼 //data為我們要存儲的數(shù)據(jù)對象
bool status=false;
DB.startTransaction();//開始事務(wù)
id=DB.Insert(data);//寫入MySQL數(shù)據(jù)庫
if(id>0){
status=NoSQL.Add(id,data);//以寫入MySQL產(chǎn)生的自增id為主鍵寫入NoSQL數(shù)據(jù)庫 }
if(id>0 && status==true){
DB.commit();//提交事務(wù) }else{
DB.rollback();//不成功,進行回滾 }
復(fù)制代碼
上面的代碼看起來可能覺得有點麻煩,但是只需要在DB類或者ORM層做一個統(tǒng)一的封裝,就能實現(xiàn)重用了,其他代碼都不用做任何的修改。
這種架構(gòu)在原有基于MySQL數(shù)據(jù)庫的架構(gòu)上增加了一層輔助的NoSQL存儲,代碼量不大,技術(shù)難度小,卻在可擴展性和性能上起到了非常大的作用。只需要程序在寫入MySQL數(shù)據(jù)庫后,同時寫入到NoSQL數(shù)據(jù)庫,讓MySQL和NoSQL擁有相同的鏡像數(shù)據(jù),在某些可以根據(jù)主鍵查詢的地方,使用高效的NoSQL數(shù)據(jù)庫查詢,這樣就節(jié)省了MySQL的查詢,用NoSQL的高性能來抵擋這些查詢。
這種不通過程序代碼,而是通過MySQL把數(shù)據(jù)同步到NoSQL中,這種模式是上面一種的變體,是一種對寫入透明但是具有更高技術(shù)難度一種模式。這種模式適用于現(xiàn)有的比較復(fù)雜的老系統(tǒng),通過修改代碼不易實現(xiàn),可能引起新的問題。同時也適用于需要把數(shù)據(jù)同步到多種類型的存儲中。
MySQL到NoSQL同步的實現(xiàn)可以使用MySQL UDF函數(shù),MySQL binlog的解析來實現(xiàn)??梢岳矛F(xiàn)有的開源項目來實現(xiàn),比如:
MySQL memcached UDFs:從通過UDF操作Memcached協(xié)議。
國內(nèi)張宴開源的mysql-udf-http:通過UDF操作http協(xié)議。
有了這兩個MySQL UDF函數(shù)庫,我們就能通過MySQL透明的處理Memcached或者Http協(xié)議,這樣只要有兼容Memcached或者Http協(xié)議的NoSQL數(shù)據(jù)庫,那么我們就能通過MySQL去操作以進行同步數(shù)據(jù)。再結(jié)合lib_mysqludf_json,通過UDF和MySQL觸發(fā)器功能的結(jié)合,就可以實現(xiàn)數(shù)據(jù)的自動同步。
(二)MySQL和NoSQL組合
MySQL中只存儲需要查詢的小字段,NoSQL存儲所有數(shù)據(jù)。
//寫入數(shù)據(jù)的示例偽代碼
//data為我們要存儲的數(shù)據(jù)對象
data.title=”title”; data.name=”name”;
data.time=”2009-12-01 10:10:01”;
data.from=”1”;
bool status=false; DB.startTransaction();//開始事務(wù)
id=DB.Insert(“INSERT INTO table (from)
VALUES(data.from)”);//寫入MySQL數(shù)據(jù)庫,只寫from需要where查詢的字段
if(id>0){
status=NoSQL.Add(id,data);//以寫入MySQL產(chǎn)生的自增id為主鍵寫入NoSQL數(shù)據(jù)庫 }
if(id>0 && status==true){
DB.commit();//提交事務(wù) }else{
DB.rollback();//不成功,進行回滾 }
復(fù)制代碼
把需要查詢的字段,一般都是數(shù)字,時間等類型的小字段存儲于MySQL中,根據(jù)查詢建立相應(yīng)的索引,其他不需要的字段,包括大文本字段都存儲在NoSQL中。在查詢的時候,我們先從MySQL中查詢出數(shù)據(jù)的主鍵,然后從NoSQL中直接取出對應(yīng)的數(shù)據(jù)即可。
這種架構(gòu)模式把MySQL和NoSQL的作用進行了融合,各司其職,讓MySQL專門負責處理擅長的關(guān)系存儲,NoSQL作為數(shù)據(jù)的存儲。它有以下優(yōu)點:
節(jié)省MySQL的IO開銷。由于MySQL只存儲需要查詢的小字段,不再負責存儲大文本字段,這樣就可以節(jié)省MySQL存儲的空間開銷,從而節(jié)省MySQL的磁盤IO。我們曾經(jīng)通過這種優(yōu)化,把MySQL一個40G的表縮減到幾百M。
提高MySQl Query Cache緩存命中率。我們知道query cache緩存失效是表級的,在MySQL表一旦被更新就會失效,經(jīng)過這種字段的分離,更新的字段如果不是存儲在MySQL中,那么對query cache就沒有任何影響。而NoSQL的Cache往往都是行級別的,只對更新的記錄的緩存失效。
提升MySQL主從同步效率。由于MySQL存儲空間的減小,同步的數(shù)據(jù)記錄也減小了,而部分數(shù)據(jù)的更新落在NoSQL而不是MySQL,這樣也減少了MySQL數(shù)據(jù)需要同步的次數(shù)。
提高MySQL數(shù)據(jù)備份和恢復(fù)的速度。由于MySQL數(shù)據(jù)庫存儲的數(shù)據(jù)的減小,很容易看到數(shù)據(jù)備份和恢復(fù)的速度也將極大的提高。
比以前更容易擴展。NoSQL天生就容易擴展。經(jīng)過這種優(yōu)化,MySQL性能也得到提高。比如手機鳳凰網(wǎng)就是這種架構(gòu)。
總結(jié)
以NoSQL為輔的架構(gòu)還是以MySQL架構(gòu)的思想為中心,只是在以前的架構(gòu)上輔助增加了NoSQL來提高其性能和可擴展性。這種架構(gòu)實現(xiàn)起來比較容易,卻能取得不錯的效果。如果正想在項目中引入NoSQL,或者你的以MySQL架構(gòu)的系統(tǒng)目前正出現(xiàn)相關(guān)的瓶頸,希望本文可以為你帶來幫助。