【架構】NoSQL架構實踐(一)以NoSQL為輔

  • 摘要:很多朋友看到NoSQL時總會有困惑,覺得很好,但是卻不知道如何正式用到自己的項目中。下文中筆者帶我們看下怎麼樣在我們的系統中使用NoSQL。
  • 標籤:NoSQL
  • 經常有朋友遇到困惑,看到NoSQL的介紹,覺得很好,但是卻不知道如何正式用到自己的項目中。很大的原因就是思維固定在MySQL中了,他們問得最多的問題就是用了NoSQL,我如何做關係查詢。那麼接下來,我們看下怎麼樣在我們的系統中使用NoSQL。

    怎麼樣把NoSQL引入到我們的系統架構設計中,需要根據我們系統的業務場景來分析,什麼樣類型的數據適合存儲在NoSQL資料庫中,什麼樣類型的數據必須使用關係資料庫存儲。明確引入的NoSQL資料庫帶給系統的作用,它能解決什麼問題,以及可能帶來的新的問題。下面我們分析幾種常見的NoSQL架構。

    (一)NoSQL作為鏡像

    不改變原有的以MySQL作為存儲的架構,使用NoSQL作為輔助鏡像存儲,用NoSQL的優勢輔助提升性能。

    圖 1 -NoSQL為鏡像(代碼完成模式 )

    1. //寫入數據的示例偽代碼
    2. //data為我們要存儲的數據對象
    3. data.title=」title」;
    4. data.name=」name」;
    5. data.time=」2009-12-0110:10:01」;
    6. data.from=」1」;
    7. id=DB.Insert(data);
    8. //寫入MySQL資料庫
    9. NoSQL.Add(id,data);
    10. //以寫入MySQL產生的自增id為主鍵寫入NoSQL資料庫

    如果有數據一致性要求,可以像如下的方式使用

    1. //寫入數據的示例偽代碼
    2. //data為我們要存儲的數據對象
    3. boolstatus=false;DB.startTransaction();
    4. //開始事務
    5. id=DB.Insert(data);
    6. //寫入MySQL資料庫
    7. if(id>0){
    8. status=NoSQL.Add(id,data);
    9. //以寫入MySQL產生的自增id為主鍵寫入NoSQL資料庫
    10. }
    11. if(id>0&&status==true){
    12. DB.commit();
    13. //提交事務
    14. }else{
    15. DB.rollback();
    16. //不成功,進行回滾
    17. }

    上面的代碼看起來可能覺得有點麻煩,但是只需要在DB類或者ORM層做一個統一的封裝,就能實現重用了,其他代碼都不用做任何的修改。

    這種架構在原有基於MySQL資料庫的架構上增加了一層輔助的NoSQL存儲,代碼量不大,技術難度小,卻在可擴展性和性能上起到了非常大的作用。只需要程序在寫入MySQL資料庫後,同時寫入到NoSQL資料庫,讓MySQL和NoSQL擁有相同的鏡像數據,在某些可以根據主鍵查詢的地方,使用高效的NoSQL資料庫查詢,這樣就節省了MySQL的查詢,用NoSQL的高性能來抵擋這些查詢。

    圖 2 -NoSQL為鏡像(同步模式)

    這種不通過程序代碼,而是通過MySQL把數據同步到NoSQL中,這種模式是上面一種的變體,是一種對寫入透明但是具有更高技術難度一種模式。這種模式適用於現有的比較複雜的老系統,通過修改代碼不易實現,可能引起新的問題。同時也適用於需要把數據同步到多種類型的存儲中。

    MySQL到NoSQL同步的實現可以使用MySQL UDF函數,MySQL binlog的解析來實現。可以利用現有的開源項目來實現,比如:

    ◆MySQL memcached UDFs:從通過UDF操作Memcached協議。◆國內張宴開源的mysql-udf-http:通過UDF操作http協議。

    有了這兩個MySQL UDF函數庫,我們就能通過MySQL透明的處理Memcached或者Http協議,這樣只要有兼容Memcached或者Http協議的NoSQL資料庫,那麼我們就能通過MySQL去操作以進行同步數據。再結合lib_mysqludf_json,通過UDF和MySQL觸發器功能的結合,就可以實現數據的自動同步。

    (二)MySQL和NoSQL組合

    MySQL中只存儲需要查詢的小欄位,NoSQL存儲所有數據。

    圖 3 -MySQL和NoSQL組合

    1. //寫入數據的示例偽代碼
    2. //data為我們要存儲的數據對象
    3. data.title=」title」;
    4. data.name=」name」;
    5. data.time=」2009-12-0110:10:01」;
    6. data.from=」1」;
    7. boolstatus=false;DB.startTransaction();
    8. //開始事務
    9. id=DB.Insert(「INSERTINTOtable(from)VALUES(data.from)」);
    10. //寫入MySQL資料庫,只寫from需要where查詢的欄位
    11. if(id>0){
    12. status=NoSQL.Add(id,data);
    13. //以寫入MySQL產生的自增id為主鍵寫入NoSQL資料庫
    14. }
    15. if(id>0&&status==true){
    16. DB.commit();
    17. //提交事務
    18. }else{
    19. DB.rollback();
    20. //不成功,進行回滾
    21. }

    把需要查詢的欄位,一般都是數字,時間等類型的小欄位存儲於MySQL中,根據查詢建立相應的索引,其他不需要的欄位,包括大文本欄位都存儲在NoSQL中。在查詢的時候,我們先從MySQL中查詢出數據的主鍵,然後從NoSQL中直接取出對應的數據即可。

    這種架構模式把MySQL和NoSQL的作用進行了融合,各司其職,讓MySQL專門負責處理擅長的關係存儲,NoSQL作為數據的存儲。它有以下優點:

    ◆節省MySQL的IO開銷。由於MySQL只存儲需要查詢的小欄位,不再負責存儲大文本欄位,這樣就可以節省MySQL存儲的空間開銷,從而節省MySQL的磁碟IO。我們曾經通過這種優化,把MySQL一個40G的表縮減到幾百M。◆提高MySQl Query Cache緩存命中率。我們知道query cache緩存失效是表級的,在MySQL表一旦被更新就會失效,經過這種欄位的分離,更新的欄位如果不是存儲在MySQL中,那麼對query cache就沒有任何影響。而NoSQL的Cache往往都是行級別的,只對更新的記錄的緩存失效。◆提升MySQL主從同步效率。由於MySQL存儲空間的減小,同步的數據記錄也減小了,而部分數據的更新落在NoSQL而不是MySQL,這樣也減少了MySQL數據需要同步的次數。◆提高MySQL數據備份和恢復的速度。由於MySQL資料庫存儲的數據的減小,很容易看到數據備份和恢復的速度也將極大的提高。◆比以前更容易擴展。NoSQL天生就容易擴展。經過這種優化,MySQL性能也得到提高。

    總結

    以NoSQL為輔的架構還是以MySQL架構的思想為中心,只是在以前的架構上輔助增加了NoSQL來提高其性能和可擴展性。這種架構實現起來比較容易,卻能取得不錯的效果。如果正想在項目中引入NoSQL,或者你的以MySQL架構的系統目前正出現相關的瓶頸,希望本文可以為你帶來幫助。

    【編輯推薦】

    1. NoSQL理論研究:內存是新的硬碟,硬碟是新的磁帶
    2. 關於NoSQL資料庫你應該知道的10件事
    3. NoSQL就業形勢分析:Cassandra和MongoDB最受歡迎
    4. 用NoSQL來替代MySQL在Digg中的原因
    5. 詳解NoSQL資料庫使用實例

    推薦閱讀:

    scylladb專欄開篇
    ScyllaDB的Userspace IO Scheduler實現
    c++ 實時消息系統什麼in-process資料庫比較好? leveldb、LMDB 還是sqlite?
    如何評價SequoiaDB巨杉資料庫?
    現在最成熟的開源nosql是什麼?分別有什麼優缺點?

    TAG:架構 | NoSQL | 實踐 |