MySQL 作為新的 NoSQL 解決方案: 輕松應對億級數據

ArletteIsab 8年前發布 | 23K 次閱讀 MySQL 數據庫服務器

來自: http://blog.csdn.net/renfufei/article/details/50682724


MySQL現在是一個更好的NoSQL解決方案。我們這樣說是因為在存儲 鍵/值(key/value) 之類數據時, MySQL 具有性能、易用性和穩定性方面的優勢。MySQL引擎穩定可靠,并且社區和官方支持良好,有非常豐富的在線資料, 涵蓋了各種操作、故障排查,復制以及各種使用模式等方面。基于這個原因, MySQL比起新興的NoSQL引擎具有很大優勢。

近年來,NoSQL引擎已成為主流。許多開發者將NoSQL引擎(包括: MongoDB, Cassandra, Redis, 和 Hadoop等)視為最優解,同時不贊成使用舊的 SQL 引擎。

選擇NoSQL數據庫通常是因為炒作,或者是認為關系數據庫解決不了和NoSQL相關的事。普通工程師在選擇數據庫時往往會忽視運營成本,穩定性和成熟度等問題。更多關于各種NoSQL(以及SQL)引擎的區別,以及局限性等方面的問題,請參考 Aphyr 上的 Jepsen專欄文章

本文將闡釋為什么用MySQL存儲 鍵/值 數據比大多數專用NoSQL引擎更適合的原因,并提供相應的指導步驟。

Wix 網站的解決方案

當用戶訪問Wix上的某個網站頁面時, 瀏覽器會向Wix網站服務器發送一個HTTP請求。不管是自定義域名(例如, cncounter.com)還是免費的Wix二級域名(如: user.wix.com/site)。服務器需要通過查詢鍵/值對來將URL請求解析為相應的站點。在下面的討論中我們將URL視為 route(路由)。

routes 表用來將網址解析為 site 對象。因為網站可能有多個路由, 所以是多對一的關系(many to one, N:1)。找到網站以后, 程序就加載它。site 對象機構比較復雜, 包括兩個子對象列表 —— 網站使用的不同服務。下面是示例對象模型, 假設使用標準SQL數據庫和規范化表結構:

當更新 site時, 如果使用傳統的范式模型來更新多個表, 需要用事務(transaction)來保證數據的一致性(data consistency)。(注意,事務使用數據庫級別的鎖(DB-level lock),這會阻止并發寫操作,有時也會影響相關表的并發讀操作。) 使用這種模型, 可能需要在每個表中設置一個序列鍵(serial key),并使用外鍵,以及為 routes 表的 URL 字段創建索引。

但是,使用范式設計會碰到很多問題:

  • 鎖限制了對表的訪問, 所以在高吞吐量情景下會嚴重影響性能。
  • 讀取一個對象需要使用多條SQL語句(此處是4條), 或者使用 join (這又會受延遲影響)。
  • 系列鍵的生成使用了鎖, 限制了寫吞吐量。

在MySQL或者其他SQL引擎中, 并發情況和吞吐量問題都是大量出現的。因為這些缺點,實際上在存儲 鍵/值對形式的數據時,很多開發者都傾向于使用 NoSQL 解決方案, 為了提供更好的吞吐量和并發性能, 而犧牲一些 穩定性(stability)、一致性(consistency)、和可用性(availability)。

在 Wix, 我們發現 MySQL 作為鍵/值存儲使用時,比起作為關系數據模型時要強悍得多, 也比大多數NoSQL引擎要優秀很多。僅僅是使用MySQL作為NoSQL引擎,我們的現有系統在擴展性/吞吐量/并發/延遲等指標上都可以媲美任何NoSQL引擎。下面是一些數據:

  • 跨三個數據中心的結構 (active-active-active setup, 三活)。
  • 吞吐量在 200,000 RPM 數量級。
  • routes 表的記錄在 1億 數量級, 占用空間為 10 GB級。
  • sites 表的記錄在 1億數量級,存儲空間 200 GB以上。
  • 平均讀取延遲在 1.0 -1.5毫秒之間(事實上,同一數據中心是 0.2 - 0.3 毫秒)。

請注意,在大多數 鍵/值 引擎中, 1.0 毫秒左右的延遲都是卓越的,包括開源的和基于云的! 而我們是用MySQL實現的(MySQL被認為是標準的SQL引擎)。

表結構如下:

CREATE TABLE `routes` (
  `route` varchar(255) NOT NULL,
  `site_id` varchar(50) NOT NULL,
  `last_update_date` bigint NOT NULL,
  PRIMARY KEY (`key`),
  KEY (`site_id`)
)

CREATE TABLE `sites` (
  `site_id` varchar(50) NOT NULL,
  `owner_id` varchar(50) NOT NULL,
  `schema_version` varchar(10) NOT NULL DEFAULT '1.0',
  `site_data` text NOT NULL,
  `last_update_date` bigint NOT NULL,
  PRIMARY KEY (`site_id`)
) /*ENGINE=InnoDB DEFAULT CHARSET=utf8 
    ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16*/;

所有不需要作為查詢條件的字段都已經合并到單個 blob 字段中(site_data text 字段)。其中包含了 sub-obj 記錄,以及 site 對象自身的其他屬性域。也請注意,這里沒有使用自增序列鍵;相反,我們使用 varchar(50) 來存儲客戶端生成的 GUID 值。

下面是我們使用的查詢語句, 具有高吞吐量和低延遲特性:

select * from sites where site_id = (
  select site_id from routes where route = ?
)

首先通過唯一索引查詢 routes 表,這只返回一個結果。然后通過主鍵查找 site, 也只有一條記錄。嵌套查詢語法確保 2個SQL查詢卻只需一次數據庫交互。

結果前面提到了, 在高流量和高更新率的情況下, 保持在平均 ~1毫秒左右 的性能。雖然沒有使用事務,但 update 是半事務性質的(semi-transactional)。這是因為, 先輸入一個 site, 但在輸入 route 記錄之前,都不會查詢到相關的記錄。所以如果我們先輸入 site, 再輸入 route, 依然能確保數據一致性狀態, 即使在 sites 表中有很多孤兒數據的情況下。

MySQL當做 NoSQL引擎使用指南

通過上面的例子(以及Wix的其他類似情景), 我們精心制作了一份用MySQL作為NoSQL引擎的經驗指南。

最主要的是要記住, 使用MySQL作為NoSQL引擎時要避免數據庫鎖(DB locks)以及復雜的查詢

  • 不使用事務,因為會導致鎖(locks)。相反, 應該使用應用層事務(applicative transactions)。
  • 不使用序列鍵(serial key)。序列鍵會導致鎖以及引起復雜的 active-active 配置。
  • 使用客戶端生成的唯一鍵(client-generated unique keys)。我們使用的是 GUID。

設計數據庫時,進行查詢優化時還有如下要點:

  • 不要使用范式(Do not normalize)。
  • 只存儲有索引的字段。如果某個字段不需要索引, 那么將其存儲在 blob/text 字段中(如JSON或XML)。
  • 不要使用外鍵(foreign key)。
  • 必須允許讀取單行數據。
  • 不準執行 alter 命令。表的 alter 命令會導致鎖以及宕機。如果不得不這樣做, 應該使用動態遷移(live migrations)。

在查詢數據時:

  • 使用主鍵(primary key)和索引(index)作為條件來查詢.
  • 不要使用 join.
  • 不要使用聚合函數(aggregation).
  • 只在副本(replica)中執行繁重的查詢(housekeeping queries), 比如商業智能(BI), 數據研究(data exploration)等操作, 盡量不要在主庫(master database)上執行.

我們準備在另一篇博客中深入介紹實時遷移(live migrations)和應用層事務(applicative transactions)。

總結

本文最主要的目的是讓你認識 MySQL 的新特性。將 MySQL 作為NoSQL引擎是很棒的, 雖然MySQL不是專為NoSQL設計的。文中展示了如何使用 MySQL 代替專用 NoSQL引擎來存儲 鍵/值(key/value) 信息。

在 Wix , 保存鍵/值信息(等情況下)會選擇MySQL引擎, 原因是其易于使用和操作, 并且MySQL強大的生態系統。另外,比起多數NoSQL引擎來說,在延遲(latency)、吞吐量(throughput)和并發性(concurrency)等指標(metrics)上MySQL并不遜色。

原文鏈接(需國內或許不能訪問): http://engineering.wix.com/2015/12/10/scaling-to-100m-mysql-is-a-better-nosql/

原文日前: 2015年12月10日

翻譯日期: 2015年12月27日

作者: 鐵錨 http://blog.csdn.net/renfufei


 

 本文由用戶 ArletteIsab 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!