深入理解数据库核心技术
“?數據庫作為IT系統核心基石,為互聯網科技的進步起著不可磨滅的功勞。”
來自公眾號:技術茶館
01
—
概述
數據庫是“按照數據結構來組織、存儲和管理數據的倉庫”。是一個長期存儲在計算機內的、有組織的、可共享的、統一管理的大量數據的集合。
數據庫系統把每一個應用只定義并且維護自己的數據的這樣一種形式(圖1)改變為對于數據的集中定義和集中管理(圖2)。這種新的變化帶來了數據獨立性(data independence), 使得應用程序不再受到數據在邏輯組織或物理組織上帶來的變化影響,反之亦然。
使用數據庫系統的動機之一就是集成企業的運營數據,提供集中的、對于數據可控制的存取。
02
—
數據庫的演進之路
數據庫已經發展了40年,可以說是一個傳統又古老的領域?;仡檾祿斓陌l展歷史,1980年到1990年屬于商業起步階段,此時Oracle、IBM DB2、Sybase以及SQL Server和Informix等開始出現。
1990年至2000年,開源數據庫開始展露頭角,出現了PostgreSQL和MySQL等。與此同時,出現了一些分析型數據庫,因為之前出現的都是OLTP,而現在隨著大量數據的出現,需要對于這些數據進行分析,因此出現了OLAP,而為了避免讀寫沖突,就需要建立分析型數據庫系統,Teradata、Sybase IQ、Greenplum等就快速成長起來。
2000年到2010年期間,以谷歌為代表的互聯網公司逐漸推出了NoSQL數據庫。尤其是谷歌的GFS(Google File System)、Google Bigtable、Google MapReduce三大件。Google File System解決了分布式文件系統問題,Google Bigtable解決了分布式KV(Key-Value)存儲的問題,Google MapReduce解決了在分布式文件系統和分布式KV存儲上面如何做分布式計算和分析的問題。之所以產生了這三大件,是因為數據強一致性對系統的水平拓展以及海量數據爆發式增長的分析能力出現了斷層。因此就需要解決這個問題,把這種數據的強一致性需求弱化,換來能夠使用用分布式的集群做水平拓展處理。谷歌三大件在業界誕生以后,很快的衍生了一個新的領域叫NoSQL(Not Only SQL),就是針對非結構化、半結構化的海量數據處理系統?,F在也有很多很好的商業公司基于NoSQL發展,比如說文檔數據(MongoDB)、緩存(Redis)等大家平常應用開發都會用到的NoSQL系統。
而在2010年以后,AWS Aurora、Redshift、Azure SQL Database、Google Spanner發展起來了,它們的特點就是云原生、一體化分布式、HTAP的能力。
總結而言,數據庫的演進經歷了從結構化數據在線處理到海量數據分析,從SQL+OLAP的RDBMS到ETL+OLAP的Data Warehouse和Data Lake,再到今天異構多源的數據類型的發展歷程。
數據庫的發展-業務視角
大家知道,數據庫可以分為幾類:
最經典的是傳統關系型OLTP數據庫,其主要用于事務處理的結構化數據庫,典型例子是銀行的轉賬記賬、電商下單、訂單以及商品庫存管理等。其面臨的核心挑戰是高并發、高可用以及高性能下的數據正確性和一致性。
其次是NoSQL數據庫及專用型數據庫,其主要用于存儲和處理非結構化或半結構化數據(如文檔,圖,時序、時空,K-V),不強制數據的一致性,以此換來系統的水平拓展、吞吐能力的提升。
再次是分析型數據庫 (On-Line Analytic Processing, OLAP),其應用場景就是海量的數據、數據類型復雜以及分析條件復雜的情況,能夠支持深度智能化分析。其面臨的挑戰主要是高性能、分析深度、與TP數據庫的聯動,以及與NoSQL數據庫的聯動。
除了數據的核心引擎之外,還有數據庫外圍的服務和管理類工具,比如數據傳輸、數據備份以及數據管理等。
最后就是數據庫的管控平臺,無論是私有云、專有云、混合云還是自己的IDC機房內進行部署,總要有一套數據庫管控系統來管理數據庫實例的產生和消亡、實例的資源消費等,能夠以簡單的形式提供給DBA以及數據庫開發者。
03
—
數據庫的技術演進之路
隨著數據庫的發展,漸漸的數據庫從傳統的集中式架構,逐步轉型成分布式架構。因為遠超單機數據庫容量的數據存儲和訪問峰值、實時數據分析檢索(OLTP兼顧OLAP)、更高級別的容災需求。
傳統的集中式架構在穩定性和可用性方面有天然的優勢,同時缺點也很明顯,擴展性差。原來傳統企業接入的終端有限,銀行、政企的業務系統都是給內部人員使用,其擴展性方面的短板還不足以構成挑戰。但是隨著互聯網尤其是移動互聯網的發展,業務系統除了滿足內部人員使用,還要支撐海量移動終端的訪問請求,數據指數級增長所帶來的高并發使得集中式架構面臨著挑戰,依靠垂直型擴展很難滿足需求。
因為傳統集中式數據庫的限制條件,無法滿足大數據時代對于數據庫性能的要求,那么分布式的數據庫逐漸進入人們的視野,分布式數據庫一般具有以下特性具有靈活的體系結構、適應分布式的管理和控制機構、經濟性能優越、系統的可靠性高、可用性好、局部應用的響應速度快、可擴展性好,易于集成現有系統等特點。
那么我們從幾個方面來描述下數據庫在集中式架構或分布式架構中使用到的核心技術點有哪些。傳統集中式數據庫架構指關系型數據庫,如MySQL、Oracle、SqlServer等。分布式數據庫系統架構比如CirrData, Oceanbase, TiDB, Cloudera Impala等等。下面我們先講一下傳統的集中式數據庫架構以Mysql為例, 來描述在集中式數據庫中涉及到的核心技術點。相關架構中的核心技術不會細講,先知道有這么個東西就好,后期會專門一系列的文章來細講數據庫架構中這些技術的使用方式、技術的原理、為什么要這么用。
一、傳統集中式數據庫架構
將數據庫系統拆開來看,其核心模塊包括應用接口、SQL接口、查詢執行引擎、數據訪問模塊和存儲引擎。其中,查詢執行引擎進一步可以拆分為計劃生成器、計劃優化器和計劃執行器;數據訪問模塊則可以分為事務處理、內存處理、安全管理以及文件和索引管理等模塊;并且事務處理是最核心的模塊,其中包括了崩潰恢復和并發控制;最底層的存儲引擎則包括數據文件、索引文件和系統及元數據文件。
傳統數據庫架構大致劃分為幾層:
應用層: 給客戶端提供連接數據庫的工具。
會話層: 處理客戶端與服務器的session信息,并檢測是否有訪問數據庫的權限相關的權限動作。
計劃層: 解析SQL字符串和邏輯計劃的生成。
計算層: 把邏輯計劃轉成物理計劃,并計算結果。
數據訪問層: 文件和索引、事務的管理。
存儲引擎: 外部數據源存儲的數據文件。
下面舉一個查詢的例子,看各個層之間是如何配合實現的。
1.?查詢分析處理過程
數據庫查詢分析處理過程是這樣的:首先,通過SQL語句將查詢任務提交上來,之后經過Session Manger和Parser進行處理,此時會有各種各樣的執行方式,并生成Catalog和邏輯執行計劃;之后對于邏輯執行計劃進行優化,并生成物理執行計劃;之后在借助系統的統計信息,如索引管理、內存管理來生成一個優化后的物理執行計劃,再執行并生成最后結果。
簡單而言,數據庫系統的架構就是持久化存儲的數據按照Data Page的形式進行存儲,這些數據塊在查詢訪問的時候會被帶到內存里面。系統中有內存池,每個內存池可以裝載一個Page,此時的問題就是內存池的大小是有限的,如果數據存儲非常大,需要進行優化。此外,還涉及到優化數據訪問的問題,一般通過索引解決,主要是Hash索引和樹形索引。那么我們把各個組件拆解,來描述下各個組件都使用什么樣的技術。
2.?核心技術
2.1?JDBC組件
大部分應用場景下,使用的都是JDBC組件,那么JDBC是什么?JDBC (Java Database Connectivity) API,即Java數據庫編程接口,是一組標準的Java語言中的接口和類,使用這些接口和類,Java客戶端程序可以訪問各種不同類型的數據庫。比如建立數據庫連接、執行SQL語句進行數據的存取操作。通常和客戶應用綁定在一起。
2.2 會話管理組件
在連接數據庫與斷開連接之間的時間被稱為一個數據會話。會話管理通常是數據庫和外部交互的組件。JDBC與會話管理通常數據交互,可以使用grpc或者thrift這種RPC通信的技術。
2.3 權限管理組件
權限是用戶對一項功能的執行權利,在數據庫中,根據系統管理方式的不同,可將權限分為系統權限與對象權限兩類, 系統權限是指被授權用戶是否可以連接到數據庫上及數據庫中可以進行哪些系統操作,另一類是對象權限是指用戶對數據庫中具體對象所擁有的權限, 對象權限,如數據庫中的表,視圖,存儲過程,存儲函數等。權限模組一般采用的技術是緩存機制。因為用戶權限相關的數據會被持久化到物理設備中。緩存機制可以有效的減少IO操作。
2.4 SQL解析器組件
數據庫需要支持標準的 SQL 語言,具體實現的時候必然要涉及到詞法分析和語法分析。早期的程序可能會優先考慮手工實現詞法分析和語法分析,現在大多數場合下都會采用工具來簡化實現。MySQL、PostgreSQL 等采用 C/C++ 實現的開源數據庫采用的是現代的 yacc/lex 組合,也就是 GNU bison/flex。其他比較流行的工具還有 ANTLR、JavaCC 等等。這些工具大多采用擴展的 BNF 語法,并支持很多定制化選項,使得語法比較容易維護和實現。通過這些工具可以使應用端發送過來的SQL字符串,轉成一個AST(Abstract Syntax Tree)抽象SQL語法樹。
2.5 SQL查詢優化器
優化器作為數據庫核心功能之一,也是數據庫的“大腦”,理解優化器將有助于我們更好地優化SQL。
傳統關系型數據庫里面的優化器分為CBO和RBO兩種。
RBO(Rule Based Potimizer) 基于規則的優化器:
RBO :RBO所用的判斷規則是一組內置的規則,這些規則是硬編碼在數據庫的編碼中的,RBO會根據這些規則去從SQL諸多的路徑中來選擇一條作為執行計劃(比如在RBO里面,有這么一條規則:有索引使用索引。那么所有帶有索引的表在任何情況下都會走索引)所以,RBO現在被很多數據庫拋棄(oracle默認是CBO,但是仍然保留RBO代碼,MySQL只有CBO)
RBO最大問題在于硬編碼在數據庫里面的一系列固定規則,來決定執行計劃。并沒有考慮目標SQL中所涉及的對象的實際數量,實際數據的分布情況,這樣一旦規則不適用于該SQL,那么很可能選出來的執行計劃就不是最優執行計劃了。
CBO(Cost Based Potimizer) 基于成本的優化器:
CBO :CBO在會從目標諸多的執行路徑中選擇一個成本最小的執行路徑來作為執行計劃。這里的成本他實際代表了MySQL根據相關統計信息計算出來目標SQL對應的步驟的IO,CPU等消耗。也就是意味著數據庫里的成本實際上就是對于執行目標SQL所需要IO,CPU等資源的一個估計值。而成本值是根據索引,表,行的統計信息計算出來的。(計算過程比較復雜)
2.6??物理執行器組件
物理執行器又叫做計劃執行器。執行器架構一般采用Volcano Model經典的基于行的流式迭代模型(Row-BasedStreaming Iterator Model)。比如我們熟知的主流關系數據庫中都采用了這種模型,例如Oracle,SQL Server, MySQL等。
在Volcano模型中,所有的代數運算符(operator)都被看成是一個迭代器,它們都提供一組簡單的接口:open()—next()—close(),查詢計劃樹由一個個這樣的關系運算符組成,每一次的next()調用,運算符就返回一行(Row),每一個運算符的next()都有自己的流控邏輯,數據通過運算符自上而下的next()嵌套調用而被動的進行拉取。
這是一個最簡單的火山模型例子,拉取數據的控制命令從最上層的Output運算符依次傳遞到執行樹的最下層,而數據流動的方向正好相反。
這種計算模型對于CPU Cache是不友好的,所以一般在做表達式計算的時候通常采用編譯執行。來提高CPU Cache的命中率。通常采用的的技術是Llvm技術。
對于OLAP數據的物理執行引擎通常采用列存的數據結構,因為可以比較高效的提高CPU Cache的利用率,通常也可以采用比較高效SIMD指令來處理。
隨著各個商業數據庫做軟硬件一體化解決方案的產生,通常也會使用GPU和FPGA這種技術來提高計算性能。
2.7?索引組件
索引是對數據庫表中一列或多列的值進行排序的一種結構,使用索引可快速訪問數據庫表中的特定信息。如果想按特定職員的姓來查找他或她,則與在表中搜索所有的行相比,索引有助于更快地獲取信息。
索引的一個主要目的就是加快檢索表中數據,亦即能協助信息搜索者盡快的找到符合限制條件的記錄ID的輔助數據結構。
數據庫索引的核心技術總的來說,索引就是拿空間換時間。數據庫技術和大數據技術會有一個融合的過程,除了前面講到的B樹索引、Hash索引等,還有倒排索引、MinMax索引、BitSet索引、MDK索引等。
2.8?事務處理組件
數據庫的事務處理是數據庫最重要的核心模組之一,數據庫事務(transaction)是訪問并可能操作各種數據項的一個數據庫操作序列,這些操作要么全部執行,要么全部不執行,是一個不可分割的工作單位。事務由事務開始與事務結束之間執行的全部數據庫操作組成。
事務是并發控制的基本單位。
一個事務包含的諸操作要么都執行,要么都不執行。
事務的屬性
原子性 :事務是數據庫的邏輯工作單位,一個事務的諸操作要么都做,要么都不做。?
一致性 :指事務執行前后必須保持數據庫的邏輯一致性。一致性和原子性是密切相關的。?
隔離性 :指并發執行的各個事務之間不能互相干擾。?
持久性 :指一個事務的操作提交后, 其對數據庫的改變是永久的,屬于物理的而非邏輯的。
數據庫的事務隔離級別
READ UNCOMMITTED(讀未提交數據):允許事務讀取未被其他事務提交的變更數據,會出現臟讀、不可重復讀和幻讀問題。
READ COMMITTED(讀已提交數據):只允許事務讀取已經被其他事務提交的變更數據,可避免臟讀,仍會出現不可重復讀和幻讀問題。
REPEATABLE READ(可重復讀):確保事務可以多次從一個字段中讀取相同的值,在此事務持續期間,禁止其他事務對此字段的更新,可以避免臟讀和不可重復讀,仍會出現幻讀問題。
SERIALIZABLE(序列化):確保事務可以從一個表中讀取相同的行,在這個事務持續期間,禁止其他事務對該表執行插入、更新和刪除操作,可避免所有并發問題,但性能非常低。
原子性使用的核心技術
Transaction Undo Log來保證數據的原子性。日志的作用能夠在發生錯誤時撤銷之前的全部操作,肯定是需要將之前的操作都記錄下來的,這樣在發生錯誤時才可以回滾。
回滾日志除了能夠在發生錯誤或者用戶執行 ROLLBACK 時提供回滾相關的信息,它還能夠在整個系統發生崩潰、數據庫進程直接被殺死后,當用戶再次啟動數據庫進程時,還能夠立刻通過查詢回滾日志將之前未完成的事務進行回滾,這也就需要回滾日志必須先于數據持久化到磁盤上,是我們需要先寫日志后寫數據庫的主要原因。
一致性使用的核心技術
數據庫一致性(Database Consistency)是指事務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。保證數據庫一致性是指當事務完成時,必須使所有數據都具有一致的狀態。通常需要使用一致性協議來保證例如Paxos、Raft。
隔離性使用的核心技術
鎖、時間戳、MVCC來保證數據的隔離性。
鎖是一種最為常見的并發控制機制,在一個事務中,我們并不會將整個數據庫都加鎖,而是只會鎖住那些需要訪問的數據項,常見數據庫中的鎖都分為兩種,共享鎖(Shared)和互斥鎖(Exclusive),前者也叫讀鎖,后者叫寫鎖。讀鎖保證了讀操作可以并發執行,相互不會影響,而寫鎖保證了在更新數據庫數據時不會有其他的事務訪問或者更改同一條記錄造成不可預知的問題。
時間戳也是實現事務的隔離性的一種方式,使用這種方式實現事務的數據庫,例如 PostgreSQL 會為每一條記錄保留兩個字段;讀時間戳中包括了所有訪問該記錄的事務中的最大時間戳,而記錄行的寫時間戳中保存了將記錄改到當前值的事務的時間戳。使用時間戳實現事務的隔離性時,往往都會使用樂觀鎖,先對數據進行修改,在寫回時再去判斷當前值,也就是時間戳是否改變過,如果沒有改變過,就寫入,否則,生成一個新的時間戳并再次更新數據,樂觀鎖其實并不是真正的鎖機制。
MVCC也是實現事務的隔離性的一種方式,通過維護多個版本的數據,數據庫可以允許事務在數據被其他事務更新時對舊版本的數據進行讀取,很多數據庫都對這一機制進行了實現;因為所有的讀操作不再需要等待寫鎖的釋放,所以能夠顯著地提升讀的性能,MySQL 和 PostgreSQL 都對這一機制進行自己的實現。
持久性使用的核心技術
Transacation Redo Log來保證數據的持久性。日志由兩部分組成,一是內存中的重做日志緩沖區,因為重做日志緩沖區在內存中,所以它是易失的,另一個就是在磁盤上的重做日志文件,它是持久的。
2.9?存儲引擎組件
存儲引擎通常要處理的事情
并發性:某些應用程序比其他應用程序具有很多的顆粒級鎖定要求(如行級鎖定)。
事務支持:并非所有的應用程序都需要事務,但對的確需要事務的應用程序來說,有著定義良好的需求,如ACID兼容等。
引用完整性:通過DDL定義的 外鍵,服務器需要強制保持關聯數據庫的引用完整性。
物理存儲:它包括各種各樣的事項,從表和索引的總的頁大小,到存儲數據所需的格式,到物理磁盤。
索引支持:不同的應用程序傾向于采用不同的索引策略,每種存儲引擎通常有自己的編制索引方法,但某些索引方法(如B-tree索引)對幾乎所有的存儲引擎來說是共同的。
內存高速緩沖:與其他應用程序相比,不同的應用程序對某些內存高速緩沖策略的響應更好,因此,盡管某些內存高速緩沖對所有存儲引擎來說是共同的(如用于用戶連接的高速緩沖,MySQL的高速查詢高速緩沖等),其他高速緩沖策略僅當使用特殊的存儲引擎時才唯一定義。
性能幫助:包括針對并行操作的多I/O線程,線程并發性,數據庫檢查點,成批插入處理等。
其他目標特性:可能包括對地理空間操作的支持,對特定數據處理操作的安全限制等。
二、分布式數據庫架構
分布式數據庫一般由多個管理節點和數據節點組成,分別負責分布式數據庫的運維和數據存儲。相比于單機數據庫,分布式數據庫具有“邏輯統一、物理分散”的特點,邏輯統一是指,從用戶角度看,不論多少個節點組成數據庫的完整功能,對用戶而言,都表現的像是一個單機數據庫;物理分散是指,從實現角度看,分布式的數據庫功能分別由不同的節點完成,由其內部進行自動化的統一調度。邏輯統一的要求和物理分散的實現,決定了在很多產品功能實現上,相較于單機數據庫具有一定的復雜性和技術難度。
目前業界的分布式數據庫產品非常多比如(Oceanbase, Impala, Greenplum, CirroData, SAP HANA)等等。按照目前業界這些分布式數據庫的現狀,技術路線分類如下:
基于開源數據庫 + 中間件:開源單機數據庫(如 mysql 、 postgres 等)已經經過了幾十年的應用,產品功能相對穩定,單機數據處理性能也相對比較高。這種方案的優點是可以利用現有單機數據庫穩定的產品功能,缺點是中間件的功能實現要受限于單機數據庫的功能。當然,也有足夠研究能力的廠商會對單機數據庫進行功能優化和改進,比如 mysql 的主從同步機制、熱點數據訪問等,這對廠商的研發能力和技能儲備要求非常高。
完全自研:公司組建團隊進行產品的自研開發,當然,不可能完全重復造輪子,在實現部分產品功能時可能會采用或者借鑒一些開源軟件,比如 TiDB 的數據存儲使用了 RocksDB 。數據資產是公司最核心的資源,尤其是銀行等金融行業,數據庫不能出現重大問題,但數據庫的產品功能完善需要經過一段時期的生成環境驗證,需要填各種坑。因此,這種方案的優點是天生具有分布式的特性,從設計之初就是針對分布式架構進行設計的,而單機數據庫的很多設計當時還未具備分布式的思維理念,缺點是產品的功能需要經過不同場景、不同數據量和不同行業用戶的檢驗、改進和完善,才能具備成熟度,需要團隊具備相應的應用場景。
目前數據庫產品的業務場景一般分為支持 OLTP(交易性數據庫)、 OLAP(分析性數據庫) 和 HTAP(分析交易混合型數據庫)。目前 OLAP 已經有很多成熟的產品或者大數據開源軟件支持, HTAP 的理念是用一款產品同時解決 OLAP 和 OLTP 的場景。
那么我們來看下分布式數據庫有哪些核心技術
數據分布
單機的縱向擴展能力受主板卡槽等影響存在上限,有單機處理容量和速度的上限,而分布式數據庫則是通過橫向擴展能力來無限提升數據庫處理速度、性能和容量。對于一個數據量很大的表,往往需要將其分布到多個節點進行處理。目前技術趨勢如下:
支持常見的數據分布方式有 hash 、 range 和 list 。MySQL 的語法還有一種 key ,但是可以類似于 hash ,區別在于 key 的 hash 函數由服務器提供。當然,有部分產品只支持其中一種或者兩種。在銀行業,比如銀行卡等部分業務數據還具有一個特征,就是某個字符串的中間部分是具有業務特征,比如可能是省市代碼,如果可以支持對字符串的子串支持多種分布方式會簡化應用開發,但目前幾乎沒有產品支持這個功能。
單表復制。在對分布在多個數據節點的 2 個表進行表連接時,會涉及網絡通訊和大量數據傳輸,會影響性能。比如, A 表和 B 表進行表連接, B 表進行 hash 后保存在四個節點,如果此時在四個節點上均保存一份全量數據 A ,那么可以分別在四個節點完成表連接,然后再進行數據匯總。這種場景成為單表復制。這種表一般是數據量相對較少,數據改動較小。數據量少,是需要單個數據節點可以對其進行處理,數據改動較小是為了降低數據頻繁改動時的性能影響。因為每次修改數據,需要同步修改四個數據節點的數據。
分布式事務
分布式事務是分布式數據庫的重點,也是它的難點。產品的實現方式各不相同,主要有如下兩種流派:
兩階段提交:這種業界最主流的選擇方案,區別在于不同的產品對兩階段的實現方式不同,一種是利用 MySQL 支持的 XA 協議, MySQL 提供了 XA 協議的接口,可以在此基礎上實現,一般用于采用中間件技術路線的產品;一種自己實現 XA 協議,一般用于自研路線的產品。目前這是業界實現主流。
一階段提交 + 事務補償:這種方案設計者一般認為兩階段的成本較高,因此將分布式事務的各個階段分別進行提交,如果某個階段發生異常時,再對已提交的各階段事務進行事務沖正。目前只有個別產品采用這種方案。
不論哪種流派,分布式事務的設計有幾個難點:
分布式事務的異常處理:從正常流程看,哪種方案都看似行得通,無法厚非。但真正設計難點在于分布式的參與節點多,在這個過程中,無論哪個節點都有可能故障,問題在于:無論哪個節點或者階段發生過程,如何保證事務的完整性和數據一致性。
分布式事務的隔離級別:如果對標單機數據庫的四個事務隔離級別,分布式事務完全實現具有很高的難度,所有產品均實現難度不大的已提交讀,部分產品實現了可串行化讀,其它兩個隔離級別實現起來復雜度較高。
分布式事務的性能優化:由于分布式事務在 commit 階段需要處理大量操作,甚至是跨節點的操作,因此,如何區分本地事務和分布式事務,如何優化提升分別式事務,是一個復雜的問題。由于每家產品各不相同,因為不具有通用可總結的規律。
分布式事務的數據多版本控制( MVCC ):Oracle 和 MySQL 均實現了 MVCC 功能。但分布式事務的 MVCC 功能實現具有一定難度,如果結合事務隔離級別,實現難度更大。
數據復制
不同于 DB2 、 Oracle 等數據庫采用增強存儲硬件可靠性,分布式數據庫使用廉價 PC 服務器,它們的特點就是故障率相對比較高。對于一個數百臺機器組成的分布式數據庫時,出現幾臺服務器故障都是正常現象。分布式數據庫一般采用 share nothing 的模型,每個數據節點都采用自己的本地存儲。主要技術特點如下:
為了保證數據的可靠性,必須將數據保存多份,經典的數值是三份:hadoop 中數據也是默認保存三份。這樣,三個節點完全壞掉的可能性非常小,但并非理論上的不可能。對于一些數據安全性要求高的場景,可以保存五份。每多保存一份,就多一份的硬件支出成本,因此需要進行硬件成本和數據安全容忍度的平衡。
為兼顧多個節點的數據安全性和數據寫性能,一般采用超半數同步寫成功的原則。在將數據保存三份或者五份時,在寫數據時,如果只有一個節點寫成功,其它節點采用異步模式,當該節點宕機,其它節點還未寫成功時就會存在數據丟失的可能性;如果等待所有節點寫成功,那么響應時間可能比較長,無法滿足性能要求。因此,采用了折中方法,即超過半數同步寫成功即可。這種思想可以采用 paxos 或者 raft 協議實現。
讀寫分離
在數據存在多份時,會有一個節點作為主節點,其余節點保持與它的同步,稱為從節點。由于半數寫成功原則的存儲,尤其在數據節點比較繁忙的時候,存在部分從節點與主節點不一致的情況。如果所有客戶端的請求均發給主節點,主節點要承擔所有讀寫功能,在高負載的情況下會雪上加霜,造成響應速度很慢。在常用業務場景中,一般都是寫少讀多。因此,對于一些對數據實時性要求不高的業務場景,可以將客戶端的讀請求發給從節點,從而降低從節點的負載。
數據備份恢復
數據的備份恢復是數據庫運維的基本操作。對于運維人員而言,一般是希望通過一個命令操作可以備份所有數據節點的數據,如同單機數據庫備份一樣。但是,因為備份過程需要每個節點的數據庫單獨進行備份,因此,需要保持每個數據節點的備份都是在同一個時間節點的備份快照,這非常重要。
業界常用的解決方法是在備份操作啟動的時間,記錄下整個數據庫的當前最大事務 ID ,比如 LSN ,同時備份數據文件和日志文件。數據文件的備份可以采用物理備份,在備份的過程中可能會產生客戶端請求修改數據的情況,這些修改的操作都已經通過日志文件進行了備份。在進行數據恢復時,首先還原數據文件,然后通過重復日志文件,一直到需要操作的時間點。
容災高可用
傳統單機數據庫的高可用和異地容災,比如 Oracle ,多采用 ADG(active data guard) 和 OGG(oracle golden gate) 的模式進行數據實時同步,但是當主庫發生故障時,切換到備庫。在實時操作過程中,雖然可以進行自動切換,但為了檢查主庫和從庫的一致性,銀行業很多案例都需要進行人工核對,這樣故障恢復就需要一定時間。但是分布式數據庫的多數據副本模式就很好的解決了這個問題。比如三副本情況下,可以將 2 個節點放在本地機房,第三個節點放在異地機房。在正常情況下,進行數據修改時,按照超過半數即為成功的原則,由于本地的 2 個節點網絡時延小,就會很快完成操作并相應客戶端。當發生某個節點故障時,可以自動切換到本地節點的另外一個節點,同時第三個節點還在運行,只要這 2 個節點都寫成功,仍然正常提供服務,此時業務系統相應時間過變長,可以視作服務能力降級,但是不會發生業務系統宕機。對于一些非常重要的系統,甚至可能采用 4+1 ,同城機房有 4 個節點,兩個機房各有 2 個節點,第 5 個節點(即 4+1 中的 1 )在異地機房,這樣,即便本地機房節點故障發生 1 個節點故障,不會服務降級。
三、SMP VS MPP
SMP(Symmetric Multi-Processor)系統內有許多緊耦合多處理器,在這樣的系統中,所有的CPU共享全部資源,如總線,內存和I/O系統等;
所謂對稱多處理器結構,是指服務器中多個 CPU 對稱工作,無主次或從屬關系。各 CPU 共享相同的物理內存,每個 CPU 訪問內存中的任何地址所需時間是相同的,因此 SMP 也被稱為一致存儲器訪問結構 (UMA :Uniform Memory Access) 。對 SMP 服務器進行擴展的方式包括增加內存、使用更快的 CPU 、增加 CPU 、擴充 I/O( 槽口數與總線數 ) 以及添加更多的外部設備 ( 通常是磁盤存儲 ) 。
主要特征是共享,系統中所有資源 (CPU 、內存、 I/O 等 ) 都是共享的。也正是由于這種特征,導致了
SMP 服務器的主要問題,那就是它的擴展能力非常有限。對于 SMP 服務器而言,每一個共享的環節都可能造成 SMP 服務器擴展時的瓶頸,而最受限制的則是內存。由于每個 CPU 必須通過相同的內存總線訪問相同的內存資源,因此隨著 CPU 數量的增加,內存訪問沖突將迅速增加,最終會造成 CPU 資源的浪費,使 CPU 性能的有效性大大降低。實驗證明, SMP 服務器 CPU 利用率最好的情況是 2 至 4 個 CPU 。
MPP(Massive Parallel Processing)由多個 SMP 服務器通過一定的節點互聯網絡進行連接,協同工作,完成相同的任務,從用戶的角度來看是一個服務器系統。其基本特征是由多個 SMP 服務器 ( 每個 SMP 服務器稱節點 ) 通過節點互聯網絡連接而成,每個節點只訪問自己的本地資源 ( 內存、存儲等 ) ,是一種完全無共享 (Share Nothing) 結構。
既然有兩種結構,那它們各有什么特點呢?采用什么結構比較合適呢?通常情況下,MPP系統因為要在不同處理單元之間傳送信息,所以它的效率要比SMP要差一點,但是這也不是絕對的,因為MPP系統不共享資源,因此對它而言,資源比SMP要多,當需要處理的事務達到一定規模時,MPP的效率要比SMP好。這就是看通信時間占用計算時間的比例而定,如果通信時間比較多,那MPP系統就不占優勢了,相反,如果通信時間比較少,那MPP系統可以充分發揮資源的優勢,達到高效率。當前使用的OTLP程序中,用戶訪問一個中心數據庫,如果采用SMP系統結構,它的效率要比采用MPP結構要快得多。而MPP系統在決策支持和數據挖掘方面顯示了優勢,可以這樣說,如果操作相互之間沒有什么關系,處理單元之間需要進行的通信比較少,那采用MPP系統就要好,相反就不合適了。
四、資源訪問方式
Shared Everthting:一般是針對單個主機,完全透明共享CPU/MEMORY/IO,并行處理能力是最差的,典型的代表SQLServer
Shared Disk:各個處理單元使用自己的私有 CPU和Memory,共享磁盤系統。典型的代表Oracle Rac, 它是數據共享,可通過增加節點來提高并行處理的能力,擴展能力較好。其類似于SMP(對稱多處理)模式,但是當存儲器接口達到飽和的時候,增加節點并不能獲得更高的性能 。
Shared Nothing:各個處理單元都有自己私有的CPU/內存/硬盤等,不存在共享資源,類似于MPP(大規模并行處理)模式,各處理單元之間通過協議通信,并行處理和擴展能力更好。典型代表DB2 DPF和Hadoop ,各節點相互獨立,各自處理自己的數據,處理后的結果可能向上層匯總或在節點間流轉。
我們常說的 Sharding 其實就是Share Nothing架構,它是把某個表從物理存儲上被水平分割,并分配給多臺服務器(或多個實例),每臺服務器可以獨立工作,具備共同的schema,比如MySQL Proxy和Google的各種架構,只需增加服務器數就可以增加處理能力和容量。
Shared nothing架構(shared nothing architecture)是一 種分布式計算架構。這種架構中的每一個節點( node)都是獨立、自給的,而且整個系統中沒有單點競爭。
04
—
結論
前幾年大數據時代剛來臨的時候,Hadoop分布式組件應運而生,Hadoop有三大組件HDFS、MapReduce、Yarn,HDFS的作用是分布式的存儲,來提高容災和高可用,MapReduce來提供分布式計算,Yarn用來做集群的資源調度和資源整合。于是業界就產生了一個說法,叫做”數據庫已死“,數據庫領域會被改朝換代。存儲、計算、調度通過Hadoop組件都可以辦到,那么我們還用數據庫做什么呢?經過時間的證明OLTP還是OLAP或者HTAP,開源數據庫與商業數據庫都存在巨大的功能和性能鴻溝。開源數據庫雖然廣泛應用在互聯網等場景,但是傳統的企業用戶,無論是金融、保險、醫療、電信、等等,還是高度依賴商業數據庫?;ヂ摼W高數據量、高性能、高并發、擴展性、軟件成本等等的限制條件。數據庫的重要性越來越重要。上文只是講了數據庫中會用到什么要的技術,后續會對于每一個技術進行詳細講解。
參考資料
1. https://baike.baidu.com/item/分布式數據庫系統
2. MySQL的多存儲引擎架構
3. MySQL 架構及優化原理
4. 全面講解分布式數據庫架構設計特點
5. 李飛飛:如何看待數據庫的未來?
6. 《分布式系統:概念與設計(第3版)》
歡迎大家加入極客星球,選擇圈子很重要,付費可以提供更好服務,以小博大,極客星球絕對是學習基礎知識,訓練基本功,扎實基本功, 提高核心基礎技術好地方。
詳細了解,公眾號菜單 或者 :極客星球
- END -
看完一鍵三連在看,轉發,點贊
是對文章最大的贊賞,極客重生感謝你
推薦閱讀
直播精彩分享
今年你參與開源了嗎?
基本功為什么如此重要!
總結
以上是生活随笔為你收集整理的深入理解数据库核心技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 今年你参与开源了吗?
- 下一篇: SQL 学习最强刷题网站!