1. 程式人生 > >循序漸進:Oracle 12c新特性Sharding技術解讀

循序漸進:Oracle 12c新特性Sharding技術解讀

引言

資料庫構架設計中主要有 Shared Everthting、Shared Nothing 和 Shared Disk:

  • Shared Everthting:一般是針對單個主機,完全透明共享 CPU/MEMORY/IO,並行處理能力是最差的,例如 Oracle 的單機模式。

  • Shared Disk:各個處理單元使用自己的私有 CPU和 Memory,共享磁碟系統。典型的代表 Oracle RAC, 它是資料共享,可通過增加節點來提高並行處理的能力,擴充套件能力較好。其類似於 SMP(對稱多處理)模式,但是當儲存器介面達到飽和的時候,增加節點並不能獲得更高的效能 。

  • Shared Nothing:各個處理單元都有自己私有的 CPU / 記憶體 / 硬碟等,不存在共享資源,類似於 MPP(大規模並行處理)模式,各處理單元之間通過協議通訊,並行處理和擴充套件能力更好。 各節點相互獨立,各自處理自己的資料,處理後的結果可能向上層彙總或在節點間流轉。

我們常說的 Sharding 其實就是 Share Nothing 架構,它是把某個表從物理儲存上被水平分割,並分配給多臺伺服器(或多個例項),每臺伺服器可以獨立工作,具備共同的 schema,只需增加伺服器數就可以增加處理能力和容量。

Oracle Sharding 簡介

Oracle Sharding 是 Oracle 12.2 版本推出的新功能,也稱為資料分片,適用於 online transaction processing (OLTP)。Oracle Sharding 基於表分割槽技術,是一種在資料層將資料水平分割槽儲存到不同的資料庫的技術。Sharding 可以實現將一個分割槽表的不同分割槽儲存在不同的資料庫中,每個資料庫位於不同的伺服器,每一個數據庫都稱為shard,這些 shard 組成一個邏輯資料庫,稱為 sharded database (SDB)。這個 table 也稱為 sharded table,每個 shard 資料庫中儲存該表的不同資料集(按照 sharding key 分割槽),但是他們有相同的列 (columns)。

Shard 是一種 shared-nothing 技術,每個 shard 資料庫使用獨立的伺服器硬體 (CPU、記憶體等)。Shard 可以執行在單機資料庫或者 DATAGUARD / ADG 資料庫。

Sharding 其實需要解決三個問題:

  1. 資料的路由

    資料路由是資料庫告訴應用程式,你讓我查的資料目前在哪個分片上,這條路怎麼走過去。

  2. 資料的分片

    資料分片就是實際資料的存放地點,往往每個分片就是一臺單獨的伺服器(含儲存)。

  3. 分片的元資料資訊儲存

    由於分片的資料實際是被切割放在不同的機器上,那麼需要有個集中的地點存放資料分片的資訊,即分片元資料的資訊。

    IMG_6040.png

Oracle Sharding 組成

Oracle Sharding 主要包括下面元件:

  • Sharded database (SDB):邏輯上 SDB 是一個數據庫,但是物理上SDB包括多個物理獨立的資料庫,SDB 類似一個數據庫池 (pool),資料庫池 (pool) 中包括多個數據庫 (Shard)。目前版本最大支援1000個 shard。

  • Shards:SDB 包括多個物理獨立的資料庫,每一個數據庫都稱為shard,每個 shard 資料庫位於不同的伺服器,他們不共享 CPU、記憶體、儲存等資源。每個shard 資料庫中儲存表的不同資料集, 但是每個 shard 中都有相同的列(columns)。Shard 資料庫可以是 Dataguard / ADG,提供高可用性,Shard 資料庫(單機或者 ADG)可以通過 GSM deploy 來自動建立,也可以將一個已經通過 dbca 建立好的資料庫 add 到 SDB。

  • Shard catalog:是一個 Oracle 資料庫,用於集中儲存管理 SDB 配置資訊,是 SDB 的核心。SDB 配置變化,比如新增/刪除 shard,Globalservice 等等,都記錄在 Shard catalog。如果應用查詢多個 shard 中的資料,那麼由 Shard catalog統一協調分配。我們推薦將 Shard catalog 配置為 dataguard 環境,這樣可以提供 HA 高可用。如果 Shard catalog 無法訪問,那麼只會影響一些維護操作和跨shard訪問,而不會影響單獨的 shard 操作(通過 sharding key 的查詢 /DML)。

  • Shard directors:Global Data Service (GDS) 實現對 Sharding 的集中部署和管理。GSM 是 GDS 的核心元件。GSM 作為 Shard director。GSM 類似於監聽器,將客戶端對 SDB 的請求路由到對應的 shard,負載均衡客戶端的訪問。

  • Shardgroup:在邏輯上,將一組相同複製屬性的 shard 稱作 shard group。如有8臺主機,其中4臺是 shard node 的 primary,另外4臺是 shard node 的 standby。那麼,我們可以把4臺 primary 定義成一個shardgroup,叫 primary_shardgroup,另外4臺 standby 定義成另外一個shardgroup,叫 standby_shardgroup。

    注:一個 shardgroup 通常是在一個 datacenter 內。

    Dataguard 可以級聯,那麼我們可以把 primary 做為一個 shardgroup1,第一級的 dataguard 叫 shardgroup2,第二級的 dataguard 叫 shardgroup2。如下:

  • IMG_6041.png

  • shardspace shardspace 的概念伴隨著綜合性分片的分片方法(compositesharding method)出現的;如果是系統管理分片方法(system-managed shardingmethod),只有一個預設的 shardspace。所以只有在 compositesharding 下,才有可能出現多個 shardspace。

在 composite sharding 下,資料首先根據 list 或者 range,分成若干個shardspace。然後再根據一致性 hash 進行分片。

注:每個 shardspace 包含一個或者多個複製 shard for HA/DR。

IMG_6042.jpg

我們可以按照服務級別來劃分 shardspace,如硬體好的,作為 shardspace_gold,硬體差一些的,劃做 shardspace_silver:

IMG_6043.png

Oracle Sharding 方法

Oracle Sharding 支援3種方法 shard / 分片方法:

  • System-Managed Sharding:這種方法使用者不用指定資料存放在哪個 shard 中。Sharding 通過一致性雜湊 (CONSISTENT HASH) 方法將資料分割槽 (partitioning),並自動分佈在不同的 Shard。System-managed sharding 只能有一個shardspace。

    IMG_6044.png

  • Composite Sharding:這種方法使用者建立多個 shardspaces ,每個 shardspaces 中存放一定範圍 (range) 或者列表 (list) 的資料。一般情況下,Shardspace 按照區域來劃分,比如美國區域的 shard 屬於 shardspace cust_america,歐洲的 shard 屬於 shardspace cust_europe。

  • Subpartitions with Sharding:Sharding 基於表分割槽,因此子分割槽 (Subpartitions) 技術同樣適用於 Sharding

Oracle Sharding 物件

被 Shard/分片的表我們成為 shardedtable,這些 sharded table 的集合稱為表家族(TableFamily)。

所謂表家族(Table Family)就是指 sharded table 之間是父-子關係,一個表家族(Table Family)中沒有任何父表的表叫做根表(root table),每個表家族中只能有一個根表。

在12.2,在一個 SDB 中只支援一個表家族。

在表家族(Table Family)中的所有 sharded table 都按照相同的 sharding key (主鍵)來分片,主要是由 root table 的 shardingkey 決定的。表家族(Table Family)中有相同 shardingkey 的資料儲存在同一個 Chunk 中,這樣方便以後的資料移動。

比如: 使用者表 – 訂單表 – 訂單明細表 就是一個表家族,其中使用者表是 root table,訂單表和訂單明細表分別是子表,他們都按照 sharding key (CustNo ) 分割槽。

IMG_6045.png

可以通過如下兩種方式建立 table family:

通過CONSTRAINT [FK_name] FOREIGN KEY(FK_column) REFERENCES [R_table_name]([R_table_column]) —這種關係可以有級聯關係。

SQL> CREATE  SHARDED TABLE Customers

  2  (

  3  CustId  VARCHAR2(60) NOT NULL,

  4  FirstName  VARCHAR2(60),

  5  LastName  VARCHAR2(60),

  6  Class  VARCHAR2(10),

  7  Geo  VARCHAR2(8),

  8  CustProfile  VARCHAR2(4000),

  9  Passwd  RAW(60),

10  CONSTRAINT  pk_customers PRIMARY KEY (CustId),

11  CONSTRAINT  json_customers CHECK (CustProfile IS JSON)

12  )  TABLESPACE SET TSP_SET_1

13  PARTITION  BY CONSISTENT HASH (CustId) PARTITIONS AUTO;

可以看到上面根表(root table)是 customer 表,主鍵是 CustId,partition 是根據 CONSISTENT HASH,對 CustId 進行分割槽;

下一級的表是 order 表,主鍵是 CustId+OrderId,外來鍵是 CustId 且 references Customers 表,partition 是參考外來鍵;

SQL> CREATE  SHARDED TABLE Orders

  2  (

  3  OrderId  INTEGER NOT NULL,

  4  CustId  VARCHAR2(60) NOT NULL,

  5  OrderDate  TIMESTAMP NOT NULL,

  6  SumTotal  NUMBER(19,4),

  7  Status  CHAR(4),

  8  constraint  pk_orders primary key (CustId, OrderId),

  9  constraint  fk_orders_parent foreign key (CustId)

10  references  Customers on delete cascade

11  ) partition  by reference (fk_orders_parent);

再下一級表是 LineItems 表,主鍵是 CustId+OrderId+ProductId,外來鍵是 CustId+OrderId,即上一層表達主鍵,partition 是參考外來鍵

SQL> CREATE  SHARDED TABLE LineItems

  2  (

  3  OrderId  INTEGER NOT NULL,

  4  CustId  VARCHAR2(60) NOT NULL,

  5  ProductId  INTEGER NOT NULL,

  6  Price  NUMBER(19,4),

  7  Qty  NUMBER,

  8  constraint  pk_items primary key (CustId, OrderId, ProductId),

  9  constraint  fk_items_parent foreign key (CustId, OrderId)

10  references  Orders on delete cascade

11  )  partition by reference (fk_items_parent);

方法2:同關鍵字 PARENT 來顯式的說明父子關係。這種關係只有父子一層關係,不能級聯。

SQL>  CREATE  SHARDED TABLE Customers

2  (  CustNo NUMBER NOT NULL

3  , Name  VARCHAR2(50)

4  ,  Address VARCHAR2(250)

5  ,  region VARCHAR2(20)

6  , class  VARCHAR2(3)

7  ,  signup DATE

8  )

9  PARTITION  BY CONSISTENT HASH (CustNo)

10 TABLESPACE SET  ts1

11 PARTITIONS AUTO

12 ;

SQL> CREATE  SHARDED TABLE  Orders          

2  (  OrderNo  NUMBER                      

3  ,  CustNo  NUMBER                      

4  ,  OrderDate  DATE                      

5  )                                    

6  PARENT  Customers                      

7  PARTITION  BY CONSISTENT HASH (CustNo)

8  TABLESPACE  SET  ts1                    

9  PARTITIONS  AUTO                      

10 ;

SQL> CREATE  SHARDED TABLE LineItems

2  (  LineNo NUMBER

3  ,  OrderNo NUMBER

4  ,  CustNo NUMBER

5  ,  StockNo NUMBER

6  ,  Quantity NUMBER

7  )

8  PARENT  Customers

9  PARTITION  BY CONSISTENT HASH (CustNo)

10 TABLESPACE SET  ts1

11 PARTITIONS AUTO

12 ;

  • 注意上面的 order 表和 LineItems 表,都是屬於同一個父表,即 customers 表。

  • 另外,也注意上面的 CustNo 欄位,在每個表中都是有的。而上面說的第一種的級聯關係的 tablefamily,可以不在每個表中都存在 CustNo 欄位。

上面建立在表,都是 sharded table,即表的各個分割槽,可以分佈在不同的 shard node 上。各個 shard node 上的分割槽,是不同的。即整個表的內容,是被切割成片,分配在不同的機器上的。

而 duplicatedtable,是整個表達同樣內容,在各個機器上是一樣的。duplicate table 在各個 shard node上,是以 read only mv 的方式呈現:在 shardcat 中,存在 mast table;在各個shard中,存在 read only mv。duplicated table 的同步:以物化檢視的方式同步。

IMG_6046.png

chunk

chunk 的概念和 table family 密不可分。因為 family 之間的各個表都是有關係的,我們把某個 table family 的一組分割槽稱作一個 chunk。

如 customers 表中的1號~100萬號客戶資訊在一個分割槽中;在 order 表中,也有1號~100萬號的客戶的 order 資訊,也在一個分割槽中;另外 LineItems 表中的1號~100萬號客戶的明細資訊,也在一個分割槽中,我們希望這些相關的分割槽,都是在一個 shard node 中,避免 cross shard join。所以,我們把這些在同一個 table family 內,相關的分割槽叫做 chunk。在進行 re-sharding 的時候,是以 chunk 為單位進行移動。因此可以避免 cross shard join。

IMG_6047.png

注:chunk 的數量在 CREATESHARDCATALOG 的指定,如果不指定,預設值是每個shard 120個chunk

chunk move

chunk move 的條件:

  1. re-sharding 發生,即當 shard 的數量發生改變的時候,會發生 chunk move。 注:re-sharding 之後,chunk 的數雖然平均,但並不連續。

    如:原來是2個 shard,1~6號 chunk在 shard 1,7~12號 chunk 在 shard2。加多一個 shard 後,1~4號 chunk 在 shard 1,7~10號 chunk 在 shard 2,那麼5~6,11~12號 chunk 在 shard 3 上。即:總是挪已經存在的 shard node 上的後面部分 chunk。

  2. DBA 手工發起:move chunk-chunk 7 -source sh2 -target sh1。將 chunk 7 從 shard node sh2 上,挪到 shard node sh1 上。

chunk move 的過程:

在 chunk migration 的時候,chunk 大部分時間是 online 的,但是期間會有幾秒鐘的時間 chunk 中的 data 處於 read-only 狀態。  

chunk migration 的過程就是綜合利用 rman 增量備份和 TTS 的過程: level 0 備份源 chunk 相關的 TS,還原到新 shard->開始 FAN(等待幾秒)->將源 chunk 相關的 TS 置於 read-only->level 1 備份還原->chunk up(更新 routing table 連新 shard)->chunk down(更新 routing table 斷開源 shard)->結束 FAN(等待幾秒)->刪除原 shard 上的老 chunk

Oracle Sharding 路由選擇(Routing)

--直接路由 應用程式初始化時,在應用層/中介軟體層建立連線池,連線池獲取所有 shard 節點的sharding key 範圍,並且儲存在連線池中,形成 shard topologycache(拓撲快取),Cache 提供了一個快速的方法直接將請求路由到具體的 shard。

客戶端請求時指定 shard key,直接從連線池獲取連線,這種情況下不經過 shard  director / catalog 資料庫,直接連線到對應的 shard。  

--代理路由 如果客戶端執行 select 或者DML 時不指定 shard key 或者執行聚合操作(比如groupby),那麼請求傳送到 Catalog 資料庫,根據 matadata 資訊,SQL 編譯器決定訪問哪些 shards。

為了實現 sharding,Oracle 在連線池和驅動方面都做了增強,提供了新的 API(UCP, JDBC, OCI 等等)在連線建立時來傳遞 sharding keys。

Sharding 技術的優點和缺點

  • 增加了 SQL 的複雜性

    因為開發人員必須要寫更復雜的 SQL 來處理 sharding 的邏輯。

  • Sharding 本身帶來的複雜性

    sharding 軟體需要照顧分割槽,資料平衡, 訪問協調,資料完整性

  • 單點故障

    一個 shard 損壞可能導致整張表不可訪問。失效接管伺服器也更復雜。因為負責失效接管的伺服器必須擁有任何可能損壞的 shard 上的資料。

  • 備份也更復雜

    多個 shard 可能都需要同時備份。

  • 維護也更復雜

    比如增加刪除索引,增減刪除欄位,修改表定義等等,都變得更困難

  • 商業 sharding 技術隨著節點數的增加,Licensing 費用也會大規模增加

在 Oracle12.2 Sharding 中都無需擔心,Oracle 作為一個商業資料庫,已通過底層開發規避了這些問題。

單點故障問題可以通過 RAC+Sharding,ADG+Sharding 來規避,但成本也會增加。

Oracle Sharding 技術提供線性擴充套件和失敗隔離的優點

  • 線性擴充套件

    因為每個 shard 是一個獨立的資料庫,通過增加新的 Shard 節點,來線性擴充套件效能。自動 rebalance 資料。

  • 失敗隔離

    由於 Shard 是一種 shared-nothing 技術,每個 shard 使用獨立的硬體,因此一個 shard 節點出現故障,只會影響到這個 shard 存放的資料,而不會影響到其他shard。

  • 按照地理位置分佈資料

    可以選擇根據地理位置不同,將資料儲存在不同的 shard。

  • 滾動升級

    選擇不同時間升級不同的 shard。比如同一時間只升級一個或一部分 shard,那麼只有這些升級的 shard 中儲存的資料受到影響,其他的 shard 不受到影響,可以繼續提供服務。

  • 雲部署

    Shard 非常適合部署在 cloud