Schemaless架構(二):Uber基於MySQL的Trip資料庫

2021-02-13 GitChat精品課

ber的Schemaless資料庫是從2014年10月開始啟用的,這是一個基於MySQL的資料庫,本文就來探究一下它的架構。本文是系列文章的第二部分;第一部分是關於Schemaless的設計。

在《Mezzanine項目——Uber的超級大遷移》一文中,我們描述了如何將Uber的核心trip數據從一個單獨的Postgres實例遷移到Schemaless這個可擴展與高可用的資料庫中。然後對Schemaless進行了簡單介紹,包括其發展決策過程、整體數據模型,並介紹了Schemaless的trigger與索引等功能。 本文將概述Schemaless的架構。

Schemaless簡介

回顧一下,Schemaless是一個可擴展的容錯資料庫,其數據的基本單位被稱為單元(cell),它是不可變的,一旦寫入,便無法被覆蓋(在特殊情況下,我們可以刪除舊記錄);單元可以被行鍵(row key)、列名(column name)和引用鍵(ref key)引用;單元內容通過編寫引用鍵更高的新版來執行更新,但行鍵和列名保持不變。Schemaless不對其中存儲的數據執行任何操作(故而命名schemaless)。從Schemaless的觀點來看,它只負責存儲JSON對象。Schemaless有著獨特的模式,它支持最終在單元欄位保持一致的高效二級索引。

架構

Schemaless有兩種節點:工作節點和存儲節點,可以放在同一個物理/虛擬主機上,也可以放在分離的主機上。工作節點接收客戶端請求,將其分發到存儲節點中,再將結果聚合起來。存儲節點存放數據的方式使得在同一個存儲節點上進行單個或多個檢索速度很快。我們將這兩種節點類型分開,分別進行擴展。Schemaless的基本結構如下:

工作節點

Schemaless的客戶端與工作節點通過HTTP端點通訊。它們向存儲節點發出路由請求,並將從存儲節點獲得的結果進行聚合(在需要時),同時處理後臺任務。對於進展緩慢或出現故障的工作節點,客戶端資料庫將嘗試連接到其他主機並重試請求。對Schemaless的寫入請求是冪等的,因此每次請求重試都是安全的(這個性能真的很棒)。客戶端資料庫利用了這個功能。

存儲節點

我們將數據集劃分成固定數量的分片(一般配置為4096),然後將其映射到存儲節點上。根據單元的行鍵,將單元與分片一一對應。複製每個分片到存儲節點的可配置數量。總體來講,這些存儲節點構成存儲集群,每個存儲集群包含一個主(master)、兩個輔(minion)。Minion(也稱為副本)會分布到多個數據中心中,提供數據冗餘,以防災難性的數據中心宕機。

讀取和寫入請求

一旦Schemaless用作讀取,比如讀取單元或查詢索引時,工作節點能夠從集群的任意存儲節點中讀取數據。每次請求是從master還是minion的存儲節點中讀取是可配置的;默認是讀取master存儲節點的數據,也就是說確保客戶端能夠看到寫入請求的結果。寫入請求(請求插入單元)必須要在單元集群的master上執行。一旦master數據更新,存儲節點將更新異步複製到集群的minion上。

故障處理

分布式數據存儲系統有趣的一點在於它們處理故障的方式,比如在存儲節點未能響應請求時(無論master還是minion)。Schemaless在設計時,旨在將存儲節點無法響應讀取與寫入請求的失敗影響降到最低。

讀取請求

Master和minion的設置意味著:只要集群中有一個節點可用,就能滿足讀取請求。如果master可用,Schemaless就總能在檢索時返回最新的數據。如果master不可用,一些數據可能還未傳到minion,因此Schemaless可能返回過期的數據。然而在生產環境中,複製的延遲通常是次秒級的,因此minion的數據往往是最新的。工作節點在與存儲節點的連接中使用斷路器模式,以檢測存儲節點是否出現問題。用這種辦法,在出現故障時將讀取任務轉移到另一節點上。

寫入請求

一個minion宕機不會影響寫入;相應操作可以轉到master上去。不過如果master宕機,Schemaless仍會接收寫入請求,但會將這些請求存入另一個master(隨機選擇)的磁碟。這與Dynamo或Cassandra系統中的暗示移交(hinted handoff)十分類似。向另一個master寫入意味著在master恢復或者minion升級為master前,隨後的讀取請求都無法讀取這些新的寫入請求。事實上,在異步複製中Schemaless總是通過將寫入轉到另一個master的方式來處理故障;我們將這種技術稱為緩存寫入(buffered writes,下面會詳細描述)。

使用單獨的節點來接收寫入請求,優勢和劣勢都很多。一個優勢在於:寫入每個分片的請求可以整體進行排序。對於Schemaless trigger來說,這是很重要的性能,我們的異步處理框架(系列文的第一部分中提到過)可以從任意節點為分片讀取數據,同時確保同樣的處理順序。在所有集群的所有節點上負責寫入請求的單元都是一樣的。因此在某種意義上,Schemaless的分片可以看作是分區單元的修改日誌。

單master最突出的缺點在於,如果一個集群的master宕機,我們向別的master緩存寫入命令,但這些新的寫入內容是無法讀取的。這種麻煩情況的優點在於:Schemaless可以在master宕機時通知客戶端,因此客戶端會知道新寫入的單元不再是立即可讀的了。

緩存寫入

由於Schemaless使用MySQL異步複製,在master收到並留存寫入請求,然後還沒來得及將其複製到minion前,便出現了故障(比如硬碟驅動器故障),這個寫入請求就會丟失。為了解決這個問題,我們使用了一種技術,名叫緩存寫入。通過寫入多個集群,將數據丟失的風險減到最低。如果一個master宕機,後續的讀取任務無法迅速執行,但請求存續卻不受影響。

通過緩存寫入,當工作節點收到寫入請求時,會將請求寫入兩個集群:次級集群和主集群(按次順序)。只有兩者都執行成功的情況下,系統才會通知客戶端寫入成功。見下圖:

在後續讀取中,數據應當在主集群的master中。如果在異步MySQL複製將單元複製到主集群的minion前,主集群的master就宕機了,那麼就將次級集群的master用作臨時數據備份。

次級集群的master是隨機選擇的,轉移的寫入命令將進入特殊的緩存表格。後臺job會監控主集群的minion,查看單元的出現時間;然後才會將相應單元從緩存表格中刪除。設置次級集群代表著需要將所有數據至少要寫入兩個主機。此外,次級集群的數量也是可配置的。

緩存寫入用到了冪等性;如果一個行鍵、列名和引用鍵相同的單元已經存在,寫入就會被拒絕。冪等性意味著只要單元的行鍵、列名和引用鍵不同,就會在主集群的master恢復運作時寫入原master。另一方面,如果緩存了多個行鍵、列名和引用鍵相同的寫入請求,那麼只有一個能夠成功;在主集群恢復時,剩下的請求都會被拒絕。

將MySQL用作存儲後端

Schemaless的強大(與簡單)大多是因為我們在存儲節點中使用了MySQL。Schemaless本身是一個在MySQL之上相對較薄的層面,負責將路由請求發送給正確的資料庫。通過使用MySQL索引,並將build緩存到InnoDB中,單元和二級索引的查詢速度很快。

每個Schemaless分片都是獨立的MySQL資料庫,而每個MySQL資料庫伺服器包含一系列MySQL資料庫。每個資料庫包含一個單元的MySQL表格(叫做單元表),而每個二級索引也有一個MySQL表格,另有一組輔助表格。每個Schemaless的單元就是單元表中的一行,定義如下:

added_id列是一個自動遞增的整數列,也是單元表的MySQL主鍵。將added_id作為主鍵,可以讓MySQL在磁碟上線性寫入單元。此外,將added_id作為每個單元的獨特指針,Schemaless trigger可以按照插入的時間順序來有效地提取單元。

而row_key、column_name和ref_key分別代表Schemaless單元的行鍵、列名和引用鍵。為了通過這三欄進行有效地查詢,我們為這三列定義了一個複合MySQL索引。這樣一來,我們就能根據指定的行鍵和列名有效地找出所有單元了。

內容列中包含每個單元的JSON對象,以壓縮的MySQL blob(二進位大對象)表示。我們嘗試了各種編碼和壓縮算法,最終由於壓縮速度和大小選用了MessagePack和ZLib(在後面的文章中,我們會詳細進行描述)。最後,created_at列是單元插入的時間戳,可供Schemaless trigger用來查找指定日期的單元。

通過這種設置,客戶端可以控制模式,而無需修改MySQL的布局;查找單元更有效率。此外,added_id列使得寫入命令以線性執行,因此我們能夠將數據視作分區日誌來訪問,達到高效。

總結

如今的Schemaless是Uber基礎架構大量服務的生產資料庫。我們的很多服務都極其依賴這個高可用性和可擴展的Schemaless。

相關焦點

  • 基於MySQL的高性能資料庫應用開發
    首頁 > 語言 > 關鍵詞 > 資料庫最新資訊 > 正文 基於MySQL的高性能資料庫應用開發
  • 高性能Mysql主從架構的複製原理及配置詳解
    mysql支持的複製類型:基於語句的複製:在主伺服器上執行的SQL語句,在從伺服器上執行同樣的語句。MySQL默認採用基於語句的複製,效率比較高。一旦發現沒法精確複製時, 會自動選著基於行的複製。基於行的複製:把改變的內容複製過去,而不是把命令在從伺服器上執行一遍.
  • 工商銀行MySQL資料庫架構解密
    本文根據DTCC資料庫大會分享內容整理而成,將介紹工商銀行 IT 架構轉型中傳統 OLTP 資料庫架構面臨的挑戰和訴求,構建基於 MySQL 分布式企業級解決方案實踐歷程,包括技術選擇、高可用設計、兩地三中心容災、運維管理、資源使用效率等方面的思考和實踐經驗,同時也介紹了工行轉型的成效以及對後續工作的一些思考。
  • Mysql資料庫的使用方法
    4)支持外鍵;        5)支持崩潰數據自修復;       6) InnoDB設計目標是處理大容量資料庫系統,它的CPU利用率是其它基於磁碟的關係資料庫引擎所不能比的。        6)數據類型-datatype:所容許的數據的類型,每個表列都有相應的數據類型,它限制(或容許)該列中存儲的數據二、Mysql命令行(如下圖)1、連接mysql——格式: mysql -h主機地址 -u用戶名 -p用戶密碼       1)連接到本地
  • 如何使用MySQL資料庫
    如何使用MySQL資料庫前言:前面我們已經了解了如何搭建MySQL資料庫,那麼接下來我們就一起來了解一下,如何使用MySQL資料庫。MySQL資料庫系統也是一個典型的C/S(客戶端/伺服器)架構應用,要訪問MySQL資料庫需要使用專門的客戶端軟體。在linux系統中,最簡單、易用的MySQL客戶端軟體是其自帶的MySQL命令工具。
  • 考前複習必備MySQL資料庫(關係型資料庫管理系統)
    應用架構單點(Single),適合小規模應用複製(Replication),適合中小規模應用集群(Cluster),適合大規模應用索引功能從理論上來說,完全可以為數據表裡的每個欄位分別建一個索引,但MySQL把同一個數據表裡的索引總數限制為16個。
  • MySQL教程之MySQL定時備份資料庫
    一、MySQL數據備份1.1、 mysqldump命令備份數據在MySQL中提供了命令行導出資料庫數據以及文件的一種方便的工具mysqldump,我們可以通過命令行直接實現資料庫內容的導出dump,首先我們簡單了解一下mysqldump命令用法:
  • 從Web查詢資料庫之PHP與MySQL篇
    PHP+MySQL的組合是構建網站的一個常見搭配,不過如何使用PHP通過Web訪問MySQL資料庫呢?下面從Web資料庫架構的工作原理講起。
  • PHP MySQL資料庫編程
    1.1 mysql擴展連接允許PHP應用與MySQL資料庫交互的早期擴展。mysql擴展提供了一個面向過程 的接口;並且是針對MySQL4.1.3或更早版本設計的。因此,這個擴展雖然可以與MySQL4.1.3或更新的資料庫服務端 進行交互,但並不支持後期MySQL服務端提供的一些特性。
  • 「資料庫分享」MySQL資料庫優化
    數據分區有以下幾種類型:RANGE分區:基於連續區間範圍,把數據分配到不同的分區。HASH分區 / KEY分區:基於分區個數,把數據分配到不同的分區。mysql> set global slow_query_log='ON';mysql> set global long_query_time=1;或者直接修改MySQL配置文件啟用慢查詢日誌。
  • MYSQL資料庫操作案例
    MySQL 創建資料庫CREATE DATABASE 資料庫名;以下命令簡單的演示了創建資料庫的過程,數據名為 RUNOOB:[root@host]# mysql -u root -p >Enter password:****** # 登錄後進入終端mysql> create DATABASE RUNOOB;MySQL 刪除資料庫drop database <資料庫名>;
  • MySQL基於MHA的FailOver過程
    本文介紹MySQL基於MHA的FailOver過程。,mha就不再工作了,也會自動宕機當mha出現時,我們可以使用send_report以郵件報警的方式來獲得錯誤信息數據,方便了解資料庫狀態。/bin/bash echo "你好,先生,資料庫宕機了" | mail -s "資料庫宕機了,請登錄系統查看mha狀態" 1915530614@qq.com添加執行權限chmod +x send_report然後修改配置文件
  • 京東面試:說說MySQL的架構體系
    字數:3620,閱讀耗時:4分35秒最近群裡一位兄弟在面試中被問到:「MySQL的架構體系是什麼」。雖然他搞java開發好幾年了,也一直使用的是MySQL資料庫,但是面對這個問題依然是一臉懵逼,還以為面試官要問索引、慢查詢、性能優化之類的(因為這些都是網上找點面試題背過了)。
  • python對mysql資料庫的操作(一)
    本文章介紹python對mysql資料庫的基本操作,以及編寫一個模擬用戶的註冊。
  • MySQL資料庫及應用
    查詢答案: A7 單選 資料庫、資料庫管理和資料庫系統之間的關係正確的是A. 資料庫包括了資料庫管理系統和資料庫系統B. 資料庫管理系統包括了資料庫和資料庫系統C.Document.Write("HelloWorld");D. write(「HelloWorld」);5 單選 連接 MySQL 資料庫的正確方法是A. mysql_open("localhost");B. mysql_connect("localhost
  • Python開發之:Django基於Docker實現Mysql資料庫讀寫分離、集群、主從同步詳解 | 原力計劃
    有很多種配置主從同步的方法,可以總結為如下的步驟:在主伺服器上,必須開啟二進位日誌機制和配置一個獨立的ID在每一個從伺服器上,配置一個唯一的ID,創建一個用來專門複製主伺服器數據的帳號在開始複製進程前,在主伺服器上記錄二進位文件的位置信息如果在開始複製之前,資料庫中已經有數據,就必須先創建一個數據快照(可以使用mysqldump 導出資料庫,或者直接複製數據文件)配置從伺服器要連接的主伺服器的IP位址和登陸授權
  • 【用binlog日誌】恢復 MySQL 資料庫刪除數據
    1)二進位日誌索引文件(文件名後綴為.index):用於記錄所有的二進位文件;2)二進位日誌文件(文件名後綴為.00000*):記錄資料庫所有的DDL和DML(除了數據查詢語句select)語句事件。binlog日誌對於mysql資料庫來說是十分重要的。
  • 利用PowerDesigner連接Mysql資料庫並逆向所有表關係圖兩種方式
    兩種方式:一種是連接mysql資料庫,另一種是有sql腳本文件的。一:配置PowerDesigner連接到mysql資料庫(使用的是JDBC方式)。1.1:新建文件,選擇mysql.所以我們就選擇jdbcDBMS type:資料庫類型,提供大部分主流的資料庫可供選擇。這裡我們選擇MySqlUser name:資料庫用戶名JDBC driver class:指定驅動類,我們使用的是mysql。
  • 實例講解:.NET如何訪問MySQL資料庫
    .NET的資料庫天然支持MSSQLServer,但是並非其他資料庫不支持,而是微軟基於自身利益需要,在支持、營銷上推自己的資料庫產品;但是作為平臺戰略,他並非排斥其他資料庫,而是參考java體系提出了一套資料庫訪問規範,讓各個第三方進行開發,提供特定的驅動。
  • day06-python資料庫-mysql之安裝
    資料庫說白了就是文件夾資料庫管理系統就是一個軟體資料庫伺服器:就是對外專門提供數據的一個機器資料庫伺服器,資料庫管理系統,表與記錄的關係:總結:資料庫管理技術的發展歷程人工管理階段---》文件系統階段---》數據系統階段mysql介紹MySQL是一個關係型資料庫管理系統,MySQL最流行的關係型資料庫管理系統,在WEB應用方面MySQL是最好的RDBMS(Relational Database Management System,關係資料庫管理系統